Skip to content

Commit

Permalink
refactor: use Vite official API for building sw.js (#20894) (#20910)
Browse files Browse the repository at this point in the history
* fix: fix service worker build

* fix PwaTestIT

* exclude sw.js from manifest

* generate service worker at closeBundle stage

* clean up service worker build config

* generate service worker at different stages depending on mode

* do not use lib mode to allow for minification in es format

* clean up plugin code

* add inlineDynamicImports: true option

* revert some changes to minimize diff

* add exports option for backward compatibility

---------

Co-authored-by: Sergey Vinogradov <mr.vursen@gmail.com>
Co-authored-by: Teppo Kurki <teppo.kurki@vaadin.com>
  • Loading branch information
3 people authored Jan 24, 2025
1 parent d4af414 commit 1db7c36
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 72 deletions.
109 changes: 38 additions & 71 deletions flow-server/src/main/resources/vite.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import settings from '#settingsImport#';
import {
AssetInfo,
ChunkInfo,
build,
defineConfig,
mergeConfig,
OutputOptions,
PluginOption,
ResolvedConfig,
InlineConfig,
UserConfigFn
} from 'vite';
import { getManifest, type ManifestTransform } from 'workbox-build';

import * as rollup from 'rollup';
import brotli from 'rollup-plugin-brotli';
import replace from '@rollup/plugin-replace';
import checker from 'vite-plugin-checker';
import postcssLit from '#buildFolder#/plugins/rollup-plugin-postcss-lit-custom/rollup-plugin-postcss-lit.js';

Expand Down Expand Up @@ -106,7 +106,7 @@ function injectManifestToSWPlugin(): rollup.Plugin {
const { manifestEntries } = await getManifest({
globDirectory: buildOutputFolder,
globPatterns: ['**/*'],
globIgnores: ['**/*.br', 'pwa-icons/**'],
globIgnores: ['**/*.br', 'pwa-icons/**', 'sw.js'],
manifestTransforms: [rewriteManifestIndexHtmlUrl],
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024 // 100mb,
});
Expand All @@ -118,87 +118,54 @@ function injectManifestToSWPlugin(): rollup.Plugin {
}

function buildSWPlugin(opts: { devMode: boolean }): PluginOption {
let config: ResolvedConfig;
let buildConfig: InlineConfig;
const devMode = opts.devMode;

const swObj: { code?: string, map?: rollup.SourceMap | null } = {};

async function build(action: 'generate' | 'write', additionalPlugins: rollup.Plugin[] = []) {
const includedPluginNames = [
'vite:esbuild',
'rollup-plugin-dynamic-import-variables',
'vite:esbuild-transpile',
'vite:terser'
];
const plugins: rollup.Plugin[] = config.plugins.filter((p) => {
return includedPluginNames.includes(p.name);
});
const resolver = config.createResolver();
const resolvePlugin: rollup.Plugin = {
name: 'resolver',
resolveId(source, importer, _options) {
return resolver(source, importer);
}
};
plugins.unshift(resolvePlugin); // Put resolve first
plugins.push(
replace({
values: {
'process.env.NODE_ENV': JSON.stringify(config.mode),
...config.define
},
preventAssignment: true
})
);
if (additionalPlugins) {
plugins.push(...additionalPlugins);
}
const bundle = await rollup.rollup({
input: path.resolve(settings.clientServiceWorkerSource),
plugins
});

try {
return await bundle[action]({
file: path.resolve(buildOutputFolder, 'sw.js'),
format: 'es',
exports: 'none',
sourcemap: config.command === 'serve' || config.build.sourcemap,
inlineDynamicImports: true
});
} finally {
await bundle.close();
}
}

return {
name: 'vaadin:build-sw',
enforce: 'post',
async configResolved(resolvedConfig) {
config = resolvedConfig;
async configResolved(viteConfig) {
buildConfig = {
base: viteConfig.base,
root: viteConfig.root,
mode: viteConfig.mode,
resolve: viteConfig.resolve,
define: {
...viteConfig.define,
'process.env.NODE_ENV': JSON.stringify(viteConfig.mode),
},
build: {
minify: viteConfig.build.minify,
outDir: viteConfig.build.outDir,
sourcemap: viteConfig.command === 'serve' || viteConfig.build.sourcemap,
emptyOutDir: false,
modulePreload: false,
rollupOptions: {
input: {
sw: settings.clientServiceWorkerSource
},
output: {
exports: 'none',
entryFileNames: 'sw.js',
inlineDynamicImports: true,
},
},
},
};
},
async buildStart() {
if (devMode) {
const { output } = await build('generate');
swObj.code = output[0].code;
swObj.map = output[0].map;
}
},
async load(id) {
if (id.endsWith('sw.js')) {
return '';
}
},
async transform(_code, id) {
if (id.endsWith('sw.js')) {
return swObj;
await build(buildConfig);
}
},
async closeBundle() {
if (!devMode) {
await build('write', [injectManifestToSWPlugin(), brotli()]);
await build({
...buildConfig,
plugins: [injectManifestToSWPlugin(), brotli()]
});
}
}
},
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void testPwaResources() throws IOException {
Assert.assertTrue(
"Expected sw-runtime-resources-precache.js to be imported, but was not",
serviceWorkerJS.contains(
"importScripts(\"sw-runtime-resources-precache.js\");"));
"importScripts(\"sw-runtime-resources-precache.js\")"));

serviceWorkerUrl = getRootURL() + "/sw-runtime-resources-precache.js";
serviceWorkerJS = readStringFromUrl(serviceWorkerUrl);
Expand Down

0 comments on commit 1db7c36

Please sign in to comment.