@vite-pwa/vitepress 1.1.0 โ†’ 2.0.0

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/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  <p align='center'>
2
- <img src='./hero.png' alt="@vite-pwa/vitepress - Zero-config PWA for VitePress"><br>
3
- Zero-config PWA Plugin for VitePress
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vite-pwa/.github/main/vitepress-hero-dark.svg" />
4
+ <img src="https://raw.githubusercontent.com/vite-pwa/.github/main/vitepress-hero.svg" alt="@vite-pwa/vitepress - Zero-config PWA for VitePress">
5
+ </picture>
4
6
  </p>
5
7
 
6
8
  <p align='center'>
7
- <a href='https://www.npmjs.com/package/@vite-pwa/vitepress' target="__blank">
9
+ <a href='https://npmx.dev/package/@vite-pwa/vitepress' target="__blank">
8
10
  <img src='https://img.shields.io/npm/v/@vite-pwa/vitepress?color=33A6B8&label=' alt="NPM version">
9
11
  </a>
10
- <a href="https://www.npmjs.com/package/@vite-pwa/vitepress" target="__blank">
12
+ <a href="https://npmx.dev/package/@vite-pwa/vitepress" target="__blank">
11
13
  <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vite-pwa/vitepress?color=476582&label=">
12
14
  </a>
13
- <a href="https://vite-pwa-org.netlify.app/frameworks/vitepress" target="__blank">
15
+ <a href="https://unplugin-pwa.netlify.app/frameworks/vitepress" target="__blank">
14
16
  <img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20guides&color=2e859c" alt="Docs & Guides">
15
17
  </a>
16
18
  <br>
@@ -23,29 +25,35 @@ Zero-config PWA Plugin for VitePress
23
25
 
24
26
  <p align="center">
25
27
  <a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
26
- <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
28
+ <img src="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg" alt="Anthony Fu SVG sponsors image"/>
27
29
  </a>
28
30
  </p>
29
31
 
30
32
  ## ๐Ÿš€ Features
31
33
 
