Skip to content

Instantly share code, notes, and snippets.

@mizchi
Last active April 16, 2025 14:24
Show Gist options
  • Save mizchi/ff150d2dc5f7f8d45519cacaf5df06ca to your computer and use it in GitHub Desktop.
Save mizchi/ff150d2dc5f7f8d45519cacaf5df06ca to your computer and use it in GitHub Desktop.
// vite.config.ts
// src/sw.ts => /sw.js build on dev
// add to index.html: <script vite-ignore type="module">navigator.serviceWorker.register("/sw.js")</script>
import { defineConfig, Plugin } from "vite";
import path from "node:path";
import { fileURLToPath } from "node:url";
const dirname = path.dirname(fileURLToPath(import.meta.url));
function sw({
swSrc,
swPath = "/sw.js",
}: {
swSrc: string;
swPath?: string;
}): Plugin {
return {
name: "sw",
enforce: "post",
config(config) {
config.build ??= {};
config.build.rollupOptions ??= {};
config.build.rollupOptions ??= {};
const input = config.build.rollupOptions.input;
if (input == null) {
config.build.rollupOptions.input = {
main: "index.html",
sw: swSrc,
};
} else if (typeof input === "string") {
config.build!.rollupOptions!.input = {
main: input,
sw: swSrc,
};
} else if (Array.isArray(input)) {
throw new Error("[sw] Array input is not string");
} else if (
typeof config.build.rollupOptions.input === "object" &&
config.build.rollupOptions.input !== null
) {
// @ts-ignore
config.build.rollupOptions.input.sw = swSrc;
}
config.build.rollupOptions.output ??= {};
const originalEntryFileNames = (config.build.rollupOptions.output as any)
.entryFileNames;
// @ts-ignore
config.build.rollupOptions.output.entryFileNames = (chunkInfo) => {
if (chunkInfo.name === "sw") {
return swPath;
}
return originalEntryFileNames?.(chunkInfo) ?? "/assets/[name]-[hash].js";
};
},
async configureServer(server) {
server.middlewares.use(async (req, res, next) => {
if (req.url !== swPath) return next();
const resolvedSwPath = path.resolve(dirname, swSrc);
const result = await server.transformRequest(resolvedSwPath);
res.setHeader("Content-Type", "application/javascript");
res.end(result!.code);
});
},
} satisfies Plugin;
}
export default defineConfig({
plugins: [sw({ swSrc: "src/sw.ts", swPath: "/sw.js" })],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment