8000 refactor: extract service worker plugin into internal package (#21298) · vaadin/flow@b9603d5 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit b9603d5

Browse files
vursenplatosha
andauthored
refactor: extract service worker plugin into internal package (#21298)
* refactor: extract service worker plugin * update test * run formatter * fix: compatibility with Hilla endpoints * fix: resolve /sw.js request * rename plugin, use TS --------- Co-authored-by: Anton Platonov <platosha@gmail.com> Co-authored-by: Anton Platonov <anton@vaadin.com>
1 parent cdaa758 commit b9603d5

File tree

5 files changed

+146
-96
lines changed

5 files changed

+146
-96
lines changed

flow-server/src/main/resources/plugins/plugins.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"theme-loader",
66
"theme-live-reload-plugin",
77
"rollup-plugin-postcss-lit-custom",
8-
"react-function-location-plugin"
8+
"react-function-location-plugin",
9+
"vite-plugin-service-worker"
910
]
1011
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/// <reference types="node" />
2+
import { resolve } from 'node:path';
3+
import type { RollupOutput } from 'rollup';
4+
import { build, InlineConfig, Plugin } from 'vite';
5+
import { getManifest, ManifestTransform } from 'workbox-build';
6+
import brotli from 'rollup-plugin-brotli';
7+
8+
const APP_SHELL_URL = '.';
9+
10+
function injectManifestToSWPlugin({ outDir }: { outDir: string }): Plugin {
11+
const rewriteManifestIndexHtmlUrl: ManifestTransform = (manifest) => {
12+
const indexEntry = manifest.find((entry) => entry.url === 'index.html');
13+
if (indexEntry) {
14+
indexEntry.url = APP_SHELL_URL;
15+
}
16+
17+
return { manifest, warnings: [] };
18+
};
19+
20+
return {
21+
name: 'vaadin:inject-manifest-to-sw',
22+
async transform(code, id) {
23+
if (/sw\.(ts|js)$/.test(id)) {
24+
const { manifestEntries } = await getManifest({
25+
67E6 globDirectory: outDir,
26+
globPatterns: ['**/*'],
27+
globIgnores: ['**/*.br', 'pwa-icons/**'],
28+
manifestTransforms: [rewriteManifestIndexHtmlUrl],
29+
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024 // 100mb,
30+
});
31+
32+
return code.replace('self.__WB_MANIFEST', JSON.stringify(manifestEntries));
33+
}
34+
35+
return;
36+
}
37+
};
38+
}
39+
40+
/**
41+
* Internal Vite plugin that builds the service worker. Not intended for public use.
42+
*
43+
* @private
44+
*/
45+
export default function serviceWorkerPlugin({ srcPath }: { srcPath: string }): Plugin {
46+
let buildConfig: InlineConfig;
47+
let buildOutput: RollupOutput;
48+
let swSourcePath = resolve(srcPath);
49+
50+
return {
51+
name: 'vaadin:build-sw',
52+
enforce: 'post',
53+
async configResolved(viteConfig) {
54+
buildConfig = {
55+
base: viteConfig.base,
56+
root: viteConfig.root,
57+
mode: viteConfig.mode,
58+
resolve: viteConfig.resolve,
59+
define: {
60+
...viteConfig.define,
61+
'process.env.NODE_ENV': JSON.stringify(viteConfig.mode),
62+
'globalThis.document': undefined,
63+
},
64+
build: {
65+
write: viteConfig.mode !== 'development',
66+
minify: viteConfig.build.minify,
67+
outDir: viteConfig.build.outDir,
68+
target: viteConfig.build.target,
69+
sourcemap: viteConfig.command === 'serve' || viteConfig.build.sourcemap,
70+
emptyOutDir: false,
71+
modulePreload: false,
72+
rollupOptions: {
73+
input: {
74+
sw: swSourcePath,
75+
},
76+
output: {
77+
format: 'iife',
78+
exports: 'none',
79+
entryFileNames: 'sw.js',
80+
inlineDynamicImports: true,
81+
},
82+
},
83+
},
84+
};
85+
},
86+
async buildStart() {
87+
if (buildConfig.mode === 'development') {
88+
buildOutput = await build(buildConfig) as RollupOutput;
89+
}
90+
},
91+
resolveId(id) {
92+
if (id === '/sw.js') {
93+
return swSourcePath;
94+
}
95+
96+
return;
97+
},
98+
async load(id) {
99+
if (id === swSourcePath) {
100+
return buildOutput.output[0].code;
101+
}
102+
103+
return;
104+
},
105+
async closeBundle() {
106+
if (buildConfig.mode !== 'development') {
107+
await build({
108+
...buildConfig,
109+
plugins: [injectManifestToSWPlugin({ outDir: buildConfig.build!.outDir! }), brotli()]
110+
});
111+
}
112+
},
113+
};
114+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"description": "Internal Vite plugin for building Flow service worker",
3+
"repository": "vaadin/flow",
4+
"name": "@vaadin/vite-plugin-service-worker",
5+
"version": "1.0.0",
6+
"main": "index.ts",
7+
"private": true,
8+
"author": "Vaadin Ltd",
9+
"license": "Apache-2.0",
10+
"bugs": {
11+
"url": "https://github.com/vaadin/flow/issues"
12+
},
13+
"files": [
14+
"index.ts"
15+
],
16+
"peerDependencies": {
17+
"vite": "6.x",
18+
"workbox-build": "7.x",
19+
"rollup-plugin-brotli": "3.x"
20+
},
21+
"devDependencies": {
22+
"@types/node": "22.x"
23+
}
24+
}

flow-server/src/main/resources/vite.generated.ts

Lines changed: 4 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,18 @@ import settings from '#settingsImport#';
1616
import {
1717
AssetInfo,
1818
ChunkInfo,
19-
build,
2019
defineConfig,
2120
mergeConfig,
2221
OutputOptions,
2322
PluginOption,
24-
InlineConfig,
2523
UserConfigFn
2624
} from 'vite';
27-
import { getManifest, type ManifestTransform } from 'workbox-build';
2825

2926
import * as rollup from 'rollup';
3027
import brotli from 'rollup-plugin-brotli';
3128
import checker from 'vite-plugin-checker';
3229
import postcssLit from '#buildFolder#/plugins/rollup-plugin-postcss-lit-custom/rollup-plugin-postcss-lit.js';
30+
import serviceWorkerPlugin from '#buildFolder#/plugins/vite-plugin-service-worker';
3331

3432
import { createRequire } from 'module';
3533

@@ -41,8 +39,6 @@ import reactPlugin from '@vitejs/plugin-react';
4139
// Make `require` compatible with ES modules
4240
const require = createRequire(import.meta.url);
4341

44-
const appShellUrl = '.';
45-
4642
const frontendFolder = path.resolve(__dirname, settings.frontendFolder);
4743
const themeFolder = path.resolve(frontendFolder, settings.themeFolder);
4844
const frontendBundleFolder = path.resolve(__dirname, settings.frontendBundleOutput);
@@ -91,94 +87,6 @@ const target = ['safari15', 'es2022'];
9187
console.trace = () => {};
9288
console.debug = () => {};
9389

94-
function injectManifestToSWPlugin(): rollup.Plugin {
95-
const rewriteManifestIndexHtmlUrl: ManifestTransform = (manifest) => {
96-
const indexEntry = manifest.find((entry) => entry.url === 'index.html');
97-
if (indexEntry) {
98-
indexEntry.url = appShellUrl;
99-
}
100-
101-
return { manifest, warnings: [] };
102-
};
103-
104-
return {
105-
name: 'vaadin:inject-manifest-to-sw',
106-
async transform(code, id) {
107-
if (/sw\.(ts|js)$/.test(id)) {
108-
const { manifestEntries } = await getManifest({
109-
globDirectory: buildOutputFolder,
110-
globPatterns: ['**/*'],
111-
globIgnores: ['**/*.br', 'pwa-icons/**'],
112-
manifestTransforms: [rewriteManifestIndexHtmlUrl],
113-
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024 // 100mb,
114-
});
115-
116-
return code.replace('self.__WB_MANIFEST', JSON.stringify(manifestEntries));
117-
}
118-
}
119-
};
120-
}
121-
122-
function buildSWPlugin(opts: { devMode: boolean }): PluginOption {
123-
let buildConfig: InlineConfig;
124-
let buildOutput: rollup.RollupOutput;
125-
const devMode = opts.devMode;
126-
127-
return {
128-
name: 'vaadin:build-sw',
129-
enforce: 'post',
130-
async configResolved(viteConfig) {
131-
buildConfig = {
132-
base: viteConfig.base,
133-
root: viteConfig.root,
134-
mode: viteConfig.mode,
135-
resolve: viteConfig.resolve,
136-
define: {
137-
...viteConfig.define,
138-
'process.env.NODE_ENV': JSON.stringify(viteConfig.mode),
139-
},
140-
build: {
141-
write: !devMode,
142-
minify: viteConfig.build.minify,
143-
outDir: viteConfig.build.outDir,
144-
target,
145-
sourcemap: viteConfig.command === 'serve' || viteConfig.build.sourcemap,
146-
emptyOutDir: false,
147-
modulePreload: false,
148-
rollupOptions: {
149-
input: {
150-
sw: settings.clientServiceWorkerSource
151-
},
152-
output: {
153-
exports: 'none',
154-
entryFileNames: 'sw.js',
155-
inlineDynamicImports: true,
156-
},
157-
},
158-
},
159-
};
160-
},
161-
async buildStart() {
162-
if (devMode) {
163-
buildOutput = await build(buildConfig) as rollup.RollupOutput;
164-
}
165-
},
166-
async load(id) {
167-
if (id.endsWith('sw.js')) {
168-
return buildOutput.output[0].code;
169-
}
170-
},
171-
async closeBundle() {
172-
if (!devMode) {
173-
await build({
174-
...buildConfig,
175-
plugins: [injectManifestToSWPlugin(), brotli()]
176-
});
177-
}
178-
},
179-
};
180-
}
181-
18290
function statsExtracterPlugin(): PluginOption {
18391
function collectThemeJsonsInFrontend(themeJsonContents: Record<string, string>, themeName: string) {
18492
const themeJson = path.resolve(frontendFolder, settings.themeFolder, themeName, 'theme.json');
@@ -753,7 +661,9 @@ export const vaadinConfig: UserConfigFn = (env) => {
753661
productionMode && brotli(),
754662
devMode && vaadinBundlesPlugin(),
755663
devMode && showRecompileReason(),
756-
settings.offlineEnabled && buildSWPlugin({ devMode }),
664+
settings.offlineEnabled && serviceWorkerPlugin({
665+
srcPath: settings.clientServiceWorkerSource,
666+
}),
757667
!devMode && statsExtracterPlugin(),
758668
!productionMode && preserveUsageStats(),
759669
themePlugin({ devMode }),

flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskInstallFrontendBuildPluginsTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ public void getPluginsReturnsExpectedList() {
6868
String[] expectedPlugins = new String[] { "application-theme-plugin",
6969
"theme-loader", "theme-live-reload-plugin",
7070
"build-status-plugin", "rollup-plugin-postcss-lit-custom",
71-
"react-function-location-plugin" };
71+
"react-function-location-plugin",
72+
"vite-plugin-service-worker" };
7273
final List<String> plugins = FrontendPluginsUtil.getPlugins();
7374
Assert.assertEquals("Unexpected number of plugins in 'plugins.json'",
7475
expectedPlugins.length, plugins.size());

0 commit comments

Comments
 (0)
0