Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use Vite official API for building sw.js #20894

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
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'],
Copy link
Contributor Author

@vursen vursen Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: Added this line to prevent sw.js from being included in the manifest when the production bundle is built after the development bundle. Previously, this didn't happen because sw.js existed only virtually in dev mode.

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',
Copy link
Contributor Author

@vursen vursen Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: This option is untested, but that can be addressed separately since it's coming from the previous config.

entryFileNames: 'sw.js',
inlineDynamicImports: true,
Copy link
Contributor Author

@vursen vursen Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: This option is untested, but that can be addressed separately since it's coming from the previous config.

},
},
},
};
},
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
Loading