32
- - ๐Ÿ“– [**Documentation & guides**](https://vite-pwa-org.netlify.app/)
34
+ - ๐Ÿ“– [**Documentation & guides**](https://unplugin-pwa.netlify.app/)
33
35
  - ๐Ÿ‘Œ **Zero-Config**: sensible built-in default configs for common use cases
34
36
  - ๐Ÿ”ฉ **Extensible**: expose the full ability to customize the behavior of the plugin
35
37
  - ๐Ÿฆพ **Type Strong**: written in [TypeScript](https://www.typescriptlang.org/)
36
38
  - ๐Ÿ”Œ **Offline Support**: generate service worker with offline support (via Workbox)
37
- - โšก **Fully tree shakable**: auto inject Web App Manifest
39
+ - โšก **Fully tree shakable**: client virtual modules are strictly optimized for Dead Code Elimination.
40
+ - ๐Ÿ“„ **Web Manifest**: auto-inject Web App Manifest and PWA assets seamlessly.
38
41
  - ๐Ÿ’ฌ **Prompt for new content**: built-in support for Vanilla JavaScript, Vue 3, React, Svelte, SolidJS and Preact
39
42
  - โš™๏ธ **Stale-while-revalidate**: automatic reload when new content is available
40
43
  - โœจ **Static assets handling**: configure static assets for offline support
41
44
  - ๐Ÿž **Development Support**: debug your custom service worker logic as you develop your application
42
- - ๐Ÿ› ๏ธ **Versatile**: integration with meta frameworks: [รฎles](https://github.com/ElMassimo/iles), [SvelteKit](https://github.com/sveltejs/kit), [VitePress](https://github.com/vuejs/vitepress), [Astro](https://github.com/withastro/astro), [Nuxt 3](https://github.com/nuxt/nuxt) and [Remix](https://github.com/remix-run/remix)
45
+ - ๐Ÿ” **Inspector**: visually inspect your resolved configuration, web manifest and service worker during development, via middleware or [DevFrame](https://github.com/devframes/devframe)
46
+ - ๐Ÿงฉ **Modular**: use the ready-to-use plugins or compose your own integration from the building blocks in `@unplugin-pwa/core` and `@unplugin-pwa/vite`
47
+ - ๐Ÿ“ฆ **Universal Bundlers**: native integration with Vite, Rolldown, Webpack (WIP), Rspack (WIP), and Rsbuild (WIP).
48
+ - ๐Ÿ› ๏ธ **Meta-Frameworks**: seamless integration with [รฎles](https://github.com/ElMassimo/iles), [SvelteKit](https://github.com/sveltejs/kit), [VitePress](https://github.com/vuejs/vitepress), [Astro](https://github.com/withastro/astro), [Nuxt 3/4/5](https://github.com/nuxt/nuxt), [React Router](https://github.com/remix-run/react-router/), [TanStack](https://github.com/TanStack) and [Next](https://github.com/vercel/next.js/) (WIP).
43
49
  - ๐Ÿ’ฅ **PWA Assets Generator**: generate all the PWA assets from a single command and a single source image
44
50
  - ๐Ÿš€ **PWA Assets Integration**: serving, generating and injecting PWA Assets on the fly in your application
45
51
 
46
52
  ## ๐Ÿ“ฆ Install
47
53
 
48
- > From v0.3, `@vite-pwa/vitepress` requires **Vite 5** and **VitePress 1.0.0-rc.26 or above**.
54
+ > From v2.0.0 `@vite-pwa/vitepress` using [@unplugin-pwa/vite](https://github.com/vite-pwa/unplugin-pwa/tree/main/packages/vite) and [@vite-pwa/workbox-build](https://github.com/vite-pwa/workbox/tree/main/packages/build). Requires Node 22.14.0 or above.
55
+
56
+ > From v0.3.0, `@vite-pwa/vitepress` requires **Vite 5** and **VitePress 1.0.0-rc.26 or above**.
49
57
 
50
58
  > Using any version older than v0.3 requires Vite 3.1.0+.
51
59
 
package/dist/index.d.mts CHANGED
@@ -1,24 +1,11 @@
1
- import { DefaultTheme, UserConfigExport } from 'vitepress';
2
- import { VitePWAOptions } from 'vite-plugin-pwa';
3
-
4
- interface PwaOptions extends Partial<VitePWAOptions> {
5
- experimental?: {
6
- /**
7
- * When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
8
- *
9
- * @see https://github.com/vite-pwa/vitepress/issues/22
10
- *
11
- * @default false
12
- */
13
- includeAllowlist?: boolean;
14
- };
15
- }
1
+ import { PwaOptions, VitePressExperimentalOptions } from "./types.mjs";
2
+ import { VitePWAStrategy } from "@unplugin-pwa/core";
3
+ import { SWType } from "@vite-pwa/workbox-build/types";
4
+ import { DefaultTheme, UserConfigExport } from "vitepress";
5
+ export declare function withPwa<UserStrategy extends VitePWAStrategy, T extends SWType, VPTheme = DefaultTheme.Config>(config: UserConfigExport<VPTheme>): Promise<UserConfigExport<VPTheme>>;
16
6
  declare module 'vitepress' {
17
- interface UserConfig {
18
- pwa?: PwaOptions;
19
- }
7
+ interface UserConfig {
8
+ pwa?: Partial<PwaOptions<VitePWAStrategy, SWType>>;
9
+ }
20
10
  }
21
-
22
- declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
23
-
24
- export { type PwaOptions, withPwa };
11
+ export type { PwaOptions, VitePressExperimentalOptions };
package/dist/index.mjs CHANGED
@@ -1,176 +1,165 @@
1
- import { VitePWA } from 'vite-plugin-pwa';
2
- import { resolve } from 'node:path';
3
-
1
+ import { BuildPwaAssetsPlugin } from "@unplugin-pwa/vite/plugins/build-pwa-assets";
2
+ import { BuildRegisterSWPlugin } from "@unplugin-pwa/vite/plugins/build-register-sw";
3
+ import { DevPlugin } from "@unplugin-pwa/vite/plugins/dev";
4
+ import { DevMiddlewarePlugin } from "@unplugin-pwa/vite/plugins/dev-middleware";
5
+ import { DevAssetsMiddlewarePlugin } from "@unplugin-pwa/vite/plugins/dev-pwa-assets-middleware";
6
+ import { DevtoolsPlugin } from "@unplugin-pwa/vite/plugins/devtools";
7
+ import { InfoPlugin } from "@unplugin-pwa/vite/plugins/info";
8
+ import { InspectorPlugin } from "@unplugin-pwa/vite/plugins/inspector";
9
+ import { MainPlugin } from "@unplugin-pwa/vite/plugins/main";
10
+ import { AssetsPlugin } from "@unplugin-pwa/vite/plugins/pwa-assets";
11
+ import { VirtualModulesPlugin } from "@unplugin-pwa/vite/plugins/virtual-modules";
12
+ import path from "node:path";
13
+ import { generateRegisterSW } from "@unplugin-pwa/core/generate-register-sw";
14
+ import { createVitePWAContext } from "@unplugin-pwa/vite/vite-context";
15
+ // src/utils.ts
4
16
  function escapeStringRegexp(value) {
5
- return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
17
+ return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
6
18
  }
7
-
8
- function configurePWAOptions(config) {
9
- const pwa = config.pwa ?? {};
10
- const assetsDir = config.assetsDir ? config.assetsDir.replace(/\\/g, "/").replace(/^\.?\/|\/$/g, "") : "assets";
11
- const dontCacheBustURLsMatching = new RegExp(`^${escapeStringRegexp(assetsDir)}/`);
12
- if (!pwa.outDir)
13
- pwa.outDir = ".vitepress/dist";
14
- if (pwa.pwaAssets) {
15
- const publicDir = typeof config.vite?.publicDir === "string" ? resolve(config.vite.publicDir) : resolve("public");
16
- pwa.pwaAssets.integration = {
17
- baseUrl: config.base ?? config.vite?.base ?? "/",
18
- publicDir,
19
- outDir: resolve(pwa.outDir)
20
- };
21
- }
22
- if (pwa.strategies === "injectManifest") {
23
- pwa.injectManifest = pwa.injectManifest ?? {};
24
- pwa.injectManifest.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
25
- } else {
26
- pwa.workbox = pwa.workbox ?? {};
27
- pwa.workbox.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
28
- if (pwa.registerType === "autoUpdate" && (pwa.injectRegister === "script" || pwa.injectRegister === "script-defer" || pwa.injectRegister === "inline")) {
29
- pwa.workbox.clientsClaim = true;
30
- pwa.workbox.skipWaiting = true;
31
- }
32
- }
33
- return pwa;
19
+ // src/create-context.ts
20
+ function createVitePressPWAContext(config) {
21
+ const pwa = config.pwa ?? {};
22
+ const ctx = Object.assign(createVitePWAContext(true, pwa), { vitepress: {
23
+ runtimeCachingAdded: false,
24
+ experimental: void 0
25
+ } });
26
+ ctx.configurePWAOptions = (_, viteResolvedConfig) => {
27
+ const vp = ctx.consumerOptions;
28
+ if (vp.experimental?.includeAllowlist) ctx.vitepress.experimental = { includeAllowlist: vp.experimental?.includeAllowlist };
29
+ else ctx.vitepress.experimental = { includeAllowlist: false };
30
+ ctx.base = config.base || "/";
31
+ if (!(viteResolvedConfig.command === "build")) return;
32
+ if (ctx.strategy === "generate-sw" && ctx.vitepress.experimental.includeAllowlist && !ctx.vitepress.runtimeCachingAdded) {
33
+ ctx.vitepress.runtimeCachingAdded = true;
34
+ ctx.resolvedOptions.generateSW ??= {};
35
+ const generateSW = ctx.resolvedOptions.generateSW;
36
+ generateSW.runtimeCaching ??= [];
37
+ generateSW.runtimeCaching.push({
38
+ urlPattern: ({ request, sameOrigin }) => {
39
+ return sameOrigin && request.mode === "navigate";
40
+ },
41
+ handler: "NetworkOnly",
42
+ options: { plugins: [{
43
+ handlerDidError: async () => Response.redirect("404", 302),
44
+ cacheWillUpdate: async () => null
45
+ }] }
46
+ });
47
+ }
48
+ const outDir = config.outDir ?? ".vitepress/dist";
49
+ const immutableAssets = config.assetsDir ? config.assetsDir.replace(/\\/g, "/").replace(/^\.?\/|\/$/g, "") : "assets";
50
+ const base = config.base ?? config.vite?.base ?? "/";
51
+ ctx.resolvedOptions.base = base;
52
+ ctx.resolvedOptions.scope = base;
53
+ if (ctx.resolvedOptions.pwaAssets) {
54
+ const publicDir = typeof config.vite?.publicDir === "string" ? path.resolve(config.vite.publicDir) : path.resolve("public");
55
+ ctx.resolvedOptions.pwaAssets.integration = {
56
+ baseUrl: base,
57
+ publicDir,
58
+ outDir: path.resolve(outDir)
59
+ };
60
+ }
61
+ return {
62
+ outDir,
63
+ immutableAssets,
64
+ cwd: viteResolvedConfig.root
65
+ };
66
+ };
67
+ const consumerTransformHead = config.transformHead;
68
+ config.transformHead = async (vpCtx) => {
69
+ const head = await consumerTransformHead?.(vpCtx) ?? [];
70
+ const assetsGenerator = await ctx.pwaAssetsGenerator;
71
+ if (assetsGenerator) {
72
+ const htmlAssets = assetsGenerator.resolveHtmlAssets();
73
+ if (htmlAssets.themeColor) head.push(["meta", {
74
+ name: "theme-color",
75
+ content: htmlAssets.themeColor.content
76
+ }]);
77
+ for (const link of htmlAssets.links) head.push(["link", { ...link }]);
78
+ }
79
+ const webManifestData = ctx.webManifestData();
80
+ if (webManifestData) {
81
+ const href = webManifestData.href;
82
+ if (webManifestData.useCredentials) head.push(["link", {
83
+ rel: "manifest",
84
+ href,
85
+ crossorigin: "use-credentials"
86
+ }]);
87
+ else head.push(["link", {
88
+ rel: "manifest",
89
+ href
90
+ }]);
91
+ }
92
+ const registerSWData = await ctx.registerSWData();
93
+ if (registerSWData && registerSWData.shouldRegisterSW) {
94
+ if (registerSWData.mode === "inline") {
95
+ const content = await generateRegisterSW(ctx);
96
+ if (registerSWData.module) head.push([
97
+ "script",
98
+ {
99
+ id: "vite-pwa:vitepress:inline-sw",
100
+ type: "module"
101
+ },
102
+ content
103
+ ]);
104
+ else head.push([
105
+ "script",
106
+ { id: "vite-pwa:vitepress:inline-sw" },
107
+ content
108
+ ]);
109
+ } else if (registerSWData.mode === "script-defer") head.push(["script", {
110
+ id: "vite-pwa:vitepress:register-sw",
111
+ defer: "defer",
112
+ src: registerSWData.registerPath
113
+ }]);
114
+ else head.push(["script", {
115
+ id: "vite-pwa:vitepress:register-sw",
116
+ src: registerSWData.registerPath
117
+ }]);
118
+ }
119
+ return head;
120
+ };
121
+ const consumerBuildEnd = config.buildEnd;
122
+ config.buildEnd = async (siteConfig) => {
123
+ await consumerBuildEnd?.(siteConfig);
124
+ if (!ctx.resolvedOptions.disable) {
125
+ if (ctx.strategy === "generate-sw" && ctx.vitepress.experimental.includeAllowlist) {
126
+ const generateSW = ctx.resolvedOptions.generateSW ?? {};
127
+ const allowlist = generateSW.navigateFallbackAllowlist ??= [];
128
+ const base = siteConfig.site.base ?? "/";
129
+ for (const page of siteConfig.pages) {
130
+ const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
131
+ allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
132
+ }
133
+ }
134
+ await ctx.runBuild();
135
+ }
136
+ };
137
+ return ctx;
34
138
  }
35
-
139
+ // src/integration.ts
36
140
  function withUserConfig(config) {
37
- let viteConf = config.vite;
38
- if (!viteConf) {
39
- viteConf = {};
40
- config.vite = viteConf;
41
- }
42
- let vitePlugins = viteConf.plugins;
43
- if (typeof vitePlugins === "undefined") {
44
- vitePlugins = [];
45
- viteConf.plugins = vitePlugins;
46
- }
47
- if (vitePlugins && vitePlugins.length > 0) {
48
- const pwaPlugin = vitePlugins.find((i) => i && typeof i === "object" && "name" in i && i.name === "vite-plugin-pwa");
49
- if (pwaPlugin)
50
- throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in VitePress config file");
51
- }
52
- const pwa = configurePWAOptions(config);
53
- let api;
54
- vitePlugins.push(VitePWA({ ...pwa }));
55
- vitePlugins.push({
56
- name: "vite-plugin-pwa:pwa-assets:vitepress",
57
- apply: "serve",
58
- enforce: "pre",
59
- configResolved(resolvedViteConfig) {
60
- if (!resolvedViteConfig.build.ssr)
61
- api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
62
- },
63
- async handleHotUpdate({ file, server }) {
64
- const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
65
- if (await pwaAssetsGenerator?.checkHotUpdate(file))
66
- await server.restart();
67
- }
68
- });
69
- vitePlugins.push({
70
- name: "vite-plugin-pwa:vitepress",
71
- apply: "build",
72
- enforce: "post",
73
- configResolved(resolvedViteConfig) {
74
- if (!resolvedViteConfig.build.ssr)
75
- api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
76
- }
77
- });
78
- const vitePressConfig = config;
79
- const userTransformHead = vitePressConfig.transformHead;
80
- const userBuildEnd = vitePressConfig.buildEnd;
81
- vitePressConfig.transformHead = async (ctx) => {
82
- const head = await userTransformHead?.(ctx) ?? [];
83
- const assetsGenerator = await api?.pwaAssetsGenerator();
84
- if (assetsGenerator) {
85
- const htmlAssets = assetsGenerator.resolveHtmlAssets();
86
- if (htmlAssets.themeColor)
87
- head.push(["meta", { name: "theme-color", content: htmlAssets.themeColor.content }]);
88
- for (const link of htmlAssets.links)
89
- head.push(["link", { ...link }]);
90
- }
91
- const webManifestData = api?.webManifestData();
92
- if (webManifestData) {
93
- const href = webManifestData.href;
94
- if (webManifestData.useCredentials)
95
- head.push(["link", { rel: "manifest", href, crossorigin: "use-credentials" }]);
96
- else
97
- head.push(["link", { rel: "manifest", href }]);
98
- }
99
- const registerSWData = api?.registerSWData();
100
- if (registerSWData && registerSWData.shouldRegisterSW) {
101
- if (registerSWData.mode === "inline") {
102
- head.push([
103
- "script",
104
- { id: "vite-plugin-pwa:inline-sw" },
105
- `if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('${registerSWData.inlinePath}', { scope: '${registerSWData.scope}' })})}`
106
- ]);
107
- } else {
108
- if (registerSWData.mode === "script-defer") {
109
- head.push([
110
- "script",
111
- {
112
- id: "vite-plugin-pwa:register-sw",
113
- defer: "defer",
114
- src: registerSWData.registerPath
115
- }
116
- ]);
117
- } else {
118
- head.push([
119
- "script",
120
- {
121
- id: "vite-plugin-pwa:register-sw",
122
- src: registerSWData.registerPath
123
- }
124
- ]);
125
- }
126
- }
127
- }
128
- return head;
129
- };
130
- let allowlist;
131
- if (pwa.strategies !== "injectManifest" && pwa.experimental?.includeAllowlist === true) {
132
- pwa.workbox = pwa.workbox ?? {};
133
- allowlist = pwa.workbox.navigateFallbackAllowlist = pwa.workbox.navigateFallbackAllowlist ?? [];
134
- pwa.workbox.runtimeCaching = pwa.workbox.runtimeCaching ?? [];
135
- pwa.workbox.runtimeCaching.push({
136
- urlPattern: ({ request, sameOrigin }) => {
137
- return sameOrigin && request.mode === "navigate";
138
- },
139
- handler: "NetworkOnly",
140
- options: {
141
- plugins: [{
142
- /* this callback will be called when the fetch call fails */
143
- handlerDidError: async () => Response.redirect("404", 302),
144
- /* this callback will prevent caching the response */
145
- cacheWillUpdate: async () => null
146
- }]
147
- }
148
- });
149
- }
150
- vitePressConfig.buildEnd = async (siteConfig) => {
151
- await userBuildEnd?.(siteConfig);
152
- if (api && !api.disabled) {
153
- if (typeof allowlist !== "undefined") {
154
- const base = siteConfig.site.base ?? "/";
155
- for (const page of siteConfig.pages) {
156
- const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
157
- allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
158
- }
159
- }
160
- await api.generateSW();
161
- }
162
- };
163
- return vitePressConfig;
141
+ const ctx = createVitePressPWAContext(config);
142
+ const viteConf = config.vite ??= {};
143
+ (viteConf.plugins ??= []).push([
144
+ MainPlugin(ctx),
145
+ VirtualModulesPlugin(ctx),
146
+ InfoPlugin(ctx),
147
+ DevPlugin(ctx),
148
+ DevMiddlewarePlugin(ctx),
149
+ DevAssetsMiddlewarePlugin(ctx),
150
+ AssetsPlugin(ctx),
151
+ BuildRegisterSWPlugin(ctx),
152
+ BuildPwaAssetsPlugin(ctx),
153
+ DevtoolsPlugin(ctx),
154
+ InspectorPlugin(ctx)
155
+ ]);
156
+ return config;
164
157
  }
165
-
158
+ // src/index.ts
166
159
  async function withPwa(config) {
167
- if (typeof config === "function") {
168
- return async (ctx) => {
169
- const userConfig = await config(ctx);
170
- return withUserConfig(userConfig);
171
- };
172
- }
173
- return withUserConfig(await config);
160
+ if (typeof config === "function") return async (ctx) => {
161
+ return withUserConfig(await config(ctx));
162
+ };
163
+ return withUserConfig(await config);
174
164
  }
175
-
176
165
  export { withPwa };
@@ -0,0 +1,15 @@
1
+ import { VitePWAOptions, VitePWAStrategy } from "@unplugin-pwa/core";
2
+ import { SWType } from "@vite-pwa/workbox-build/types";
3
+ export interface VitePressExperimentalOptions {
4
+ /**
5
+ * When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
6
+ *
7
+ * @see https://github.com/vite-pwa/vitepress/issues/22
8
+ *
9
+ * @default false
10
+ */
11
+ includeAllowlist?: boolean;
12
+ }
13
+ export type PwaOptions<UserStrategy extends VitePWAStrategy, T extends SWType> = VitePWAOptions<UserStrategy, T> & {
14
+ experimental?: VitePressExperimentalOptions;
15
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vite-pwa/vitepress",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "2.0.0",
5
5
  "description": "Zero-config PWA for VitePress",
6
6
  "author": "antfu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -17,51 +17,75 @@
17
17
  "workbox",
18
18
  "pwa",
19
19
  "vite",
20
- "vite-plugin"
20
+ "unplugin-pwa"
21
21
  ],
22
+ "sideEffects": false,
22
23
  "exports": {
23
- ".": {
24
- "types": "./dist/index.d.ts",
25
- "default": "./dist/index.mjs"
24
+ ".": "./dist/index.mjs",
25
+ "./types": {
26
+ "types": "./dist/index.d.mts"
26
27
  },
27
- "./package.json": "./package.json",
28
- "./dist/*": "./dist/*"
28
+ "./package.json": "./package.json"
29
29
  },
30
- "main": "dist/index.mjs",
31
- "module": "dist/index.mjs",
32
- "types": "dist/index.d.ts",
30
+ "types": "dist/index.d.mts",
33
31
  "files": [
34
- "*.d.ts",
35
32
  "dist"
36
33
  ],
34
+ "engines": {
35
+ "node": ">=22.14.0"
36
+ },
37
37
  "peerDependencies": {
38
- "@vite-pwa/assets-generator": "^1.0.0",
39
- "vite-plugin-pwa": "^1.2.0"
38
+ "@vite-pwa/assets-generator": "^1.0.0 || ^2.0.0",
39
+ "magicast": "^0.5.0",
40
+ "rolldown": "^1.0.0-0",
41
+ "vitepress": "^1.0.0 || ^2.0.0-0"
40
42
  },
41
43
  "peerDependenciesMeta": {
42
44
  "@vite-pwa/assets-generator": {
43
45
  "optional": true
46
+ },
47
+ "magicast": {
48
+ "optional": true
49
+ },
50
+ "rolldown": {
51
+ "optional": true
44
52
  }
45
53
  },
54
+ "dependencies": {
55
+ "@unplugin-pwa/core": "^0.0.2",
56
+ "@unplugin-pwa/inspector": "^0.0.2",
57
+ "@unplugin-pwa/vite": "^0.0.2",
58
+ "@vite-pwa/workbox-build": "^8.0.13",
59
+ "@vite-pwa/workbox-swkit": "^8.0.13",
60
+ "@vite-pwa/workbox-window": "^8.0.13"
61
+ },
46
62
  "devDependencies": {
47
- "@antfu/eslint-config": "^4.11.0",
48
- "@antfu/ni": "^0.21.9",
49
- "@types/debug": "^4.1.12",
50
- "@types/node": "^20.8.7",
51
- "@typescript-eslint/eslint-plugin": "^6.11.0",
52
- "bumpp": "^9.2.0",
53
- "eslint": "^9.23.0",
54
- "https-localhost": "^4.7.1",
55
- "typescript": "^5.4.5",
56
- "unbuild": "^2.0.0",
57
- "vite": "^5.2.10",
58
- "vite-plugin-pwa": "^1.2.0",
59
- "vitepress": "^1.1.4"
63
+ "@antfu/eslint-config": "^9.5.1",
64
+ "@antfu/ni": "^25.0.0",
65
+ "@arethetypeswrong/core": "^0.18.5",
66
+ "@types/debug": "^4.1.13",
67
+ "@types/node": "24.19.2",
68
+ "@vite-pwa/assets-generator": "^2.0.0",
69
+ "@vitejs/devtools": "^0.7.6",
70
+ "eslint": "^10.13.0",
71
+ "eslint-plugin-antfu": "^3.2.3",
72
+ "https-localhost": "4.7.2",
73
+ "publint": "^0.3.25",
74
+ "taze": "21.1.0",
75
+ "tsdown": "^0.23.1",
76
+ "typescript": "~6.0.3",
77
+ "vite": "^8.3.5",
78
+ "vitepress": "^2.0.0-alpha.21"
79
+ },
80
+ "publishConfig": {
81
+ "access": "public",
82
+ "provenance": true
60
83
  },
61
84
  "scripts": {
62
- "build": "unbuild",
63
85
  "lint": "eslint .",
64
- "lint:fix": "nr lint --fix",
65
- "release": "bumpp"
86
+ "lint:fix": "pnpm lint --fix",
87
+ "update:deps": "taze -I",
88
+ "build": "tsdown",
89
+ "test:typecheck": "tsc --noEmit"
66
90
  }
67
91
  }
package/dist/index.cjs DELETED
@@ -1,178 +0,0 @@
1
- 'use strict';
2
-
3
- const vitePluginPwa = require('vite-plugin-pwa');
4
- const node_path = require('node:path');
5
-
6
- function escapeStringRegexp(value) {
7
- return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
8
- }
9
-
10
- function configurePWAOptions(config) {
11
- const pwa = config.pwa ?? {};
12
- const assetsDir = config.assetsDir ? config.assetsDir.replace(/\\/g, "/").replace(/^\.?\/|\/$/g, "") : "assets";
13
- const dontCacheBustURLsMatching = new RegExp(`^${escapeStringRegexp(assetsDir)}/`);
14
- if (!pwa.outDir)
15
- pwa.outDir = ".vitepress/dist";
16
- if (pwa.pwaAssets) {
17
- const publicDir = typeof config.vite?.publicDir === "string" ? node_path.resolve(config.vite.publicDir) : node_path.resolve("public");
18
- pwa.pwaAssets.integration = {
19
- baseUrl: config.base ?? config.vite?.base ?? "/",
20
- publicDir,
21
- outDir: node_path.resolve(pwa.outDir)
22
- };
23
- }
24
- if (pwa.strategies === "injectManifest") {
25
- pwa.injectManifest = pwa.injectManifest ?? {};
26
- pwa.injectManifest.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
27
- } else {
28
- pwa.workbox = pwa.workbox ?? {};
29
- pwa.workbox.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
30
- if (pwa.registerType === "autoUpdate" && (pwa.injectRegister === "script" || pwa.injectRegister === "script-defer" || pwa.injectRegister === "inline")) {
31
- pwa.workbox.clientsClaim = true;
32
- pwa.workbox.skipWaiting = true;
33
- }
34
- }
35
- return pwa;
36
- }
37
-
38
- function withUserConfig(config) {
39
- let viteConf = config.vite;
40
- if (!viteConf) {
41
- viteConf = {};
42
- config.vite = viteConf;
43
- }
44
- let vitePlugins = viteConf.plugins;
45
- if (typeof vitePlugins === "undefined") {
46
- vitePlugins = [];
47
- viteConf.plugins = vitePlugins;
48
- }
49
- if (vitePlugins && vitePlugins.length > 0) {
50
- const pwaPlugin = vitePlugins.find((i) => i && typeof i === "object" && "name" in i && i.name === "vite-plugin-pwa");
51
- if (pwaPlugin)
52
- throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in VitePress config file");
53
- }
54
- const pwa = configurePWAOptions(config);
55
- let api;
56
- vitePlugins.push(vitePluginPwa.VitePWA({ ...pwa }));
57
- vitePlugins.push({
58
- name: "vite-plugin-pwa:pwa-assets:vitepress",
59
- apply: "serve",
60
- enforce: "pre",
61
- configResolved(resolvedViteConfig) {
62
- if (!resolvedViteConfig.build.ssr)
63
- api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
64
- },
65
- async handleHotUpdate({ file, server }) {
66
- const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
67
- if (await pwaAssetsGenerator?.checkHotUpdate(file))
68
- await server.restart();
69
- }
70
- });
71
- vitePlugins.push({
72
- name: "vite-plugin-pwa:vitepress",
73
- apply: "build",
74
- enforce: "post",
75
- configResolved(resolvedViteConfig) {
76
- if (!resolvedViteConfig.build.ssr)
77
- api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
78
- }
79
- });
80
- const vitePressConfig = config;
81
- const userTransformHead = vitePressConfig.transformHead;
82
- const userBuildEnd = vitePressConfig.buildEnd;
83
- vitePressConfig.transformHead = async (ctx) => {
84
- const head = await userTransformHead?.(ctx) ?? [];
85
- const assetsGenerator = await api?.pwaAssetsGenerator();
86
- if (assetsGenerator) {
87
- const htmlAssets = assetsGenerator.resolveHtmlAssets();
88
- if (htmlAssets.themeColor)
89
- head.push(["meta", { name: "theme-color", content: htmlAssets.themeColor.content }]);
90
- for (const link of htmlAssets.links)
91
- head.push(["link", { ...link }]);
92
- }
93
- const webManifestData = api?.webManifestData();
94
- if (webManifestData) {
95
- const href = webManifestData.href;
96
- if (webManifestData.useCredentials)
97
- head.push(["link", { rel: "manifest", href, crossorigin: "use-credentials" }]);
98
- else
99
- head.push(["link", { rel: "manifest", href }]);
100
- }
101
- const registerSWData = api?.registerSWData();
102
- if (registerSWData && registerSWData.shouldRegisterSW) {
103
- if (registerSWData.mode === "inline") {
104
- head.push([
105
- "script",
106
- { id: "vite-plugin-pwa:inline-sw" },
107
- `if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('${registerSWData.inlinePath}', { scope: '${registerSWData.scope}' })})}`
108
- ]);
109
- } else {
110
- if (registerSWData.mode === "script-defer") {
111
- head.push([
112
- "script",
113
- {
114
- id: "vite-plugin-pwa:register-sw",
115
- defer: "defer",
116
- src: registerSWData.registerPath
117
- }
118
- ]);
119
- } else {
120
- head.push([
121
- "script",
122
- {
123
- id: "vite-plugin-pwa:register-sw",
124
- src: registerSWData.registerPath
125
- }
126
- ]);
127
- }
128
- }
129
- }
130
- return head;
131
- };
132
- let allowlist;
133
- if (pwa.strategies !== "injectManifest" && pwa.experimental?.includeAllowlist === true) {
134
- pwa.workbox = pwa.workbox ?? {};
135
- allowlist = pwa.workbox.navigateFallbackAllowlist = pwa.workbox.navigateFallbackAllowlist ?? [];
136
- pwa.workbox.runtimeCaching = pwa.workbox.runtimeCaching ?? [];
137
- pwa.workbox.runtimeCaching.push({
138
- urlPattern: ({ request, sameOrigin }) => {
139
- return sameOrigin && request.mode === "navigate";
140
- },
141
- handler: "NetworkOnly",
142
- options: {
143
- plugins: [{
144
- /* this callback will be called when the fetch call fails */
145
- handlerDidError: async () => Response.redirect("404", 302),
146
- /* this callback will prevent caching the response */
147
- cacheWillUpdate: async () => null
148
- }]
149
- }
150
- });
151
- }
152
- vitePressConfig.buildEnd = async (siteConfig) => {
153
- await userBuildEnd?.(siteConfig);
154
- if (api && !api.disabled) {
155
- if (typeof allowlist !== "undefined") {
156
- const base = siteConfig.site.base ?? "/";
157
- for (const page of siteConfig.pages) {
158
- const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
159
- allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
160
- }
161
- }
162
- await api.generateSW();
163
- }
164
- };
165
- return vitePressConfig;
166
- }
167
-
168
- async function withPwa(config) {
169
- if (typeof config === "function") {
170
- return async (ctx) => {
171
- const userConfig = await config(ctx);
172
- return withUserConfig(userConfig);
173
- };
174
- }
175
- return withUserConfig(await config);
176
- }
177
-
178
- exports.withPwa = withPwa;
package/dist/index.d.cts DELETED
@@ -1,24 +0,0 @@
1
- import { DefaultTheme, UserConfigExport } from 'vitepress';
2
- import { VitePWAOptions } from 'vite-plugin-pwa';
3
-
4
- interface PwaOptions extends Partial<VitePWAOptions> {
5
- experimental?: {
6
- /**
7
- * When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
8
- *
9
- * @see https://github.com/vite-pwa/vitepress/issues/22
10
- *
11
- * @default false
12
- */
13
- includeAllowlist?: boolean;
14
- };
15
- }
16
- declare module 'vitepress' {
17
- interface UserConfig {
18
- pwa?: PwaOptions;
19
- }
20
- }
21
-
22
- declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
23
-
24
- export { type PwaOptions, withPwa };
package/dist/index.d.ts DELETED
@@ -1,24 +0,0 @@
1
- import { DefaultTheme, UserConfigExport } from 'vitepress';
2
- import { VitePWAOptions } from 'vite-plugin-pwa';
3
-
4
- interface PwaOptions extends Partial<VitePWAOptions> {
5
- experimental?: {
6
- /**
7
- * When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
8
- *
9
- * @see https://github.com/vite-pwa/vitepress/issues/22
10
- *
11
- * @default false
12
- */
13
- includeAllowlist?: boolean;
14
- };
15
- }
16
- declare module 'vitepress' {
17
- interface UserConfig {
18
- pwa?: PwaOptions;
19
- }
20
- }
21
-
22
- declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
23
-
24
- export { type PwaOptions, withPwa };
package/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './dist'