@serwist/vite 9.0.0-preview.0 → 9.0.0-preview.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/index.js +472 -24
- package/dist/index.worker.d.ts +10 -2
- package/dist/index.worker.d.ts.map +1 -1
- package/dist/index.worker.js +75 -64
- package/package.json +12 -17
- package/src/context.ts +1 -1
- package/src/index.worker.ts +76 -66
- package/src/modules.ts +1 -1
- package/src/options.ts +1 -1
- package/src/rollup.js +0 -22
- package/dist/integration/svelte/build.d.ts +0 -5
- package/dist/integration/svelte/build.d.ts.map +0 -1
- package/dist/integration/svelte/config.d.ts +0 -9
- package/dist/integration/svelte/config.d.ts.map +0 -1
- package/dist/integration/svelte/index.d.ts +0 -10
- package/dist/integration/svelte/index.d.ts.map +0 -1
- package/dist/integration/svelte/index.js +0 -163
- package/dist/integration/svelte/types.d.ts +0 -24
- package/dist/integration/svelte/types.d.ts.map +0 -1
- package/dist/main.js +0 -542
- package/src/integration/svelte/build.ts +0 -21
- package/src/integration/svelte/config.ts +0 -141
- package/src/integration/svelte/index.ts +0 -27
- package/src/integration/svelte/types.ts +0 -26
package/dist/main.js
DELETED
|
@@ -1,542 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path, { resolve } from 'node:path';
|
|
3
|
-
import { normalizePath } from 'vite';
|
|
4
|
-
import process$1 from 'node:process';
|
|
5
|
-
import crypto from 'node:crypto';
|
|
6
|
-
import fs$1 from 'node:fs';
|
|
7
|
-
import fg from 'fast-glob';
|
|
8
|
-
import assert from 'node:assert';
|
|
9
|
-
|
|
10
|
-
let enabled = true;
|
|
11
|
-
// Support both browser and node environments
|
|
12
|
-
const globalVar = typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
|
|
13
|
-
/**
|
|
14
|
-
* Detect how much colors the current terminal supports
|
|
15
|
-
*/ let supportLevel = 0 /* none */ ;
|
|
16
|
-
if (globalVar.process && globalVar.process.env && globalVar.process.stdout) {
|
|
17
|
-
const { FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, COLORTERM } = globalVar.process.env;
|
|
18
|
-
if (NODE_DISABLE_COLORS || NO_COLOR || FORCE_COLOR === '0') {
|
|
19
|
-
enabled = false;
|
|
20
|
-
} else if (FORCE_COLOR === '1' || FORCE_COLOR === '2' || FORCE_COLOR === '3') {
|
|
21
|
-
enabled = true;
|
|
22
|
-
} else if (TERM === 'dumb') {
|
|
23
|
-
enabled = false;
|
|
24
|
-
} else if ('CI' in globalVar.process.env && [
|
|
25
|
-
'TRAVIS',
|
|
26
|
-
'CIRCLECI',
|
|
27
|
-
'APPVEYOR',
|
|
28
|
-
'GITLAB_CI',
|
|
29
|
-
'GITHUB_ACTIONS',
|
|
30
|
-
'BUILDKITE',
|
|
31
|
-
'DRONE'
|
|
32
|
-
].some((vendor)=>vendor in globalVar.process.env)) {
|
|
33
|
-
enabled = true;
|
|
34
|
-
} else {
|
|
35
|
-
enabled = process.stdout.isTTY;
|
|
36
|
-
}
|
|
37
|
-
if (enabled) {
|
|
38
|
-
// Windows supports 24bit True Colors since Windows 10 revision #14931,
|
|
39
|
-
// see https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/
|
|
40
|
-
if (process.platform === 'win32') {
|
|
41
|
-
supportLevel = 3 /* trueColor */ ;
|
|
42
|
-
} else {
|
|
43
|
-
if (COLORTERM && (COLORTERM === 'truecolor' || COLORTERM === '24bit')) {
|
|
44
|
-
supportLevel = 3 /* trueColor */ ;
|
|
45
|
-
} else if (TERM && (TERM.endsWith('-256color') || TERM.endsWith('256'))) {
|
|
46
|
-
supportLevel = 2 /* ansi256 */ ;
|
|
47
|
-
} else {
|
|
48
|
-
supportLevel = 1 /* ansi */ ;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
let options = {
|
|
54
|
-
enabled,
|
|
55
|
-
supportLevel
|
|
56
|
-
};
|
|
57
|
-
function kolorist(start, end, level = 1 /* ansi */ ) {
|
|
58
|
-
const open = `\x1b[${start}m`;
|
|
59
|
-
const close = `\x1b[${end}m`;
|
|
60
|
-
const regex = new RegExp(`\\x1b\\[${end}m`, 'g');
|
|
61
|
-
return (str)=>{
|
|
62
|
-
return options.enabled && options.supportLevel >= level ? open + ('' + str).replace(regex, open) + close : '' + str;
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
const dim = kolorist(2, 22);
|
|
66
|
-
const green = kolorist(32, 39);
|
|
67
|
-
const yellow = kolorist(33, 39);
|
|
68
|
-
const cyan = kolorist(36, 39);
|
|
69
|
-
|
|
70
|
-
var version = "9.0.0-preview.0";
|
|
71
|
-
|
|
72
|
-
const logSerwistResult = (buildResult, viteOptions)=>{
|
|
73
|
-
const { logLevel = "info" } = viteOptions;
|
|
74
|
-
if (logLevel === "silent") return;
|
|
75
|
-
const { count, size, warnings } = buildResult;
|
|
76
|
-
if (logLevel === "info") {
|
|
77
|
-
console.info([
|
|
78
|
-
"",
|
|
79
|
-
`${cyan(`@serwist/vite v${version}`)} ${green("files generated.")}`,
|
|
80
|
-
`${green("✓")} ${count} precache entries ${dim(`(${(size / 1024).toFixed(2)} KiB)`)}`,
|
|
81
|
-
// log build warning
|
|
82
|
-
warnings && warnings.length > 0 ? yellow([
|
|
83
|
-
"⚠ warnings",
|
|
84
|
-
...warnings.map((w)=>` ${w}`),
|
|
85
|
-
""
|
|
86
|
-
].join("\n")) : ""
|
|
87
|
-
].join("\n"));
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const loadSerwistBuild = async ()=>{
|
|
92
|
-
// "@serwist/build" is large and makes config loading slow.
|
|
93
|
-
// Since it is not always used, we only load this when it is needed.
|
|
94
|
-
try {
|
|
95
|
-
return await import('@serwist/build');
|
|
96
|
-
} catch (_) {
|
|
97
|
-
// We don't have a default export, don't worry.
|
|
98
|
-
return require("@serwist/build");
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
const injectManifest = async (config)=>{
|
|
102
|
-
const { validateViteInjectManifestOptions, getFileManifestEntries, stringify } = await loadSerwistBuild();
|
|
103
|
-
const options = await validateViteInjectManifestOptions(config);
|
|
104
|
-
const { count, size, manifestEntries, warnings } = await getFileManifestEntries(options);
|
|
105
|
-
const manifestString = manifestEntries === undefined ? "undefined" : stringify(manifestEntries);
|
|
106
|
-
return {
|
|
107
|
-
warnings,
|
|
108
|
-
size,
|
|
109
|
-
count,
|
|
110
|
-
manifestEntries,
|
|
111
|
-
manifestString
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
const generateServiceWorker = async (ctx)=>{
|
|
115
|
-
const { format, plugins, rollupOptions } = ctx.options.injectManifestRollupOptions;
|
|
116
|
-
const parsedSwDest = path.parse(ctx.options.injectManifest.swDest);
|
|
117
|
-
let injectManifestResult = undefined;
|
|
118
|
-
if (ctx.options.injectManifest.injectionPoint) {
|
|
119
|
-
await ctx.options.integration?.beforeBuildServiceWorker?.(ctx.options);
|
|
120
|
-
injectManifestResult = await injectManifest(ctx.options.injectManifest);
|
|
121
|
-
}
|
|
122
|
-
const isProduction = ctx.options.mode === "production";
|
|
123
|
-
const isDev = ctx.options.mode === "development";
|
|
124
|
-
if (isProduction && ctx.framework === "sveltekit" || isDev && !ctx.options.devOptions.bundle) {
|
|
125
|
-
if (!injectManifestResult) {
|
|
126
|
-
throw new Error("injectManifest failed to generate results. This is likely a bug.");
|
|
127
|
-
}
|
|
128
|
-
const { errors, escapeRegExp, getSourceMapURL, rebasePath, replaceAndUpdateSourceMap, translateURLToSourcemapPaths } = await loadSerwistBuild();
|
|
129
|
-
// Make sure we leave swSrc and swDest out of the precache manifest.
|
|
130
|
-
for (const file of [
|
|
131
|
-
ctx.options.injectManifest.swSrc,
|
|
132
|
-
ctx.options.injectManifest.swDest
|
|
133
|
-
]){
|
|
134
|
-
ctx.options.injectManifest.globIgnores.push(rebasePath({
|
|
135
|
-
file,
|
|
136
|
-
baseDirectory: ctx.options.injectManifest.globDirectory
|
|
137
|
-
}));
|
|
138
|
-
}
|
|
139
|
-
const injectionPoint = ctx.options.injectManifest.injectionPoint;
|
|
140
|
-
const globalRegexp = new RegExp(escapeRegExp(injectionPoint), "g");
|
|
141
|
-
let swFileContents;
|
|
142
|
-
try {
|
|
143
|
-
swFileContents = await fs.readFile(ctx.options.injectManifest.swSrc, "utf8");
|
|
144
|
-
} catch (error) {
|
|
145
|
-
throw new Error(`${errors["invalid-sw-src"]} ${error instanceof Error && error.message ? error.message : ""}`);
|
|
146
|
-
}
|
|
147
|
-
const injectionResults = swFileContents.match(globalRegexp);
|
|
148
|
-
// See https://github.com/GoogleChrome/workbox/issues/2230
|
|
149
|
-
if (!injectionResults) {
|
|
150
|
-
throw new Error(`${errors["injection-point-not-found"]} ${injectionPoint}`);
|
|
151
|
-
}
|
|
152
|
-
assert(injectionResults.length === 1, `${errors["multiple-injection-points"]} ${injectionPoint}`);
|
|
153
|
-
const filesToWrite = {};
|
|
154
|
-
const url = getSourceMapURL(swFileContents);
|
|
155
|
-
// See https://github.com/GoogleChrome/workbox/issues/2957
|
|
156
|
-
const { destPath, srcPath, warning } = translateURLToSourcemapPaths(url, ctx.options.injectManifest.swSrc, ctx.options.injectManifest.swDest);
|
|
157
|
-
if (warning) {
|
|
158
|
-
injectManifestResult.warnings.push(warning);
|
|
159
|
-
}
|
|
160
|
-
// If our swSrc file contains a sourcemap, we would invalidate that
|
|
161
|
-
// mapping if we just replaced injectionPoint with the stringified manifest.
|
|
162
|
-
// Instead, we need to update the swDest contents as well as the sourcemap
|
|
163
|
-
// (assuming it's a real file, not a data: URL) at the same time.
|
|
164
|
-
// See https://github.com/GoogleChrome/workbox/issues/2235
|
|
165
|
-
// and https://github.com/GoogleChrome/workbox/issues/2648
|
|
166
|
-
if (srcPath && destPath) {
|
|
167
|
-
const { map, source } = await replaceAndUpdateSourceMap({
|
|
168
|
-
originalMap: JSON.parse(await fs.readFile(srcPath, "utf8")),
|
|
169
|
-
jsFilename: path.basename(ctx.options.injectManifest.swDest),
|
|
170
|
-
originalSource: swFileContents,
|
|
171
|
-
replaceString: injectManifestResult.manifestString,
|
|
172
|
-
searchString: injectionPoint
|
|
173
|
-
});
|
|
174
|
-
filesToWrite[ctx.options.injectManifest.swDest] = source;
|
|
175
|
-
filesToWrite[destPath] = map;
|
|
176
|
-
} else {
|
|
177
|
-
// If there's no sourcemap associated with swSrc, a simple string
|
|
178
|
-
// replacement will suffice.
|
|
179
|
-
filesToWrite[ctx.options.injectManifest.swDest] = swFileContents.replace(globalRegexp, injectManifestResult.manifestString);
|
|
180
|
-
}
|
|
181
|
-
for (const [file, contents] of Object.entries(filesToWrite)){
|
|
182
|
-
try {
|
|
183
|
-
await fs.mkdir(path.dirname(file), {
|
|
184
|
-
recursive: true
|
|
185
|
-
});
|
|
186
|
-
} catch (error) {
|
|
187
|
-
throw new Error(`${errors["unable-to-make-sw-directory"]} '${error instanceof Error && error.message ? error.message : ""}'`);
|
|
188
|
-
}
|
|
189
|
-
await fs.writeFile(file, contents);
|
|
190
|
-
}
|
|
191
|
-
} else {
|
|
192
|
-
const define = {
|
|
193
|
-
// Nuxt does some really weird stuff. During the build, they MANUALLY
|
|
194
|
-
// set browser APIs, such as window, document, location,..., to `undefined`??
|
|
195
|
-
// Probably some Vue or server stuff. Their `define` doesn't seem to have anything
|
|
196
|
-
// particularly useful for the service worker anyway, so we don't extend it.
|
|
197
|
-
...ctx.framework === "nuxt" ? undefined : ctx.viteConfig.define,
|
|
198
|
-
"process.env.NODE_ENV": `"${ctx.options.mode}"`
|
|
199
|
-
};
|
|
200
|
-
if (ctx.options.injectManifest.injectionPoint && injectManifestResult) {
|
|
201
|
-
define[ctx.options.injectManifest.injectionPoint] = injectManifestResult.manifestString;
|
|
202
|
-
}
|
|
203
|
-
const { build } = await import('vite');
|
|
204
|
-
await build({
|
|
205
|
-
logLevel: ctx.viteConfig.isProduction ? "info" : "warn",
|
|
206
|
-
root: ctx.viteConfig.root,
|
|
207
|
-
base: ctx.viteConfig.base,
|
|
208
|
-
resolve: ctx.viteConfig.resolve,
|
|
209
|
-
// Don't copy anything from public folder
|
|
210
|
-
publicDir: false,
|
|
211
|
-
build: {
|
|
212
|
-
sourcemap: ctx.viteConfig.build.sourcemap,
|
|
213
|
-
lib: {
|
|
214
|
-
entry: ctx.options.injectManifest.swSrc,
|
|
215
|
-
name: "app",
|
|
216
|
-
formats: [
|
|
217
|
-
format
|
|
218
|
-
]
|
|
219
|
-
},
|
|
220
|
-
rollupOptions: {
|
|
221
|
-
...rollupOptions,
|
|
222
|
-
plugins,
|
|
223
|
-
output: {
|
|
224
|
-
entryFileNames: parsedSwDest.base
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
outDir: parsedSwDest.dir,
|
|
228
|
-
emptyOutDir: false,
|
|
229
|
-
minify: isProduction || ctx.options.devOptions.minify
|
|
230
|
-
},
|
|
231
|
-
configFile: false,
|
|
232
|
-
define
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
return injectManifestResult;
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const createApi = (ctx)=>{
|
|
239
|
-
return {
|
|
240
|
-
get disabled () {
|
|
241
|
-
return ctx?.options?.disable;
|
|
242
|
-
},
|
|
243
|
-
async generateSW () {
|
|
244
|
-
if (ctx.options.disable) {
|
|
245
|
-
return undefined;
|
|
246
|
-
}
|
|
247
|
-
const buildResult = await generateServiceWorker(ctx);
|
|
248
|
-
if (buildResult) {
|
|
249
|
-
if (ctx.viteConfig.isProduction) {
|
|
250
|
-
// Log Serwist result
|
|
251
|
-
logSerwistResult(buildResult, ctx.viteConfig);
|
|
252
|
-
} else if (buildResult.warnings && buildResult.warnings.length > 0) {
|
|
253
|
-
console.warn(yellow([
|
|
254
|
-
"[@serwist/vite] Warnings",
|
|
255
|
-
...buildResult.warnings.map((w)=>` - ${w}`),
|
|
256
|
-
""
|
|
257
|
-
].join("\n")));
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
extendManifestEntries (fn) {
|
|
262
|
-
const { options } = ctx;
|
|
263
|
-
if (options.disable) return;
|
|
264
|
-
const result = fn(options.injectManifest.additionalPrecacheEntries || []);
|
|
265
|
-
if (result != null) {
|
|
266
|
-
options.injectManifest.additionalPrecacheEntries = result;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
const createContext = (userOptions, framework)=>{
|
|
273
|
-
return {
|
|
274
|
-
userOptions,
|
|
275
|
-
options: undefined,
|
|
276
|
-
viteConfig: undefined,
|
|
277
|
-
useImportRegister: false,
|
|
278
|
-
devEnvironment: false,
|
|
279
|
-
framework
|
|
280
|
-
};
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
const slash = (str)=>{
|
|
284
|
-
return str.replace(/\\/g, "/");
|
|
285
|
-
};
|
|
286
|
-
const resolveBasePath = (base)=>{
|
|
287
|
-
if (isAbsolute(base)) return base;
|
|
288
|
-
return !base.startsWith("/") && !base.startsWith("./") ? `/${base}` : base;
|
|
289
|
-
};
|
|
290
|
-
const isAbsolute = (url)=>{
|
|
291
|
-
return url.match(/^(?:[a-z]+:)?\/\//i);
|
|
292
|
-
};
|
|
293
|
-
// Source: https://github.com/sveltejs/kit/blob/6419d3eaa7bf1b0a756b28f06a73f71fe042de0a/packages/kit/src/utils/filesystem.js
|
|
294
|
-
// License: MIT
|
|
295
|
-
/**
|
|
296
|
-
* Internal function used by `@serwist/vite`.
|
|
297
|
-
* Resolves a file path without extension. Also handles `/index` if the path
|
|
298
|
-
* actually points to a directory.
|
|
299
|
-
* @internal
|
|
300
|
-
* @param ctx
|
|
301
|
-
* @param api
|
|
302
|
-
* @returns
|
|
303
|
-
*/ const resolveEntry = (entry)=>{
|
|
304
|
-
if (fs$1.existsSync(entry)) {
|
|
305
|
-
const stats = fs$1.statSync(entry);
|
|
306
|
-
if (stats.isDirectory()) {
|
|
307
|
-
return resolveEntry(path.join(entry, "index"));
|
|
308
|
-
}
|
|
309
|
-
return entry;
|
|
310
|
-
}
|
|
311
|
-
const dir = path.dirname(entry);
|
|
312
|
-
if (fs$1.existsSync(dir)) {
|
|
313
|
-
const base = path.basename(entry);
|
|
314
|
-
const files = fs$1.readdirSync(dir);
|
|
315
|
-
const found = files.find((file)=>file.replace(/\.[^.]+$/, "") === base);
|
|
316
|
-
if (found) return path.join(dir, found);
|
|
317
|
-
}
|
|
318
|
-
return null;
|
|
319
|
-
};
|
|
320
|
-
// Source: https://github.com/sveltejs/kit/blob/6419d3eaa7bf1b0a756b28f06a73f71fe042de0a/packages/kit/src/utils/filesystem.js
|
|
321
|
-
// License: MIT
|
|
322
|
-
/**
|
|
323
|
-
* Internal function used by `@serwist/vite`.
|
|
324
|
-
* Converts a filesystem path to a Vite `@fs` URL.
|
|
325
|
-
* @internal
|
|
326
|
-
* @param ctx
|
|
327
|
-
* @param api
|
|
328
|
-
* @returns
|
|
329
|
-
*/ const toFs = (str)=>{
|
|
330
|
-
str = str.replace(/\\/g, "/");
|
|
331
|
-
// Windows/Linux separation - Windows starts with a drive letter, we need a / in front there
|
|
332
|
-
return `/@fs${str.startsWith("/") ? "" : "/"}${str}`;
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
// This plugin handles the service worker in two ways:
|
|
336
|
-
// - If `devOptions.bundle` is enabled, hook a middleware that bundles the service worker
|
|
337
|
-
// through `api.generateSW()` and returns the result into Vite's dev server.
|
|
338
|
-
// - Otherwise, run `injectManifest` and return the service worker through `async load(id)`. Although
|
|
339
|
-
// `precacheEntries` is always `undefined`, we still do this to check the user's `injectManifest` options
|
|
340
|
-
// in dev mode.
|
|
341
|
-
/**
|
|
342
|
-
* Internal dev plugin used by `@serwist/vite`.
|
|
343
|
-
* @internal
|
|
344
|
-
* @param ctx
|
|
345
|
-
* @param api
|
|
346
|
-
* @returns
|
|
347
|
-
*/ const devPlugin = (ctx, api)=>{
|
|
348
|
-
return {
|
|
349
|
-
name: "@serwist/vite:dev",
|
|
350
|
-
apply: "serve",
|
|
351
|
-
configureServer (server) {
|
|
352
|
-
ctx.devEnvironment = true;
|
|
353
|
-
server.middlewares.use(async (req, res, next)=>{
|
|
354
|
-
if (!ctx.options.disable && req.url === ctx.options.swUrl) {
|
|
355
|
-
if (ctx.options.devOptions.bundle) {
|
|
356
|
-
await api.generateSW();
|
|
357
|
-
const content = await fs.readFile(ctx.options.injectManifest.swDest, "utf-8");
|
|
358
|
-
await fs.rm(ctx.options.injectManifest.swDest);
|
|
359
|
-
res.setHeader("Content-Type", "application/javascript");
|
|
360
|
-
res.write(content);
|
|
361
|
-
res.end();
|
|
362
|
-
} else {
|
|
363
|
-
res.setHeader("Content-Type", "application/javascript");
|
|
364
|
-
res.write(`import "${toFs(path.resolve(ctx.options.injectManifest.swSrc))}";`);
|
|
365
|
-
res.end();
|
|
366
|
-
}
|
|
367
|
-
} else {
|
|
368
|
-
next();
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
},
|
|
372
|
-
async load (id) {
|
|
373
|
-
if (!ctx.options.disable && !ctx.options.devOptions.bundle) {
|
|
374
|
-
const swSrcId = normalizePath(ctx.options.injectManifest.swSrc);
|
|
375
|
-
if (id === swSrcId) {
|
|
376
|
-
await api.generateSW();
|
|
377
|
-
const content = await fs.readFile(ctx.options.injectManifest.swDest, "utf-8");
|
|
378
|
-
await fs.rm(ctx.options.injectManifest.swDest);
|
|
379
|
-
return content;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return undefined;
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
const INTERNAL_SERWIST_VIRTUAL = "virtual:internal-serwist";
|
|
388
|
-
const RESOLVED_INTERNAL_SERWIST_VIRTUAL = `\0${INTERNAL_SERWIST_VIRTUAL}`;
|
|
389
|
-
|
|
390
|
-
const buildManifestEntry = (publicDir, url)=>{
|
|
391
|
-
return new Promise((resolve$1, reject)=>{
|
|
392
|
-
const cHash = crypto.createHash("MD5");
|
|
393
|
-
const stream = fs$1.createReadStream(resolve(publicDir, url));
|
|
394
|
-
stream.on("error", (err)=>{
|
|
395
|
-
reject(err);
|
|
396
|
-
});
|
|
397
|
-
stream.on("data", (chunk)=>{
|
|
398
|
-
cHash.update(chunk);
|
|
399
|
-
});
|
|
400
|
-
stream.on("end", ()=>{
|
|
401
|
-
return resolve$1({
|
|
402
|
-
url,
|
|
403
|
-
revision: `${cHash.digest("hex")}`
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
};
|
|
408
|
-
const lookupAdditionalPrecacheEntries = (serwistOptions)=>{
|
|
409
|
-
return serwistOptions.additionalPrecacheEntries || [];
|
|
410
|
-
};
|
|
411
|
-
// we need to make icons relative, we can have for example icon entries with: /pwa.png
|
|
412
|
-
// fast-glob will not resolve absolute paths
|
|
413
|
-
const normalizeIconPath = (path)=>{
|
|
414
|
-
return path.startsWith("/") ? path.substring(1) : path;
|
|
415
|
-
};
|
|
416
|
-
const configureStaticAssets = async (resolvedPluginOptions, viteConfig)=>{
|
|
417
|
-
const { injectManifest, includeAssets } = resolvedPluginOptions;
|
|
418
|
-
const { publicDir } = viteConfig;
|
|
419
|
-
const globs = [];
|
|
420
|
-
const manifestEntries = lookupAdditionalPrecacheEntries(injectManifest);
|
|
421
|
-
if (includeAssets) {
|
|
422
|
-
// we need to make icons relative, we can have for example icon entries with: /pwa.png
|
|
423
|
-
// fast-glob will not resolve absolute paths
|
|
424
|
-
if (Array.isArray(includeAssets)) globs.push(...includeAssets.map(normalizeIconPath));
|
|
425
|
-
else globs.push(normalizeIconPath(includeAssets));
|
|
426
|
-
}
|
|
427
|
-
if (globs.length > 0) {
|
|
428
|
-
let assets = await fg(globs, {
|
|
429
|
-
cwd: publicDir,
|
|
430
|
-
onlyFiles: true,
|
|
431
|
-
unique: true
|
|
432
|
-
});
|
|
433
|
-
// we also need to remove from the list existing included by the user
|
|
434
|
-
if (manifestEntries.length > 0) {
|
|
435
|
-
const included = manifestEntries.map((me)=>{
|
|
436
|
-
if (typeof me === "string") return me;
|
|
437
|
-
return me.url;
|
|
438
|
-
});
|
|
439
|
-
assets = assets.filter((a)=>!included.includes(a));
|
|
440
|
-
}
|
|
441
|
-
const assetsEntries = await Promise.all(assets.map((a)=>{
|
|
442
|
-
return buildManifestEntry(publicDir, a);
|
|
443
|
-
}));
|
|
444
|
-
manifestEntries.push(...assetsEntries);
|
|
445
|
-
}
|
|
446
|
-
if (manifestEntries.length > 0) {
|
|
447
|
-
injectManifest.additionalPrecacheEntries = manifestEntries;
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
const resolveOptions = async (options, viteConfig)=>{
|
|
452
|
-
const { type = "classic", mode = process$1.env.NODE_ENV || "production", injectRegister = "auto", registerType = "prompt", minify = true, base = viteConfig.base, scope: _scope, swUrl = "/sw.js", includeAssets = undefined, useCredentials = false, disable = false, integration = {}, buildBase, devOptions, plugins = [], rollupOptions = {}, rollupFormat = "es", ...injectManifest } = options;
|
|
453
|
-
const basePath = resolveBasePath(base);
|
|
454
|
-
// check typescript service worker for injectManifest strategy
|
|
455
|
-
const scope = _scope || basePath;
|
|
456
|
-
let assetsDir = slash(viteConfig.build.assetsDir ?? "assets");
|
|
457
|
-
if (assetsDir[assetsDir.length - 1] !== "/") assetsDir += "/";
|
|
458
|
-
const resolvedDevOptions = {
|
|
459
|
-
bundle: true,
|
|
460
|
-
minify: false,
|
|
461
|
-
...devOptions
|
|
462
|
-
};
|
|
463
|
-
// remove './' prefix from assetsDir
|
|
464
|
-
const dontCacheBustURLsMatching = new RegExp(`^${assetsDir.replace(/^\.*?\//, "")}`);
|
|
465
|
-
const { validateViteInjectManifestOptions } = await loadSerwistBuild();
|
|
466
|
-
const validatedInjectManifest = await validateViteInjectManifestOptions(injectManifest);
|
|
467
|
-
const { swSrc, swDest, ...userInjectManifest } = validatedInjectManifest || {};
|
|
468
|
-
const resolvedPluginOptions = {
|
|
469
|
-
base: basePath,
|
|
470
|
-
type,
|
|
471
|
-
mode,
|
|
472
|
-
injectRegister,
|
|
473
|
-
registerType,
|
|
474
|
-
useCredentials,
|
|
475
|
-
swUrl,
|
|
476
|
-
injectManifest: {
|
|
477
|
-
dontCacheBustURLsMatching,
|
|
478
|
-
...userInjectManifest,
|
|
479
|
-
swSrc: path.resolve(viteConfig.root, swSrc),
|
|
480
|
-
swDest: path.resolve(viteConfig.root, viteConfig.build.outDir, swDest),
|
|
481
|
-
disablePrecacheManifest: !viteConfig.isProduction
|
|
482
|
-
},
|
|
483
|
-
scope,
|
|
484
|
-
minify,
|
|
485
|
-
includeAssets,
|
|
486
|
-
disable,
|
|
487
|
-
integration,
|
|
488
|
-
buildBase: buildBase ?? basePath,
|
|
489
|
-
injectManifestRollupOptions: {
|
|
490
|
-
plugins,
|
|
491
|
-
rollupOptions,
|
|
492
|
-
format: rollupFormat
|
|
493
|
-
},
|
|
494
|
-
devOptions: resolvedDevOptions
|
|
495
|
-
};
|
|
496
|
-
// calculate hash only when required
|
|
497
|
-
const calculateHash = !resolvedPluginOptions.disable && resolvedPluginOptions.includeAssets && viteConfig.command === "build";
|
|
498
|
-
if (calculateHash) await configureStaticAssets(resolvedPluginOptions, viteConfig);
|
|
499
|
-
return resolvedPluginOptions;
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* Internal plugin used by `@serwist/vite`.
|
|
504
|
-
* @internal
|
|
505
|
-
* @param ctx
|
|
506
|
-
* @param api
|
|
507
|
-
* @returns
|
|
508
|
-
*/ const mainPlugin = (ctx, api)=>{
|
|
509
|
-
return {
|
|
510
|
-
name: "@serwist/vite",
|
|
511
|
-
enforce: "pre",
|
|
512
|
-
config () {
|
|
513
|
-
return {
|
|
514
|
-
ssr: {
|
|
515
|
-
noExternal: []
|
|
516
|
-
}
|
|
517
|
-
};
|
|
518
|
-
},
|
|
519
|
-
async configResolved (config) {
|
|
520
|
-
ctx.viteConfig = config;
|
|
521
|
-
ctx.userOptions?.integration?.configureOptions?.(config, ctx.userOptions);
|
|
522
|
-
ctx.options = await resolveOptions(ctx.userOptions, config);
|
|
523
|
-
},
|
|
524
|
-
resolveId (id) {
|
|
525
|
-
if (id === INTERNAL_SERWIST_VIRTUAL) {
|
|
526
|
-
return RESOLVED_INTERNAL_SERWIST_VIRTUAL;
|
|
527
|
-
}
|
|
528
|
-
return undefined;
|
|
529
|
-
},
|
|
530
|
-
load (id) {
|
|
531
|
-
if (id === RESOLVED_INTERNAL_SERWIST_VIRTUAL) {
|
|
532
|
-
return `export const swUrl = "${path.posix.join(ctx.options.buildBase, ctx.options.swUrl)}";
|
|
533
|
-
export const swScope = "${ctx.options.scope}";
|
|
534
|
-
export const swType = "${ctx.devEnvironment ? "module" : ctx.options.type}";`;
|
|
535
|
-
}
|
|
536
|
-
return undefined;
|
|
537
|
-
},
|
|
538
|
-
api
|
|
539
|
-
};
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
export { createApi as a, createContext as c, devPlugin as d, mainPlugin as m, resolveEntry as r, toFs as t };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "vite";
|
|
2
|
-
|
|
3
|
-
import type { SerwistViteContext } from "../../context.js";
|
|
4
|
-
import type { SerwistViteApi } from "../../types.js";
|
|
5
|
-
|
|
6
|
-
export const buildPlugin = (ctx: SerwistViteContext, api: SerwistViteApi) => {
|
|
7
|
-
return <Plugin>{
|
|
8
|
-
name: "@serwist/vite/integration-svelte:build",
|
|
9
|
-
apply: "build",
|
|
10
|
-
enforce: "pre",
|
|
11
|
-
closeBundle: {
|
|
12
|
-
sequential: true,
|
|
13
|
-
enforce: "pre",
|
|
14
|
-
async handler() {
|
|
15
|
-
if (api && !api.disabled && ctx.viteConfig.build.ssr) {
|
|
16
|
-
await api.generateSW();
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
};
|