Fix service worker failing to load due to 404 on chunk dependencies (#39433)
This commit is contained in:
parent
dd12940ed5
commit
72fa17a441
61
config/vite/plugin-sw-chunk-paths.ts
Normal file
61
config/vite/plugin-sw-chunk-paths.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/* The service worker is built as a regular Vite entry point and is served from
|
||||
`/sw.js` (a symlink to `packs/sw.js`), while the chunks it depends on live in
|
||||
the build output directory (e.g. `/packs/`).
|
||||
|
||||
Browsers resolve a module's static import specifiers relative to the *URL* of
|
||||
the script, not its location on disk. Because the worker is served from the
|
||||
root, relative specifiers such as `./chunk-abc123.js` resolve to
|
||||
`/chunk-abc123.js` and return a 404, which prevents the service worker from
|
||||
installing.
|
||||
|
||||
This plugin rewrites those relative specifiers in the service worker output
|
||||
to absolute paths pointing at the build output directory, so they resolve
|
||||
correctly regardless of the URL the worker is served from.
|
||||
*/
|
||||
|
||||
import type { Plugin, ResolvedConfig } from 'vite';
|
||||
|
||||
const SERVICE_WORKER_FILENAME = 'sw.js';
|
||||
|
||||
export function MastodonServiceWorkerChunkPaths(): Plugin {
|
||||
let config: ResolvedConfig;
|
||||
|
||||
return {
|
||||
name: 'mastodon-sw-chunk-paths',
|
||||
configResolved(resolvedConfig) {
|
||||
config = resolvedConfig;
|
||||
},
|
||||
renderChunk(code, chunk) {
|
||||
if (chunk.fileName !== SERVICE_WORKER_FILENAME) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Resolve the base from the final Vite config rather than receiving it as
|
||||
// an argument, so forks or other plugins that alter `base` are respected.
|
||||
// Vite normalises `base` to always include a trailing slash.
|
||||
const { base } = config;
|
||||
|
||||
// Drive the rewrite from the chunk's actual dependency list rather than a
|
||||
// generic regex, so we only ever touch real (hashed) chunk specifiers and
|
||||
// never accidentally match similar-looking text inside string literals.
|
||||
const dependencies = [...chunk.imports, ...chunk.dynamicImports];
|
||||
|
||||
let rewritten = code;
|
||||
for (const dependency of dependencies) {
|
||||
// The worker sits at the root of the output directory, so each
|
||||
// dependency is imported with a leading `./`.
|
||||
rewritten = rewritten
|
||||
.replaceAll(`"./${dependency}"`, `"${base}${dependency}"`)
|
||||
.replaceAll(`'./${dependency}'`, `'${base}${dependency}'`);
|
||||
}
|
||||
|
||||
if (rewritten === code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only import specifiers are changed, so the existing source map stays
|
||||
// accurate enough; returning `null` avoids a spurious sourcemap warning.
|
||||
return { code: rewritten, map: null };
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -22,6 +22,7 @@ import svgr from 'vite-plugin-svgr';
|
||||
import { MastodonAssetsManifest } from './config/vite/plugin-assets-manifest';
|
||||
import { MastodonThemes } from './config/vite/plugin-mastodon-themes';
|
||||
import { MastodonNameLookup } from './config/vite/plugin-name-lookup';
|
||||
import { MastodonServiceWorkerChunkPaths } from './config/vite/plugin-sw-chunk-paths';
|
||||
import { MastodonServiceWorkerLocales } from './config/vite/plugin-sw-locales';
|
||||
|
||||
const jsRoot = path.resolve(__dirname, 'app/javascript');
|
||||
@ -185,6 +186,7 @@ export const config: UserConfigFnPromise = async ({ mode, command }) => {
|
||||
MastodonThemes(),
|
||||
MastodonAssetsManifest(),
|
||||
MastodonServiceWorkerLocales(),
|
||||
MastodonServiceWorkerChunkPaths(),
|
||||
legacy({
|
||||
renderLegacyChunks: false,
|
||||
modernPolyfills: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user