@serwist/next 9.3.0 → 9.3.1
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/index.config.d.ts +7 -0
- package/dist/index.config.d.ts.map +1 -0
- package/dist/index.config.js +100 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.react.d.ts +19 -0
- package/dist/index.react.d.ts.map +1 -0
- package/dist/index.react.js +93 -0
- package/dist/lib/config/types.d.ts +11 -0
- package/dist/lib/config/types.d.ts.map +1 -0
- package/dist/lib/config/utils.d.ts +2 -0
- package/dist/lib/config/utils.d.ts.map +1 -0
- package/dist/lib/context.d.ts +7 -0
- package/dist/lib/context.d.ts.map +1 -0
- package/dist/lib/schema.d.ts +16 -16
- package/package.json +38 -17
- package/src/index.config.ts +91 -0
- package/src/index.react.tsx +86 -0
- package/src/index.ts +1 -4
- package/src/lib/config/types.ts +11 -0
- package/src/lib/config/utils.ts +4 -0
- package/src/lib/context.ts +16 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BuildOptions } from "@serwist/cli";
|
|
2
|
+
import type { SerwistOptions } from "./lib/config/types.js";
|
|
3
|
+
import { generateGlobPatterns } from "./lib/config/utils.js";
|
|
4
|
+
export declare const serwist: (options: SerwistOptions) => Promise<BuildOptions>;
|
|
5
|
+
export { generateGlobPatterns };
|
|
6
|
+
export type { SerwistOptions };
|
|
7
|
+
//# sourceMappingURL=index.config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.config.d.ts","sourceRoot":"","sources":["../src/index.config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAI7D,eAAO,MAAM,OAAO,GAAU,SAAS,cAAc,KAAG,OAAO,CAAC,YAAY,CA4E3E,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { rebasePath } from '@serwist/build';
|
|
5
|
+
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from 'next/constants.js';
|
|
6
|
+
|
|
7
|
+
const generateGlobPatterns = (distDir)=>[
|
|
8
|
+
`${distDir}static/**/*.{js,css,html,ico,apng,png,avif,jpg,jpeg,jfif,pjpeg,pjp,gif,svg,webp,json,webmanifest}`,
|
|
9
|
+
"public/**/*"
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const __require = createRequire(import.meta.url);
|
|
13
|
+
const loadNextConfig = __require("next/dist/server/config.js");
|
|
14
|
+
const serwist = async (options)=>{
|
|
15
|
+
const isWatch = process.env.SERWIST_ENV === "watch";
|
|
16
|
+
const nextPhase = isWatch ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD;
|
|
17
|
+
const config = await loadNextConfig.default(nextPhase, process.cwd(), {
|
|
18
|
+
silent: false
|
|
19
|
+
});
|
|
20
|
+
const basePath = config.basePath || "/";
|
|
21
|
+
let distDir = config.distDir;
|
|
22
|
+
if (distDir[0] === "/") distDir = distDir.slice(1);
|
|
23
|
+
if (distDir[distDir.length - 1] !== "/") distDir += "/";
|
|
24
|
+
const distServerDir = `${distDir}server/`;
|
|
25
|
+
const distAppDir = `${distServerDir}app/`;
|
|
26
|
+
const distPagesDir = `${distServerDir}pages/`;
|
|
27
|
+
const { precachePrerendered = true, globDirectory = process.cwd(), ...cliOptions } = options;
|
|
28
|
+
for (const file of [
|
|
29
|
+
cliOptions.swDest,
|
|
30
|
+
`${cliOptions.swDest}.map`
|
|
31
|
+
]){
|
|
32
|
+
fs.rmSync(file, {
|
|
33
|
+
force: true
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
dontCacheBustURLsMatching: new RegExp(`^${distDir}static/`),
|
|
38
|
+
disablePrecacheManifest: isWatch,
|
|
39
|
+
...cliOptions,
|
|
40
|
+
globDirectory,
|
|
41
|
+
globPatterns: [
|
|
42
|
+
...cliOptions.globPatterns ?? generateGlobPatterns(distDir),
|
|
43
|
+
...precachePrerendered ? [
|
|
44
|
+
`${distServerDir}{app,pages}/**/*.html`
|
|
45
|
+
] : []
|
|
46
|
+
],
|
|
47
|
+
globIgnores: [
|
|
48
|
+
`${distAppDir}**/_not-found.html`,
|
|
49
|
+
`${distPagesDir}404.html`,
|
|
50
|
+
`${distPagesDir}500.html`,
|
|
51
|
+
...cliOptions.globIgnores ?? [],
|
|
52
|
+
rebasePath({
|
|
53
|
+
baseDirectory: globDirectory,
|
|
54
|
+
file: cliOptions.swSrc
|
|
55
|
+
}),
|
|
56
|
+
rebasePath({
|
|
57
|
+
baseDirectory: globDirectory,
|
|
58
|
+
file: cliOptions.swDest
|
|
59
|
+
}),
|
|
60
|
+
rebasePath({
|
|
61
|
+
baseDirectory: globDirectory,
|
|
62
|
+
file: `${cliOptions.swDest}.map`
|
|
63
|
+
})
|
|
64
|
+
],
|
|
65
|
+
manifestTransforms: [
|
|
66
|
+
...cliOptions.manifestTransforms ?? [],
|
|
67
|
+
(manifestEntries)=>{
|
|
68
|
+
const manifest = manifestEntries.map((m)=>{
|
|
69
|
+
if (m.url.startsWith(distAppDir)) {
|
|
70
|
+
m.url = m.url.slice(distAppDir.length - 1);
|
|
71
|
+
}
|
|
72
|
+
if (m.url.startsWith(distPagesDir)) {
|
|
73
|
+
m.url = m.url.slice(distPagesDir.length - 1);
|
|
74
|
+
}
|
|
75
|
+
if (m.url.endsWith(".html")) {
|
|
76
|
+
if (m.url.endsWith("/index.html")) {
|
|
77
|
+
m.url = m.url.slice(0, m.url.lastIndexOf("/") + 1);
|
|
78
|
+
} else {
|
|
79
|
+
m.url = m.url.substring(0, m.url.lastIndexOf("."));
|
|
80
|
+
}
|
|
81
|
+
m.url = path.posix.join(basePath, m.url);
|
|
82
|
+
}
|
|
83
|
+
if (m.url.startsWith(distDir)) {
|
|
84
|
+
m.url = `${config.assetPrefix ?? ""}/_next/${m.url.slice(distDir.length)}`;
|
|
85
|
+
}
|
|
86
|
+
if (m.url.startsWith("public/")) {
|
|
87
|
+
m.url = path.posix.join(basePath, m.url.slice(7));
|
|
88
|
+
}
|
|
89
|
+
return m;
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
manifest,
|
|
93
|
+
warnings: []
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export { generateGlobPatterns, serwist };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAMnE;;;;GAIG;AACH,QAAA,MAAM,eAAe,GAAI,aAAa,qBAAqB,KAAG,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAMnE;;;;GAIG;AACH,QAAA,MAAM,eAAe,GAAI,aAAa,qBAAqB,KAAG,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,KAAK,UAAU,CA6NrG,CAAC;AAEF,eAAe,eAAe,CAAC;AAC/B,OAAO,EAAE,6BAA6B,EAAE,CAAC;AACzC,YAAY,EAAE,qBAAqB,IAAI,aAAa,EAAE,6BAA6B,IAAI,qBAAqB,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -194,10 +194,8 @@ const withSerwistInit = (userOptions)=>{
|
|
|
194
194
|
cwd: destDir
|
|
195
195
|
});
|
|
196
196
|
for (const file of cleanUpList){
|
|
197
|
-
fs.
|
|
197
|
+
fs.rmSync(file, {
|
|
198
198
|
force: true
|
|
199
|
-
}, (err)=>{
|
|
200
|
-
if (err) throw err;
|
|
201
199
|
});
|
|
202
200
|
}
|
|
203
201
|
const shouldBuildSWEntryWorker = cacheOnNavigation;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Serwist } from "@serwist/window";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import { useSerwist } from "./lib/context.js";
|
|
4
|
+
export interface SerwistProviderProps {
|
|
5
|
+
swUrl: string;
|
|
6
|
+
register?: boolean;
|
|
7
|
+
cacheOnNavigation?: boolean;
|
|
8
|
+
reloadOnOnline?: boolean;
|
|
9
|
+
options?: RegistrationOptions;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
declare global {
|
|
13
|
+
interface Window {
|
|
14
|
+
serwist: Serwist;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export declare function SerwistProvider({ swUrl, register, cacheOnNavigation, reloadOnOnline, options, children, }: SerwistProviderProps): import("react").JSX.Element;
|
|
18
|
+
export { useSerwist };
|
|
19
|
+
//# sourceMappingURL=index.react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.react.d.ts","sourceRoot":"","sources":["../src/index.react.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAkB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,OAAO,EAAE,OAAO,CAAC;KAClB;CACF;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAe,EACf,iBAAwB,EACxB,cAAqB,EACrB,OAAO,EACP,QAAQ,GACT,EAAE,oBAAoB,+BAwDtB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Serwist } from '@serwist/window';
|
|
3
|
+
import { isCurrentPageOutOfScope } from '@serwist/window/internal';
|
|
4
|
+
import { createContext, useContext, useState, useEffect } from 'react';
|
|
5
|
+
|
|
6
|
+
const SerwistContext = createContext(null);
|
|
7
|
+
const useSerwist = ()=>{
|
|
8
|
+
const context = useContext(SerwistContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error("[useSerwist]: 'SerwistContext' is not available.");
|
|
11
|
+
}
|
|
12
|
+
return context;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function SerwistProvider({ swUrl, register = true, cacheOnNavigation = true, reloadOnOnline = true, options, children }) {
|
|
16
|
+
const [serwist] = useState(()=>{
|
|
17
|
+
if (typeof window === "undefined") return null;
|
|
18
|
+
if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) {
|
|
19
|
+
window.serwist = new Serwist(swUrl, {
|
|
20
|
+
...options,
|
|
21
|
+
type: options?.type || "module",
|
|
22
|
+
scope: options?.scope || "/"
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return window.serwist ?? null;
|
|
26
|
+
});
|
|
27
|
+
useEffect(()=>{
|
|
28
|
+
const scope = options?.scope || "/";
|
|
29
|
+
if (register && !isCurrentPageOutOfScope(scope)) {
|
|
30
|
+
void serwist?.register();
|
|
31
|
+
}
|
|
32
|
+
}, [
|
|
33
|
+
register,
|
|
34
|
+
options?.scope,
|
|
35
|
+
serwist?.register
|
|
36
|
+
]);
|
|
37
|
+
useEffect(()=>{
|
|
38
|
+
const cacheUrls = async (url)=>{
|
|
39
|
+
if (!window.navigator.onLine || !url) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
serwist?.messageSW({
|
|
43
|
+
type: "CACHE_URLS",
|
|
44
|
+
payload: {
|
|
45
|
+
urlsToCache: [
|
|
46
|
+
url
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const cacheCurrentPathname = ()=>cacheUrls(window.location.pathname);
|
|
52
|
+
const pushState = history.pushState;
|
|
53
|
+
const replaceState = history.replaceState;
|
|
54
|
+
if (cacheOnNavigation) {
|
|
55
|
+
history.pushState = (...args)=>{
|
|
56
|
+
pushState.apply(history, args);
|
|
57
|
+
cacheUrls(args[2]);
|
|
58
|
+
};
|
|
59
|
+
history.replaceState = (...args)=>{
|
|
60
|
+
replaceState.apply(history, args);
|
|
61
|
+
cacheUrls(args[2]);
|
|
62
|
+
};
|
|
63
|
+
window.addEventListener("online", cacheCurrentPathname);
|
|
64
|
+
}
|
|
65
|
+
return ()=>{
|
|
66
|
+
history.pushState = pushState;
|
|
67
|
+
history.replaceState = replaceState;
|
|
68
|
+
window.removeEventListener("online", cacheCurrentPathname);
|
|
69
|
+
};
|
|
70
|
+
}, [
|
|
71
|
+
serwist?.messageSW,
|
|
72
|
+
cacheOnNavigation
|
|
73
|
+
]);
|
|
74
|
+
useEffect(()=>{
|
|
75
|
+
const reload = ()=>location.reload();
|
|
76
|
+
if (reloadOnOnline) {
|
|
77
|
+
window.addEventListener("online", reload);
|
|
78
|
+
}
|
|
79
|
+
return ()=>{
|
|
80
|
+
window.removeEventListener("online", reload);
|
|
81
|
+
};
|
|
82
|
+
}, [
|
|
83
|
+
reloadOnOnline
|
|
84
|
+
]);
|
|
85
|
+
return jsx(SerwistContext.Provider, {
|
|
86
|
+
value: {
|
|
87
|
+
serwist
|
|
88
|
+
},
|
|
89
|
+
children: children
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { SerwistProvider, useSerwist };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BuildOptions } from "@serwist/cli";
|
|
2
|
+
import type { Optional } from "@serwist/utils";
|
|
3
|
+
export interface SerwistOptions extends Optional<BuildOptions, "globDirectory"> {
|
|
4
|
+
/**
|
|
5
|
+
* Whether Serwist should precache prerendered routes.
|
|
6
|
+
*
|
|
7
|
+
* @default true
|
|
8
|
+
*/
|
|
9
|
+
precachePrerendered?: boolean;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IAC7E;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/config/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,aAGnD,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Serwist } from "@serwist/window";
|
|
2
|
+
export interface SerwistContextValues {
|
|
3
|
+
serwist: Serwist | null;
|
|
4
|
+
}
|
|
5
|
+
export declare const SerwistContext: import("react").Context<SerwistContextValues>;
|
|
6
|
+
export declare const useSerwist: () => SerwistContextValues;
|
|
7
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/lib/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,cAAc,+CAA6C,CAAC;AAEzE,eAAO,MAAM,UAAU,4BAMtB,CAAC"}
|
package/dist/lib/schema.d.ts
CHANGED
|
@@ -9,22 +9,6 @@ export declare const injectPartial: z.ZodObject<{
|
|
|
9
9
|
globPublicPatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
10
10
|
}, z.core.$strict>;
|
|
11
11
|
export declare const injectManifestOptions: z.ZodObject<{
|
|
12
|
-
cacheOnNavigation: z.ZodDefault<z.ZodBoolean>;
|
|
13
|
-
disable: z.ZodDefault<z.ZodBoolean>;
|
|
14
|
-
register: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
-
reloadOnOnline: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
-
scope: z.ZodOptional<z.ZodString>;
|
|
17
|
-
swUrl: z.ZodDefault<z.ZodString>;
|
|
18
|
-
globPublicPatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
19
|
-
swDest: z.ZodString;
|
|
20
|
-
compileSrc: z.ZodDefault<z.ZodBoolean>;
|
|
21
|
-
webpackCompilationPlugins: z.ZodOptional<z.ZodArray<z.ZodAny>>;
|
|
22
|
-
injectionPoint: z.ZodDefault<z.ZodString>;
|
|
23
|
-
swSrc: z.ZodString;
|
|
24
|
-
chunks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
-
exclude: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<RegExp, RegExp>, z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>, z.ZodTransform<(args_0: any) => boolean, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>>]>>>;
|
|
26
|
-
excludeChunks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
-
include: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<RegExp, RegExp>, z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>, z.ZodTransform<(args_0: any) => boolean, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>>]>>>;
|
|
28
12
|
additionalPrecacheEntries: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
29
13
|
integrity: z.ZodOptional<z.ZodString>;
|
|
30
14
|
revision: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -86,5 +70,21 @@ export declare const injectManifestOptions: z.ZodObject<{
|
|
|
86
70
|
}, z.core.$strict>>>>>>;
|
|
87
71
|
maximumFileSizeToCacheInBytes: z.ZodDefault<z.ZodNumber>;
|
|
88
72
|
modifyURLPrefix: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
73
|
+
injectionPoint: z.ZodDefault<z.ZodString>;
|
|
74
|
+
swSrc: z.ZodString;
|
|
75
|
+
swDest: z.ZodString;
|
|
76
|
+
cacheOnNavigation: z.ZodDefault<z.ZodBoolean>;
|
|
77
|
+
disable: z.ZodDefault<z.ZodBoolean>;
|
|
78
|
+
register: z.ZodDefault<z.ZodBoolean>;
|
|
79
|
+
reloadOnOnline: z.ZodDefault<z.ZodBoolean>;
|
|
80
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
81
|
+
swUrl: z.ZodDefault<z.ZodString>;
|
|
82
|
+
globPublicPatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
83
|
+
compileSrc: z.ZodDefault<z.ZodBoolean>;
|
|
84
|
+
webpackCompilationPlugins: z.ZodOptional<z.ZodArray<z.ZodAny>>;
|
|
85
|
+
chunks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
86
|
+
exclude: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<RegExp, RegExp>, z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>, z.ZodTransform<(args_0: any) => boolean, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>>]>>>;
|
|
87
|
+
excludeChunks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
88
|
+
include: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodCustom<RegExp, RegExp>, z.ZodPipe<z.ZodCustom<z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>, z.ZodTransform<(args_0: any) => boolean, z.core.$InferInnerFunctionType<z.ZodTuple<[z.ZodAny], null>, z.ZodBoolean>>>]>>>;
|
|
89
89
|
}, z.core.$strict>;
|
|
90
90
|
//# sourceMappingURL=schema.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serwist/next",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A module that integrates Serwist into your Next.js application.",
|
|
6
6
|
"files": [
|
|
@@ -32,14 +32,20 @@
|
|
|
32
32
|
"types": "./dist/index.d.ts",
|
|
33
33
|
"typesVersions": {
|
|
34
34
|
"*": {
|
|
35
|
-
"
|
|
36
|
-
"./dist/index.
|
|
35
|
+
"config": [
|
|
36
|
+
"./dist/index.config.d.ts"
|
|
37
37
|
],
|
|
38
|
-
"
|
|
39
|
-
"./dist/
|
|
38
|
+
"react": [
|
|
39
|
+
"./dist/index.react.d.ts"
|
|
40
40
|
],
|
|
41
41
|
"schema": [
|
|
42
42
|
"./dist/index.schema.d.ts"
|
|
43
|
+
],
|
|
44
|
+
"typings": [
|
|
45
|
+
"./dist/sw-entry.d.ts"
|
|
46
|
+
],
|
|
47
|
+
"worker": [
|
|
48
|
+
"./dist/index.worker.d.ts"
|
|
43
49
|
]
|
|
44
50
|
}
|
|
45
51
|
},
|
|
@@ -48,17 +54,25 @@
|
|
|
48
54
|
"types": "./dist/index.d.ts",
|
|
49
55
|
"default": "./dist/index.js"
|
|
50
56
|
},
|
|
51
|
-
"./
|
|
52
|
-
"types": "./dist/index.
|
|
53
|
-
"default": "./dist/index.
|
|
57
|
+
"./config": {
|
|
58
|
+
"types": "./dist/index.config.d.ts",
|
|
59
|
+
"default": "./dist/index.config.js"
|
|
54
60
|
},
|
|
55
|
-
"./
|
|
56
|
-
"types": "./dist/
|
|
61
|
+
"./react": {
|
|
62
|
+
"types": "./dist/index.react.d.ts",
|
|
63
|
+
"default": "./dist/index.react.js"
|
|
57
64
|
},
|
|
58
65
|
"./schema": {
|
|
59
66
|
"types": "./dist/index.schema.d.ts",
|
|
60
67
|
"default": "./dist/index.schema.js"
|
|
61
68
|
},
|
|
69
|
+
"./typings": {
|
|
70
|
+
"types": "./dist/sw-entry.d.ts"
|
|
71
|
+
},
|
|
72
|
+
"./worker": {
|
|
73
|
+
"types": "./dist/index.worker.d.ts",
|
|
74
|
+
"default": "./dist/index.worker.js"
|
|
75
|
+
},
|
|
62
76
|
"./package.json": "./package.json"
|
|
63
77
|
},
|
|
64
78
|
"dependencies": {
|
|
@@ -66,13 +80,14 @@
|
|
|
66
80
|
"kolorist": "1.8.0",
|
|
67
81
|
"semver": "7.7.3",
|
|
68
82
|
"zod": "4.2.1",
|
|
69
|
-
"@serwist/build": "9.3.
|
|
70
|
-
"@serwist/webpack-plugin": "9.3.
|
|
71
|
-
"@serwist/window": "9.3.
|
|
72
|
-
"serwist": "9.3.
|
|
83
|
+
"@serwist/build": "9.3.1",
|
|
84
|
+
"@serwist/webpack-plugin": "9.3.1",
|
|
85
|
+
"@serwist/window": "9.3.1",
|
|
86
|
+
"serwist": "9.3.1"
|
|
73
87
|
},
|
|
74
88
|
"devDependencies": {
|
|
75
89
|
"@types/node": "25.0.3",
|
|
90
|
+
"@types/react": "19.2.7",
|
|
76
91
|
"@types/semver": "7.7.1",
|
|
77
92
|
"next": "16.1.0",
|
|
78
93
|
"react": "19.2.3",
|
|
@@ -81,14 +96,20 @@
|
|
|
81
96
|
"type-fest": "5.3.1",
|
|
82
97
|
"typescript": "5.9.3",
|
|
83
98
|
"webpack": "5.104.1",
|
|
84
|
-
"@serwist/
|
|
85
|
-
"@serwist/
|
|
99
|
+
"@serwist/cli": "9.3.1",
|
|
100
|
+
"@serwist/configs": "9.3.1",
|
|
101
|
+
"@serwist/utils": "9.3.1"
|
|
86
102
|
},
|
|
87
103
|
"peerDependencies": {
|
|
88
104
|
"next": ">=14.0.0",
|
|
89
|
-
"
|
|
105
|
+
"react": ">=18.0.0",
|
|
106
|
+
"typescript": ">=5.0.0",
|
|
107
|
+
"@serwist/cli": "9.3.1"
|
|
90
108
|
},
|
|
91
109
|
"peerDependenciesMeta": {
|
|
110
|
+
"@serwist/cli": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
92
113
|
"typescript": {
|
|
93
114
|
"optional": true
|
|
94
115
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { rebasePath } from "@serwist/build";
|
|
4
|
+
import type { BuildOptions } from "@serwist/cli";
|
|
5
|
+
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "next/constants.js";
|
|
6
|
+
import type { SerwistOptions } from "./lib/config/types.js";
|
|
7
|
+
import { generateGlobPatterns } from "./lib/config/utils.js";
|
|
8
|
+
|
|
9
|
+
import loadNextConfig = require("next/dist/server/config.js");
|
|
10
|
+
|
|
11
|
+
export const serwist = async (options: SerwistOptions): Promise<BuildOptions> => {
|
|
12
|
+
const isWatch = process.env.SERWIST_ENV === "watch";
|
|
13
|
+
const nextPhase = isWatch ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD;
|
|
14
|
+
const config = await loadNextConfig.default(nextPhase, process.cwd(), {
|
|
15
|
+
silent: false,
|
|
16
|
+
});
|
|
17
|
+
const basePath = config.basePath || "/";
|
|
18
|
+
let distDir = config.distDir;
|
|
19
|
+
if (distDir[0] === "/") distDir = distDir.slice(1);
|
|
20
|
+
if (distDir[distDir.length - 1] !== "/") distDir += "/";
|
|
21
|
+
const distServerDir = `${distDir}server/`;
|
|
22
|
+
const distAppDir = `${distServerDir}app/`;
|
|
23
|
+
const distPagesDir = `${distServerDir}pages/`;
|
|
24
|
+
const { precachePrerendered = true, globDirectory = process.cwd(), ...cliOptions } = options;
|
|
25
|
+
for (const file of [cliOptions.swDest, `${cliOptions.swDest}.map`]) {
|
|
26
|
+
fs.rmSync(file, { force: true });
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
dontCacheBustURLsMatching: new RegExp(`^${distDir}static/`),
|
|
30
|
+
disablePrecacheManifest: isWatch,
|
|
31
|
+
...cliOptions,
|
|
32
|
+
globDirectory,
|
|
33
|
+
globPatterns: [
|
|
34
|
+
...(cliOptions.globPatterns ?? generateGlobPatterns(distDir)),
|
|
35
|
+
...(precachePrerendered ? [`${distServerDir}{app,pages}/**/*.html`] : []),
|
|
36
|
+
],
|
|
37
|
+
globIgnores: [
|
|
38
|
+
`${distAppDir}**/_not-found.html`,
|
|
39
|
+
`${distPagesDir}404.html`,
|
|
40
|
+
`${distPagesDir}500.html`,
|
|
41
|
+
...(cliOptions.globIgnores ?? []),
|
|
42
|
+
rebasePath({ baseDirectory: globDirectory, file: cliOptions.swSrc }),
|
|
43
|
+
rebasePath({ baseDirectory: globDirectory, file: cliOptions.swDest }),
|
|
44
|
+
rebasePath({ baseDirectory: globDirectory, file: `${cliOptions.swDest}.map` }),
|
|
45
|
+
],
|
|
46
|
+
manifestTransforms: [
|
|
47
|
+
...(cliOptions.manifestTransforms ?? []),
|
|
48
|
+
(manifestEntries) => {
|
|
49
|
+
const manifest = manifestEntries.map((m) => {
|
|
50
|
+
if (m.url.startsWith(distAppDir)) {
|
|
51
|
+
// Keep the prefixing slash.
|
|
52
|
+
m.url = m.url.slice(distAppDir.length - 1);
|
|
53
|
+
}
|
|
54
|
+
if (m.url.startsWith(distPagesDir)) {
|
|
55
|
+
// Keep the prefixing slash.
|
|
56
|
+
m.url = m.url.slice(distPagesDir.length - 1);
|
|
57
|
+
}
|
|
58
|
+
if (m.url.endsWith(".html")) {
|
|
59
|
+
// trailingSlash: true && output: 'export'
|
|
60
|
+
// or root index.html.
|
|
61
|
+
// https://nextjs.org/docs/app/api-reference/config/next-config-js/trailingSlash
|
|
62
|
+
// "/abc/index.html" -> "/abc/"
|
|
63
|
+
// "/index.html" -> "/"
|
|
64
|
+
if (m.url.endsWith("/index.html")) {
|
|
65
|
+
m.url = m.url.slice(0, m.url.lastIndexOf("/") + 1);
|
|
66
|
+
}
|
|
67
|
+
// "/xxx.html" -> "/xxx"
|
|
68
|
+
else {
|
|
69
|
+
m.url = m.url.substring(0, m.url.lastIndexOf("."));
|
|
70
|
+
}
|
|
71
|
+
m.url = path.posix.join(basePath, m.url);
|
|
72
|
+
}
|
|
73
|
+
// Replace all references to "$(distDir)" with "$(assetPrefix)/_next/".
|
|
74
|
+
if (m.url.startsWith(distDir)) {
|
|
75
|
+
m.url = `${config.assetPrefix ?? ""}/_next/${m.url.slice(distDir.length)}`;
|
|
76
|
+
}
|
|
77
|
+
// Replace all references to public/ with "$(basePath)/".
|
|
78
|
+
if (m.url.startsWith("public/")) {
|
|
79
|
+
m.url = path.posix.join(basePath, m.url.slice(7));
|
|
80
|
+
}
|
|
81
|
+
return m;
|
|
82
|
+
});
|
|
83
|
+
return { manifest, warnings: [] };
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { generateGlobPatterns };
|
|
90
|
+
|
|
91
|
+
export type { SerwistOptions };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Serwist } from "@serwist/window";
|
|
2
|
+
import { isCurrentPageOutOfScope } from "@serwist/window/internal";
|
|
3
|
+
import { type ReactNode, useEffect, useState } from "react";
|
|
4
|
+
import { SerwistContext, useSerwist } from "./lib/context.js";
|
|
5
|
+
|
|
6
|
+
export interface SerwistProviderProps {
|
|
7
|
+
swUrl: string;
|
|
8
|
+
register?: boolean;
|
|
9
|
+
cacheOnNavigation?: boolean;
|
|
10
|
+
reloadOnOnline?: boolean;
|
|
11
|
+
options?: RegistrationOptions;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
serwist: Serwist;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function SerwistProvider({
|
|
22
|
+
swUrl,
|
|
23
|
+
register = true,
|
|
24
|
+
cacheOnNavigation = true,
|
|
25
|
+
reloadOnOnline = true,
|
|
26
|
+
options,
|
|
27
|
+
children,
|
|
28
|
+
}: SerwistProviderProps) {
|
|
29
|
+
const [serwist] = useState(() => {
|
|
30
|
+
if (typeof window === "undefined") return null;
|
|
31
|
+
if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) {
|
|
32
|
+
window.serwist = new Serwist(swUrl, { ...options, type: options?.type || "module", scope: options?.scope || "/" });
|
|
33
|
+
}
|
|
34
|
+
return window.serwist ?? null;
|
|
35
|
+
});
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const scope = options?.scope || "/";
|
|
38
|
+
if (register && !isCurrentPageOutOfScope(scope)) {
|
|
39
|
+
void serwist?.register();
|
|
40
|
+
}
|
|
41
|
+
}, [register, options?.scope, serwist?.register]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const cacheUrls = async (url?: string | URL | null | undefined) => {
|
|
44
|
+
if (!window.navigator.onLine || !url) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
serwist?.messageSW({
|
|
48
|
+
type: "CACHE_URLS",
|
|
49
|
+
payload: { urlsToCache: [url] },
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const cacheCurrentPathname = () => cacheUrls(window.location.pathname);
|
|
53
|
+
const pushState = history.pushState;
|
|
54
|
+
const replaceState = history.replaceState;
|
|
55
|
+
|
|
56
|
+
if (cacheOnNavigation) {
|
|
57
|
+
history.pushState = (...args) => {
|
|
58
|
+
pushState.apply(history, args);
|
|
59
|
+
cacheUrls(args[2]);
|
|
60
|
+
};
|
|
61
|
+
history.replaceState = (...args) => {
|
|
62
|
+
replaceState.apply(history, args);
|
|
63
|
+
cacheUrls(args[2]);
|
|
64
|
+
};
|
|
65
|
+
window.addEventListener("online", cacheCurrentPathname);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
history.pushState = pushState;
|
|
70
|
+
history.replaceState = replaceState;
|
|
71
|
+
window.removeEventListener("online", cacheCurrentPathname);
|
|
72
|
+
};
|
|
73
|
+
}, [serwist?.messageSW, cacheOnNavigation]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const reload = () => location.reload();
|
|
76
|
+
if (reloadOnOnline) {
|
|
77
|
+
window.addEventListener("online", reload);
|
|
78
|
+
}
|
|
79
|
+
return () => {
|
|
80
|
+
window.removeEventListener("online", reload);
|
|
81
|
+
};
|
|
82
|
+
}, [reloadOnOnline]);
|
|
83
|
+
return <SerwistContext.Provider value={{ serwist }}>{children}</SerwistContext.Provider>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { useSerwist };
|
package/src/index.ts
CHANGED
|
@@ -141,9 +141,7 @@ const withSerwistInit = (userOptions: InjectManifestOptions): ((nextConfig?: Nex
|
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
for (const file of cleanUpList) {
|
|
144
|
-
fs.
|
|
145
|
-
if (err) throw err;
|
|
146
|
-
});
|
|
144
|
+
fs.rmSync(file, { force: true });
|
|
147
145
|
}
|
|
148
146
|
|
|
149
147
|
const shouldBuildSWEntryWorker = cacheOnNavigation;
|
|
@@ -214,7 +212,6 @@ const withSerwistInit = (userOptions: InjectManifestOptions): ((nextConfig?: Nex
|
|
|
214
212
|
},
|
|
215
213
|
],
|
|
216
214
|
manifestTransforms: [
|
|
217
|
-
// TODO(ducanhgh): move this spread to below our transform function?
|
|
218
215
|
...manifestTransforms,
|
|
219
216
|
async (manifestEntries, compilation) => {
|
|
220
217
|
// This path always uses forward slashes, so it is safe to use it in the following string replace.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BuildOptions } from "@serwist/cli";
|
|
2
|
+
import type { Optional } from "@serwist/utils";
|
|
3
|
+
|
|
4
|
+
export interface SerwistOptions extends Optional<BuildOptions, "globDirectory"> {
|
|
5
|
+
/**
|
|
6
|
+
* Whether Serwist should precache prerendered routes.
|
|
7
|
+
*
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
precachePrerendered?: boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Serwist } from "@serwist/window";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
|
|
4
|
+
export interface SerwistContextValues {
|
|
5
|
+
serwist: Serwist | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const SerwistContext = createContext<SerwistContextValues>(null!);
|
|
9
|
+
|
|
10
|
+
export const useSerwist = () => {
|
|
11
|
+
const context = useContext(SerwistContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error("[useSerwist]: 'SerwistContext' is not available.");
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
};
|