UNPKG

3.95 kBJavaScriptView Raw
1/* eslint-disable no-param-reassign */
2/** @typedef {import('./types').SpaOptions} SpaOptions */
3/** @typedef {import('polyfills-loader').PolyfillsLoaderConfig} PolyfillsLoaderConfig */
4
5const merge = require('deepmerge');
6const html = require('@open-wc/rollup-plugin-html');
7const polyfillsLoader = require('@open-wc/rollup-plugin-polyfills-loader');
8const path = require('path');
9const { generateSW } = require('rollup-plugin-workbox');
10const { createBasicConfig } = require('./createBasicConfig');
11const { pluginWithOptions, applyServiceWorkerRegistration, isFalsy } = require('./utils');
12const { defaultPolyfills } = require('./polyfills');
13
14/**
15 * @param {SpaOptions} options
16 */
17function createSpaConfig(options) {
18 const basicConfig = createBasicConfig(options);
19
20 /** @type {SpaOptions} */
21 const userOptions = merge(
22 {
23 html: true,
24 polyfillsLoader: true,
25 workbox: true,
26 injectServiceWorker: false,
27 },
28 options,
29 );
30 let outputDir = basicConfig.output.dir;
31
32 if (userOptions.rootDir) {
33 if (typeof userOptions.html === 'boolean' && userOptions.html) {
34 userOptions.html = {
35 rootDir: userOptions.rootDir,
36 };
37 }
38 if (typeof userOptions.html === 'object') {
39 userOptions.html.rootDir = userOptions.rootDir;
40 }
41 }
42
43 const applySw = (htmlString, transformOptions) =>
44 applyServiceWorkerRegistration(htmlString, transformOptions, userOptions, outputDir);
45
46 const htmlPlugin = pluginWithOptions(html, userOptions.html, {
47 minify: !userOptions.developmentMode,
48 transform: [userOptions.injectServiceWorker && applySw].filter(isFalsy),
49 inject: false,
50 });
51
52 let polyfillsLoaderConfig = {
53 polyfills: {},
54 minify: !userOptions.developmentMode,
55 };
56
57 if (userOptions.legacyBuild) {
58 if (!htmlPlugin) {
59 throw new Error('Cannot generate multi build outputs when html plugin is disabled');
60 }
61 outputDir = basicConfig.output[0].dir;
62
63 basicConfig.output[0].plugins.push(htmlPlugin.addOutput('module'));
64 basicConfig.output[1].plugins.push(htmlPlugin.addOutput('nomodule'));
65 polyfillsLoaderConfig = {
66 modernOutput: {
67 name: 'module',
68 type: 'module',
69 },
70 legacyOutput: {
71 name: 'nomodule',
72 type: 'systemjs',
73 test:
74 // test if browser supports dynamic imports (and thus modules). import.meta.url cannot be tested
75 "(function(){try{Function('!function(){import(_)}').call();return false;}catch(_){return true}})()",
76 },
77 minify: !userOptions.developmentMode,
78 polyfills: defaultPolyfills,
79 };
80 }
81
82 const workboxPlugin = pluginWithOptions(
83 generateSW,
84 userOptions.workbox,
85 {
86 // Keep 'legacy-*.js' just for retro compatibility
87 globIgnores: ['polyfills/*.js', 'legacy-*.js', 'nomodule-*.js'],
88 navigateFallback: '/index.html',
89 // where to output the generated sw
90 swDest: path.join(process.cwd(), outputDir, 'sw.js'),
91 // directory to match patterns against to be precached
92 globDirectory: path.join(process.cwd(), outputDir),
93 // cache any html js and css by default
94 globPatterns: ['**/*.{html,js,css,webmanifest}'],
95 skipWaiting: true,
96 clientsClaim: true,
97 runtimeCaching: [
98 {
99 urlPattern: 'polyfills/*.js',
100 handler: 'CacheFirst',
101 },
102 ],
103 },
104 () => {},
105 );
106
107 if (userOptions.workbox) {
108 if (basicConfig.output.length > 1) {
109 const lastOutput = basicConfig.output.length - 1;
110 basicConfig.output[lastOutput].plugins.push(workboxPlugin);
111 } else {
112 basicConfig.output.plugins.push(workboxPlugin);
113 }
114 }
115
116 return merge(basicConfig, {
117 plugins: [
118 // create HTML file output
119 htmlPlugin,
120
121 // inject polyfills loader into HTML
122 pluginWithOptions(polyfillsLoader, userOptions.polyfillsLoader, polyfillsLoaderConfig),
123 ],
124 });
125}
126
127module.exports = { createSpaConfig };