UNPKG

@sveltejs/kit

Version:

SvelteKit is the fastest way to build Svelte apps

134 lines (118 loc) 3.96 kB
import fs from 'node:fs'; import * as vite from 'vite'; import { dedent } from '../../../core/sync/utils.js'; import { s } from '../../../utils/misc.js'; import { get_config_aliases, strip_virtual_prefix, get_env, normalize_id } from '../utils.js'; import { create_static_module } from '../../../core/env.js'; import { env_static_public, service_worker } from '../module_ids.js'; /** * @param {string} out * @param {import('types').ValidatedKitConfig} kit * @param {import('vite').ResolvedConfig} vite_config * @param {import('types').ManifestData} manifest_data * @param {string} service_worker_entry_file * @param {import('types').Prerendered} prerendered * @param {import('vite').Manifest} client_manifest */ export async function build_service_worker( out, kit, vite_config, manifest_data, service_worker_entry_file, prerendered, client_manifest ) { const build = new Set(); for (const key in client_manifest) { const { file, css = [], assets = [] } = client_manifest[key]; build.add(file); css.forEach((file) => build.add(file)); assets.forEach((file) => build.add(file)); } // in a service worker, `location` is the location of the service worker itself, // which is guaranteed to be `<base>/service-worker.js` const base = "location.pathname.split('/').slice(0, -1).join('/')"; const service_worker_code = dedent` export const base = /*@__PURE__*/ ${base}; export const build = [ ${Array.from(build) .map((file) => `base + ${s(`/${file}`)}`) .join(',\n')} ]; export const files = [ ${manifest_data.assets .filter((asset) => kit.serviceWorker.files(asset.file)) .map((asset) => `base + ${s(`/${asset.file}`)}`) .join(',\n')} ]; export const prerendered = [ ${prerendered.paths.map((path) => `base + ${s(path.replace(kit.paths.base, ''))}`).join(',\n')} ]; export const version = ${s(kit.version.name)}; `; const env = get_env(kit.env, vite_config.mode); /** * @type {import('vite').Plugin} */ const sw_virtual_modules = { name: 'service-worker-build-virtual-modules', resolveId(id) { if (id.startsWith('$env/') || id.startsWith('$app/') || id === '$service-worker') { // ids with :$ don't work with reverse proxies like nginx return `\0virtual:${id.substring(1)}`; } }, load(id) { if (!id.startsWith('\0virtual:')) return; if (id === service_worker) { return service_worker_code; } if (id === env_static_public) { return create_static_module('$env/static/public', env.public); } const normalized_cwd = vite.normalizePath(process.cwd()); const normalized_lib = vite.normalizePath(kit.files.lib); const relative = normalize_id(id, normalized_lib, normalized_cwd); const stripped = strip_virtual_prefix(relative); throw new Error( `Cannot import ${stripped} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.` ); } }; await vite.build({ build: { modulePreload: false, rollupOptions: { input: { 'service-worker': service_worker_entry_file }, output: { // .mjs so that esbuild doesn't incorrectly inject `export` https://github.com/vitejs/vite/issues/15379 entryFileNames: 'service-worker.mjs', assetFileNames: `${kit.appDir}/immutable/assets/[name].[hash][extname]`, inlineDynamicImports: true } }, outDir: `${out}/client`, emptyOutDir: false, minify: vite_config.build.minify }, configFile: false, define: vite_config.define, publicDir: false, plugins: [sw_virtual_modules], resolve: { alias: [...get_config_aliases(kit)] }, experimental: { renderBuiltUrl(filename) { return { runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname` }; } } }); // rename .mjs to .js to avoid incorrect MIME types with ancient webservers fs.renameSync(`${out}/client/service-worker.mjs`, `${out}/client/service-worker.js`); }