@serwist/next 9.0.0-preview.8 → 9.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/dist/chunks/schema.js +20 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -36
- package/dist/index.schema.d.ts +3 -0
- package/dist/index.schema.d.ts.map +1 -0
- package/dist/index.schema.js +4 -0
- package/dist/index.worker.js +28 -17
- package/dist/lib/find-first-truthy.d.ts.map +1 -0
- package/dist/lib/get-content-hash.d.ts.map +1 -0
- package/dist/lib/get-file-hash.d.ts.map +1 -0
- package/dist/lib/get-package-version.d.ts.map +1 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/load-tsconfig.d.ts.map +1 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/schema.d.ts +240 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/types.d.ts +95 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/validator.d.ts +3 -0
- package/dist/lib/validator.d.ts.map +1 -0
- package/dist/worker/defaultCache.d.ts +8 -14
- package/dist/worker/defaultCache.d.ts.map +1 -1
- package/package.json +24 -26
- package/src/index.schema.ts +3 -0
- package/src/index.ts +37 -41
- package/src/lib/schema.ts +21 -0
- package/src/lib/types.ts +104 -0
- package/src/lib/validator.ts +13 -0
- package/src/worker/defaultCache.ts +264 -241
- package/dist/utils/find-first-truthy.d.ts.map +0 -1
- package/dist/utils/get-content-hash.d.ts.map +0 -1
- package/dist/utils/get-file-hash.d.ts.map +0 -1
- package/dist/utils/get-package-version.d.ts.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/load-tsconfig.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- /package/dist/{utils → lib}/find-first-truthy.d.ts +0 -0
- /package/dist/{utils → lib}/get-content-hash.d.ts +0 -0
- /package/dist/{utils → lib}/get-file-hash.d.ts +0 -0
- /package/dist/{utils → lib}/get-package-version.d.ts +0 -0
- /package/dist/{utils → lib}/index.d.ts +0 -0
- /package/dist/{utils → lib}/load-tsconfig.d.ts +0 -0
- /package/dist/{utils → lib}/logger.d.ts +0 -0
- /package/src/{utils → lib}/find-first-truthy.ts +0 -0
- /package/src/{utils → lib}/get-content-hash.ts +0 -0
- /package/src/{utils → lib}/get-file-hash.ts +0 -0
- /package/src/{utils → lib}/get-package-version.ts +0 -0
- /package/src/{utils → lib}/index.ts +0 -0
- /package/src/{utils → lib}/load-tsconfig.ts +0 -0
- /package/src/{utils → lib}/logger.ts +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { RequiredSwDestPartial, RequiredSwDestResolved } from "@serwist/build";
|
|
2
|
+
import type { Require } from "@serwist/utils";
|
|
3
|
+
import type { InjectManifestOptions as WebpackInjectManifestOptions, InjectManifestOptionsComplete as WebpackInjectManifestOptionsComplete } from "@serwist/webpack-plugin";
|
|
4
|
+
export interface InjectPartial {
|
|
5
|
+
/**
|
|
6
|
+
* Enables additional route caching when users navigate through pages with
|
|
7
|
+
* `next/link`. This improves the user experience in some cases but it
|
|
8
|
+
* also adds a bit of overhead due to additional network calls.
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
cacheOnNavigation?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Whether Serwist should be disabled.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
disable?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether `@serwist/next` should automatically register the service worker for you. If
|
|
19
|
+
* you want to register the service worker yourself, set this to `false` and run
|
|
20
|
+
* `window.serwist.register()` in `componentDidMount` or `useEffect`.
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* // app/register-pwa.tsx
|
|
24
|
+
* "use client";
|
|
25
|
+
* import { useEffect } from "react";
|
|
26
|
+
* import type { Serwist } from "@serwist/window";
|
|
27
|
+
*
|
|
28
|
+
* declare global {
|
|
29
|
+
* interface Window {
|
|
30
|
+
* serwist: Serwist;
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* export default function RegisterPWA() {
|
|
35
|
+
* useEffect(() => {
|
|
36
|
+
* if ("serviceWorker" in navigator && window.serwist !== undefined) {
|
|
37
|
+
* window.serwist.register();
|
|
38
|
+
* }
|
|
39
|
+
* }, []);
|
|
40
|
+
* return <></>;
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* // app/layout.tsx
|
|
44
|
+
* import RegisterPWA from "./register-pwa";
|
|
45
|
+
*
|
|
46
|
+
* export default function RootLayout({
|
|
47
|
+
* children,
|
|
48
|
+
* }: {
|
|
49
|
+
* children: React.ReactNode;
|
|
50
|
+
* }) {
|
|
51
|
+
* return (
|
|
52
|
+
* <html lang="en">
|
|
53
|
+
* <head />
|
|
54
|
+
* <body>
|
|
55
|
+
* <RegisterPWA />
|
|
56
|
+
* {children}
|
|
57
|
+
* </body>
|
|
58
|
+
* </html>
|
|
59
|
+
* );
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
register?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Whether Serwist should reload the app when it goes online.
|
|
67
|
+
* @default true
|
|
68
|
+
*/
|
|
69
|
+
reloadOnOnline?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The service worker's URL scope. Set to `/foo/` so that paths under `/foo/` are under the service
|
|
72
|
+
* worker's control while others are not.
|
|
73
|
+
* @default nextConfig.basePath
|
|
74
|
+
*/
|
|
75
|
+
scope?: string;
|
|
76
|
+
/**
|
|
77
|
+
* The URL to the service worker.
|
|
78
|
+
* @default "/sw.js"
|
|
79
|
+
*/
|
|
80
|
+
swUrl?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Files in the public directory matching any of these patterns
|
|
83
|
+
* will be included in the precache manifest. For more information,
|
|
84
|
+
* see [`node-glob`'s Glob Primer](https://github.com/isaacs/node-glob#glob-primer).
|
|
85
|
+
* @default
|
|
86
|
+
* ```
|
|
87
|
+
* ["**\/*"]
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
globPublicPatterns?: string[];
|
|
91
|
+
}
|
|
92
|
+
export type InjectResolved = Require<InjectPartial, "cacheOnNavigation" | "disable" | "register" | "reloadOnOnline" | "swUrl" | "globPublicPatterns">;
|
|
93
|
+
export type InjectManifestOptions = Omit<WebpackInjectManifestOptions & RequiredSwDestPartial & InjectPartial, "disablePrecacheManifest">;
|
|
94
|
+
export type InjectManifestOptionsComplete = Omit<WebpackInjectManifestOptionsComplete & RequiredSwDestResolved & InjectResolved, "disablePrecacheManifest">;
|
|
95
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EACV,qBAAqB,IAAI,4BAA4B,EACrD,6BAA6B,IAAI,oCAAoC,EACtE,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,EAAE,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,gBAAgB,GAAG,OAAO,GAAG,oBAAoB,CAAC,CAAC;AAEtJ,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,4BAA4B,GAAG,qBAAqB,GAAG,aAAa,EAAE,yBAAyB,CAAC,CAAC;AAE1I,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAC9C,oCAAoC,GAAG,sBAAsB,GAAG,cAAc,EAC9E,yBAAyB,CAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAEhE,eAAO,MAAM,6BAA6B,UAAW,OAAO,KAAG,6BAQ9D,CAAC"}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
handler: NetworkFirst;
|
|
10
|
-
} | {
|
|
11
|
-
matcher: ({ request, url: { pathname }, sameOrigin }: import("@serwist/core").RouteMatchCallbackOptions) => boolean | undefined;
|
|
12
|
-
handler: NetworkFirst;
|
|
13
|
-
method?: undefined;
|
|
14
|
-
})[];
|
|
1
|
+
import type { RuntimeCaching } from "serwist";
|
|
2
|
+
/**
|
|
3
|
+
* The default, recommended list of caching strategies for applications
|
|
4
|
+
* built with Next.js.
|
|
5
|
+
*
|
|
6
|
+
* @see https://serwist.pages.dev/docs/next/worker-exports#default-cache
|
|
7
|
+
*/
|
|
8
|
+
export declare const defaultCache: RuntimeCaching[];
|
|
15
9
|
//# sourceMappingURL=defaultCache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultCache.d.ts","sourceRoot":"","sources":["../../src/worker/defaultCache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"defaultCache.d.ts","sourceRoot":"","sources":["../../src/worker/defaultCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK9C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,EAiQlC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serwist/next",
|
|
3
|
-
"version": "9.0.0
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A module that integrates Serwist into your Next.js application.",
|
|
6
6
|
"files": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"author": "Serwist's Team",
|
|
27
27
|
"license": "MIT",
|
|
28
|
-
"repository": "serwist/serwist",
|
|
28
|
+
"repository": "https://github.com/serwist/serwist",
|
|
29
29
|
"bugs": "https://github.com/serwist/serwist/issues",
|
|
30
30
|
"homepage": "https://serwist.pages.dev",
|
|
31
31
|
"main": "./dist/index.js",
|
|
@@ -37,6 +37,9 @@
|
|
|
37
37
|
],
|
|
38
38
|
"typings": [
|
|
39
39
|
"./dist/sw-entry.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"schema": [
|
|
42
|
+
"./dist/index.schema.d.ts"
|
|
40
43
|
]
|
|
41
44
|
}
|
|
42
45
|
},
|
|
@@ -52,43 +55,38 @@
|
|
|
52
55
|
"./typings": {
|
|
53
56
|
"types": "./dist/sw-entry.d.ts"
|
|
54
57
|
},
|
|
58
|
+
"./schema": {
|
|
59
|
+
"types": "./dist/index.schema.d.ts",
|
|
60
|
+
"default": "./dist/index.schema.js"
|
|
61
|
+
},
|
|
55
62
|
"./package.json": "./package.json"
|
|
56
63
|
},
|
|
57
64
|
"dependencies": {
|
|
58
65
|
"chalk": "5.3.0",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"@serwist/build": "9.0.0
|
|
62
|
-
"@serwist/
|
|
63
|
-
"@serwist/
|
|
64
|
-
"
|
|
65
|
-
"@serwist/strategies": "9.0.0-preview.8",
|
|
66
|
-
"@serwist/webpack-plugin": "9.0.0-preview.8",
|
|
67
|
-
"@serwist/window": "9.0.0-preview.8"
|
|
66
|
+
"glob": "10.3.12",
|
|
67
|
+
"zod": "3.22.4",
|
|
68
|
+
"@serwist/build": "9.0.0",
|
|
69
|
+
"@serwist/webpack-plugin": "9.0.0",
|
|
70
|
+
"@serwist/window": "9.0.0",
|
|
71
|
+
"serwist": "9.0.0"
|
|
68
72
|
},
|
|
69
73
|
"devDependencies": {
|
|
70
|
-
"@types/node": "20.
|
|
71
|
-
"next": "14.1
|
|
74
|
+
"@types/node": "20.12.7",
|
|
75
|
+
"next": "14.2.1",
|
|
72
76
|
"react": "18.2.0",
|
|
73
77
|
"react-dom": "18.2.0",
|
|
74
|
-
"rollup": "4.
|
|
75
|
-
"type-fest": "4.
|
|
76
|
-
"typescript": "5.
|
|
77
|
-
"webpack": "5.
|
|
78
|
-
"@serwist/
|
|
79
|
-
"@serwist/
|
|
80
|
-
"@serwist/utils": "9.0.0-preview.8"
|
|
78
|
+
"rollup": "4.14.3",
|
|
79
|
+
"type-fest": "4.15.0",
|
|
80
|
+
"typescript": "5.5.0-dev.20240415",
|
|
81
|
+
"webpack": "5.91.0",
|
|
82
|
+
"@serwist/configs": "9.0.0",
|
|
83
|
+
"@serwist/utils": "9.0.0"
|
|
81
84
|
},
|
|
82
85
|
"peerDependencies": {
|
|
83
86
|
"next": ">=14.0.0",
|
|
84
|
-
"typescript": ">=5.0.0"
|
|
85
|
-
"webpack": ">=5.9.0",
|
|
86
|
-
"@serwist/sw": "9.0.0-preview.8"
|
|
87
|
+
"typescript": ">=5.0.0"
|
|
87
88
|
},
|
|
88
89
|
"peerDependenciesMeta": {
|
|
89
|
-
"@serwist/sw": {
|
|
90
|
-
"optional": true
|
|
91
|
-
},
|
|
92
90
|
"typescript": {
|
|
93
91
|
"optional": true
|
|
94
92
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
|
|
4
|
-
import type { NextInjectManifestOptions } from "@serwist/build";
|
|
5
|
-
import { validateNextInjectManifestOptions } from "@serwist/build/next";
|
|
6
4
|
import { InjectManifest } from "@serwist/webpack-plugin";
|
|
7
5
|
import { ChildCompilationPlugin, relativeToOutputPath } from "@serwist/webpack-plugin/internal";
|
|
8
|
-
import {
|
|
9
|
-
import fg from "fast-glob";
|
|
6
|
+
import { globSync } from "glob";
|
|
10
7
|
import type { NextConfig } from "next";
|
|
11
8
|
import type { Compilation, Configuration, default as Webpack } from "webpack";
|
|
12
|
-
|
|
13
9
|
import type { ExcludeParams, SerwistNextOptions, SerwistNextOptionsKey } from "./internal-types.js";
|
|
14
|
-
import { getContentHash, getFileHash, loadTSConfig, logger } from "./
|
|
10
|
+
import { getContentHash, getFileHash, loadTSConfig, logger } from "./lib/index.js";
|
|
11
|
+
import type { InjectManifestOptions, InjectManifestOptionsComplete } from "./lib/types.js";
|
|
12
|
+
import { validateInjectManifestOptions } from "./lib/validator.js";
|
|
15
13
|
|
|
16
14
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Integrates Serwist into your Next.js app.
|
|
18
|
+
* @param userOptions
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
const withSerwistInit = (userOptions: InjectManifestOptions): ((nextConfig?: NextConfig) => NextConfig) => {
|
|
19
22
|
return (nextConfig = {}) => ({
|
|
20
23
|
...nextConfig,
|
|
21
24
|
webpack(config: Configuration, options) {
|
|
@@ -35,7 +38,7 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
35
38
|
reloadOnOnline,
|
|
36
39
|
globPublicPatterns,
|
|
37
40
|
...buildOptions
|
|
38
|
-
} =
|
|
41
|
+
} = validateInjectManifestOptions(userOptions);
|
|
39
42
|
|
|
40
43
|
if (typeof nextConfig.webpack === "function") {
|
|
41
44
|
config = nextConfig.webpack(config, options);
|
|
@@ -50,8 +53,6 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
50
53
|
config.plugins = [];
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
logger.event(`Compiling for ${options.isServer ? "server" : "client (static)"}...`);
|
|
54
|
-
|
|
55
56
|
const _sw = path.posix.join(basePath, swUrl);
|
|
56
57
|
const _scope = path.posix.join(scope, "/");
|
|
57
58
|
|
|
@@ -89,13 +90,13 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
89
90
|
if (!options.isServer) {
|
|
90
91
|
if (!register) {
|
|
91
92
|
logger.info(
|
|
92
|
-
"
|
|
93
|
+
"The service worker will not be automatically registered, please call 'window.serwist.register()' in 'componentDidMount' or 'useEffect'.",
|
|
93
94
|
);
|
|
94
95
|
|
|
95
|
-
logger.info(" window.serwist.register()");
|
|
96
|
-
|
|
97
96
|
if (!tsConfigJson?.compilerOptions?.types?.includes("@serwist/next/typings")) {
|
|
98
|
-
logger.info(
|
|
97
|
+
logger.info(
|
|
98
|
+
"You may also want to add '@serwist/next/typings' to your TypeScript/JavaScript configuration file at 'compilerOptions.types'.",
|
|
99
|
+
);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -122,7 +123,19 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
const publicDir = path.resolve(options.dir, "public");
|
|
125
|
-
const destDir = path.
|
|
126
|
+
const { dir: destDir, base: destBase } = path.parse(swDest);
|
|
127
|
+
|
|
128
|
+
const cleanUpList = globSync(["swe-worker-*.js", "swe-worker-*.js.map", destBase, `${destBase}.map`], {
|
|
129
|
+
absolute: true,
|
|
130
|
+
nodir: true,
|
|
131
|
+
cwd: destDir,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
for (const file of cleanUpList) {
|
|
135
|
+
fs.rm(file, { force: true }, (err) => {
|
|
136
|
+
if (err) throw err;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
126
139
|
|
|
127
140
|
const shouldBuildSWEntryWorker = cacheOnNavigation;
|
|
128
141
|
let swEntryPublicPath: string | undefined = undefined;
|
|
@@ -146,35 +159,17 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
146
159
|
} satisfies Record<`${SerwistNextOptionsKey}.${Extract<keyof SerwistNextOptions, "swEntryWorker">}`, string | undefined>),
|
|
147
160
|
);
|
|
148
161
|
|
|
149
|
-
logger.
|
|
150
|
-
logger.info(` URL: ${_sw}`);
|
|
151
|
-
logger.info(` Scope: ${_scope}`);
|
|
152
|
-
|
|
153
|
-
config.plugins.push(
|
|
154
|
-
new CleanWebpackPlugin({
|
|
155
|
-
cleanOnceBeforeBuildPatterns: [path.join(destDir, "swe-worker-*.js"), path.join(destDir, "swe-worker-*.js.map"), swDest],
|
|
156
|
-
}),
|
|
157
|
-
);
|
|
162
|
+
logger.event(`Bundling the service worker script with the URL '${_sw}' and the scope '${_scope}'...`);
|
|
158
163
|
|
|
159
164
|
// Precache files in public folder
|
|
160
165
|
let resolvedManifestEntries = additionalPrecacheEntries;
|
|
161
166
|
|
|
162
167
|
if (!resolvedManifestEntries) {
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
[
|
|
167
|
-
|
|
168
|
-
// Forcibly include these in case the user outputs these files to `public`.
|
|
169
|
-
"!swe-worker-*.js",
|
|
170
|
-
"!swe-worker-*.js.map",
|
|
171
|
-
`!${swDestFileName.replace(/^\/+/, "")}`,
|
|
172
|
-
`!${swDestFileName.replace(/^\/+/, "")}.map`,
|
|
173
|
-
],
|
|
174
|
-
{
|
|
175
|
-
cwd: publicDir,
|
|
176
|
-
},
|
|
177
|
-
);
|
|
168
|
+
const publicScan = globSync(globPublicPatterns, {
|
|
169
|
+
nodir: true,
|
|
170
|
+
cwd: publicDir,
|
|
171
|
+
ignore: ["swe-worker-*.js", destBase, `${destBase}.map`],
|
|
172
|
+
});
|
|
178
173
|
resolvedManifestEntries = publicScan.map((f) => ({
|
|
179
174
|
url: path.posix.join(basePath, f),
|
|
180
175
|
revision: getFileHash(path.join(publicDir, f)),
|
|
@@ -238,4 +233,5 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
|
|
|
238
233
|
};
|
|
239
234
|
|
|
240
235
|
export default withSerwistInit;
|
|
241
|
-
export
|
|
236
|
+
export { validateInjectManifestOptions };
|
|
237
|
+
export type { InjectManifestOptions as PluginOptions, InjectManifestOptionsComplete as PluginOptionsComplete };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { requiredSwDestPartial } from "@serwist/build/schema";
|
|
2
|
+
import { injectManifestOptions as webpackInjectManifestOptions } from "@serwist/webpack-plugin/schema";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
export const injectPartial = z
|
|
6
|
+
.object({
|
|
7
|
+
cacheOnNavigation: z.boolean().default(false),
|
|
8
|
+
disable: z.boolean().default(false),
|
|
9
|
+
register: z.boolean().default(true),
|
|
10
|
+
reloadOnOnline: z.boolean().default(true),
|
|
11
|
+
scope: z.string().optional(),
|
|
12
|
+
swUrl: z.string().default("/sw.js"),
|
|
13
|
+
globPublicPatterns: z.array(z.string()).default(["**/*"]),
|
|
14
|
+
})
|
|
15
|
+
.strict("Do not pass invalid properties to NextInjectManifestPartial!");
|
|
16
|
+
|
|
17
|
+
export const injectManifestOptions = webpackInjectManifestOptions
|
|
18
|
+
.merge(requiredSwDestPartial)
|
|
19
|
+
.merge(injectPartial)
|
|
20
|
+
.omit({ disablePrecacheManifest: true })
|
|
21
|
+
.strict("Do not pass invalid properties to NextInjectManifestOptions!");
|
package/src/lib/types.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { RequiredSwDestPartial, RequiredSwDestResolved } from "@serwist/build";
|
|
2
|
+
import type { Require } from "@serwist/utils";
|
|
3
|
+
import type {
|
|
4
|
+
InjectManifestOptions as WebpackInjectManifestOptions,
|
|
5
|
+
InjectManifestOptionsComplete as WebpackInjectManifestOptionsComplete,
|
|
6
|
+
} from "@serwist/webpack-plugin";
|
|
7
|
+
|
|
8
|
+
export interface InjectPartial {
|
|
9
|
+
/**
|
|
10
|
+
* Enables additional route caching when users navigate through pages with
|
|
11
|
+
* `next/link`. This improves the user experience in some cases but it
|
|
12
|
+
* also adds a bit of overhead due to additional network calls.
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
cacheOnNavigation?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether Serwist should be disabled.
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
disable?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether `@serwist/next` should automatically register the service worker for you. If
|
|
23
|
+
* you want to register the service worker yourself, set this to `false` and run
|
|
24
|
+
* `window.serwist.register()` in `componentDidMount` or `useEffect`.
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // app/register-pwa.tsx
|
|
28
|
+
* "use client";
|
|
29
|
+
* import { useEffect } from "react";
|
|
30
|
+
* import type { Serwist } from "@serwist/window";
|
|
31
|
+
*
|
|
32
|
+
* declare global {
|
|
33
|
+
* interface Window {
|
|
34
|
+
* serwist: Serwist;
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* export default function RegisterPWA() {
|
|
39
|
+
* useEffect(() => {
|
|
40
|
+
* if ("serviceWorker" in navigator && window.serwist !== undefined) {
|
|
41
|
+
* window.serwist.register();
|
|
42
|
+
* }
|
|
43
|
+
* }, []);
|
|
44
|
+
* return <></>;
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* // app/layout.tsx
|
|
48
|
+
* import RegisterPWA from "./register-pwa";
|
|
49
|
+
*
|
|
50
|
+
* export default function RootLayout({
|
|
51
|
+
* children,
|
|
52
|
+
* }: {
|
|
53
|
+
* children: React.ReactNode;
|
|
54
|
+
* }) {
|
|
55
|
+
* return (
|
|
56
|
+
* <html lang="en">
|
|
57
|
+
* <head />
|
|
58
|
+
* <body>
|
|
59
|
+
* <RegisterPWA />
|
|
60
|
+
* {children}
|
|
61
|
+
* </body>
|
|
62
|
+
* </html>
|
|
63
|
+
* );
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
* @default true
|
|
67
|
+
*/
|
|
68
|
+
register?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Whether Serwist should reload the app when it goes online.
|
|
71
|
+
* @default true
|
|
72
|
+
*/
|
|
73
|
+
reloadOnOnline?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The service worker's URL scope. Set to `/foo/` so that paths under `/foo/` are under the service
|
|
76
|
+
* worker's control while others are not.
|
|
77
|
+
* @default nextConfig.basePath
|
|
78
|
+
*/
|
|
79
|
+
scope?: string;
|
|
80
|
+
/**
|
|
81
|
+
* The URL to the service worker.
|
|
82
|
+
* @default "/sw.js"
|
|
83
|
+
*/
|
|
84
|
+
swUrl?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Files in the public directory matching any of these patterns
|
|
87
|
+
* will be included in the precache manifest. For more information,
|
|
88
|
+
* see [`node-glob`'s Glob Primer](https://github.com/isaacs/node-glob#glob-primer).
|
|
89
|
+
* @default
|
|
90
|
+
* ```
|
|
91
|
+
* ["**\/*"]
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
globPublicPatterns?: string[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type InjectResolved = Require<InjectPartial, "cacheOnNavigation" | "disable" | "register" | "reloadOnOnline" | "swUrl" | "globPublicPatterns">;
|
|
98
|
+
|
|
99
|
+
export type InjectManifestOptions = Omit<WebpackInjectManifestOptions & RequiredSwDestPartial & InjectPartial, "disablePrecacheManifest">;
|
|
100
|
+
|
|
101
|
+
export type InjectManifestOptionsComplete = Omit<
|
|
102
|
+
WebpackInjectManifestOptionsComplete & RequiredSwDestResolved & InjectResolved,
|
|
103
|
+
"disablePrecacheManifest"
|
|
104
|
+
>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SerwistConfigError, validationErrorMap } from "@serwist/build/schema";
|
|
2
|
+
import { injectManifestOptions } from "./schema.js";
|
|
3
|
+
import type { InjectManifestOptionsComplete } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export const validateInjectManifestOptions = (input: unknown): InjectManifestOptionsComplete => {
|
|
6
|
+
const result = injectManifestOptions.safeParse(input, {
|
|
7
|
+
errorMap: validationErrorMap,
|
|
8
|
+
});
|
|
9
|
+
if (!result.success) {
|
|
10
|
+
throw new SerwistConfigError({ moduleName: "@serwist/next", message: JSON.stringify(result.error.format(), null, 2) });
|
|
11
|
+
}
|
|
12
|
+
return result.data;
|
|
13
|
+
};
|