@serwist/turbopack 10.0.0-preview.11 → 10.0.0-preview.13

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.d.ts CHANGED
@@ -8,9 +8,9 @@ export declare const createSerwistRoute: (options: InjectManifestOptions) => {
8
8
  dynamic: "force-static";
9
9
  dynamicParams: false;
10
10
  revalidate: false;
11
- generateStaticParams: () => {
11
+ generateStaticParams: () => Promise<{
12
12
  path: string;
13
- }[];
13
+ }[]>;
14
14
  GET: (_: Request, { params }: {
15
15
  params: Promise<{
16
16
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,OAAO,KAAK,EAAE,qBAAqB,EAAiC,MAAM,YAAY,CAAC;AAuCvF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,qBAAqB;;;;;;;aA8DzC,OAAO,cAAc;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE;CAYjF,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,OAAO,KAAK,EAAE,qBAAqB,EAAiC,MAAM,YAAY,CAAC;AAuCvF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,qBAAqB;;;;;;;aAgFzC,OAAO,cAAc;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE;CAajF,CAAC"}
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ const esbuild = import('esbuild-wasm');
61
61
  const logSerwistResult = (filePath, buildResult)=>{
62
62
  const { count, size, warnings } = buildResult;
63
63
  const hasWarnings = warnings && warnings.length > 0;
64
- if (filePath === "sw.js") {
64
+ if (filePath === "sw.js" && (hasWarnings || count > 0)) {
65
65
  logger[hasWarnings ? "warn" : "event"](`${cyan(count)} precache entries ${dim(`(${(size / 1024).toFixed(2)} KiB)`)}${hasWarnings ? `\n${yellow([
66
66
  "⚠ warnings",
67
67
  ...warnings.map((w)=>` ${w}`),
@@ -89,36 +89,33 @@ const contentTypeMap = {
89
89
  const createSerwistRoute = (options)=>{
90
90
  const dynamic = "force-static", dynamicParams = false, revalidate = false;
91
91
  const validation = validateGetManifestOptions(options).then((config)=>{
92
- config.globIgnores.push(rebasePath({
93
- file: config.swSrc,
94
- baseDirectory: config.globDirectory
95
- }));
96
- if (!config.manifestTransforms) {
97
- config.manifestTransforms = [];
98
- }
99
- config.manifestTransforms.push((manifestEntries)=>{
100
- const manifest = manifestEntries.map((m)=>{
101
- if (m.url.startsWith(".next/")) m.url = `/_next/${m.url.slice(6)}`;
102
- if (m.url.startsWith("public/")) m.url = path.posix.join(config.basePath, m.url.slice(7));
103
- return m;
104
- });
105
- return {
106
- manifest,
107
- warnings: []
108
- };
109
- });
110
- return config;
92
+ return {
93
+ ...config,
94
+ disablePrecacheManifest: isDev,
95
+ additionalPrecacheEntries: isDev ? [] : config.additionalPrecacheEntries,
96
+ globIgnores: [
97
+ ...config.globIgnores,
98
+ rebasePath({
99
+ file: config.swSrc,
100
+ baseDirectory: config.globDirectory
101
+ })
102
+ ],
103
+ manifestTransforms: [
104
+ ...config.manifestTransforms ?? [],
105
+ (manifestEntries)=>{
106
+ const manifest = manifestEntries.map((m)=>{
107
+ if (m.url.startsWith(".next/")) m.url = `/_next/${m.url.slice(6)}`;
108
+ if (m.url.startsWith("public/")) m.url = path.posix.join(config.basePath, m.url.slice(7));
109
+ return m;
110
+ });
111
+ return {
112
+ manifest,
113
+ warnings: []
114
+ };
115
+ }
116
+ ]
117
+ };
111
118
  });
112
- const generateStaticParams = ()=>{
113
- return [
114
- {
115
- path: "sw.js"
116
- },
117
- {
118
- path: "sw.js.map"
119
- }
120
- ];
121
- };
122
119
  let map = null;
123
120
  const loadMap = async (filePath)=>{
124
121
  const config = await validation;
@@ -131,22 +128,37 @@ const createSerwistRoute = (options)=>{
131
128
  warnings
132
129
  });
133
130
  const result = await (await esbuild).build({
131
+ sourcemap: true,
132
+ format: "esm",
133
+ target: [
134
+ "chrome64",
135
+ "edge79",
136
+ "firefox67",
137
+ "opera51",
138
+ "safari12"
139
+ ],
140
+ treeShaking: true,
141
+ minify: !isDev,
142
+ bundle: true,
143
+ ...config.esbuildOptions,
144
+ platform: "browser",
145
+ define: {
146
+ ...config.esbuildOptions.define,
147
+ ...injectionPoint ? {
148
+ [injectionPoint]: manifestString
149
+ } : {}
150
+ },
151
+ outdir: config.cwd,
152
+ write: false,
153
+ entryNames: "[name]",
154
+ assetNames: "[name]-[hash]",
155
+ chunkNames: "[name]-[hash]",
134
156
  entryPoints: [
135
157
  {
136
158
  in: config.swSrc,
137
159
  out: "sw"
138
160
  }
139
- ],
140
- format: "esm",
141
- sourcemap: true,
142
- bundle: true,
143
- write: false,
144
- minify: !isDev,
145
- define: injectionPoint ? {
146
- [injectionPoint]: manifestString
147
- } : undefined,
148
- outdir: process.cwd(),
149
- entryNames: "[name]"
161
+ ]
150
162
  });
151
163
  if (result.errors.length) {
152
164
  console.error("Failed to build the service worker.", result.errors);
@@ -160,10 +172,20 @@ const createSerwistRoute = (options)=>{
160
172
  e.text
161
173
  ]));
162
174
  };
175
+ const generateStaticParams = async ()=>{
176
+ const config = await validation;
177
+ if (!map) map = await loadMap("root");
178
+ return [
179
+ ...map.keys().map((e)=>({
180
+ path: path.relative(config.cwd, e)
181
+ }))
182
+ ];
183
+ };
163
184
  const GET = async (_, { params })=>{
164
185
  const { path: filePath } = await params;
186
+ const config = await validation;
165
187
  if (!map) map = await loadMap(filePath);
166
- return new NextResponse(map.get(path.join(process.cwd(), filePath)), {
188
+ return new NextResponse(map.get(path.join(config.cwd, filePath)), {
167
189
  headers: {
168
190
  "Content-Type": contentTypeMap[path.extname(filePath)] || "text/plain",
169
191
  "Service-Worker-Allowed": "/"
@@ -11,6 +11,7 @@ function SerwistProvider({ swUrl, register = true, reloadOnOnline = true, option
11
11
  if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) {
12
12
  window.serwist = new Serwist(swUrl, {
13
13
  ...options,
14
+ type: options?.type || "module",
14
15
  scope: options?.scope || "/"
15
16
  });
16
17
  }
@@ -1,54 +1,59 @@
1
1
  import z from "zod";
2
+ export declare const turboPartial: z.ZodObject<{
3
+ cwd: z.ZodPrefault<z.ZodString>;
4
+ basePath: z.ZodString;
5
+ esbuildOptions: z.ZodPrefault<z.ZodRecord<z.ZodLiteral<"bundle" | "splitting" | "preserveSymlinks" | "external" | "packages" | "alias" | "loader" | "resolveExtensions" | "mainFields" | "conditions" | "allowOverwrite" | "tsconfig" | "outExtension" | "publicPath" | "inject" | "banner" | "footer" | "plugins" | "sourcemap" | "legalComments" | "sourceRoot" | "sourcesContent" | "format" | "globalName" | "target" | "supported" | "mangleProps" | "reserveProps" | "mangleQuoted" | "mangleCache" | "drop" | "dropLabels" | "minify" | "minifyWhitespace" | "minifyIdentifiers" | "minifySyntax" | "lineLimit" | "charset" | "treeShaking" | "ignoreAnnotations" | "jsx" | "jsxFactory" | "jsxFragment" | "jsxImportSource" | "jsxDev" | "jsxSideEffects" | "define" | "pure" | "keepNames" | "absPaths" | "color" | "logLevel" | "logLimit" | "logOverride" | "tsconfigRaw"> & z.z.core.$partial, z.ZodAny>>;
6
+ }, z.z.core.$strict>;
2
7
  export declare const injectManifestOptions: z.ZodPipe<z.ZodObject<{
3
8
  cwd: z.ZodPrefault<z.ZodString>;
9
+ esbuildOptions: z.ZodPrefault<z.ZodRecord<z.ZodLiteral<"bundle" | "splitting" | "preserveSymlinks" | "external" | "packages" | "alias" | "loader" | "resolveExtensions" | "mainFields" | "conditions" | "allowOverwrite" | "tsconfig" | "outExtension" | "publicPath" | "inject" | "banner" | "footer" | "plugins" | "sourcemap" | "legalComments" | "sourceRoot" | "sourcesContent" | "format" | "globalName" | "target" | "supported" | "mangleProps" | "reserveProps" | "mangleQuoted" | "mangleCache" | "drop" | "dropLabels" | "minify" | "minifyWhitespace" | "minifyIdentifiers" | "minifySyntax" | "lineLimit" | "charset" | "treeShaking" | "ignoreAnnotations" | "jsx" | "jsxFactory" | "jsxFragment" | "jsxImportSource" | "jsxDev" | "jsxSideEffects" | "define" | "pure" | "keepNames" | "absPaths" | "color" | "logLevel" | "logLimit" | "logOverride" | "tsconfigRaw"> & z.z.core.$partial, z.ZodAny>>;
4
10
  basePath: z.ZodString;
5
- globPatterns: z.ZodPrefault<z.ZodArray<z.ZodString>>;
6
- globDirectory: z.ZodOptional<z.ZodString>;
7
- injectionPoint: z.ZodPrefault<z.ZodString>;
8
- swSrc: z.ZodString;
9
- globFollow: z.ZodDefault<z.ZodBoolean>;
10
- globIgnores: z.ZodDefault<z.ZodArray<z.ZodString>>;
11
- globStrict: z.ZodDefault<z.ZodBoolean>;
12
- templatedURLs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
13
11
  additionalPrecacheEntries: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodType<import("@serwist/build").ManifestEntry, import("@serwist/build").ManifestEntry, z.z.core.$ZodTypeInternals<import("@serwist/build").ManifestEntry, import("@serwist/build").ManifestEntry>>]>>>;
14
- disablePrecacheManifest: z.ZodDefault<z.ZodBoolean>;
15
12
  dontCacheBustURLsMatching: z.ZodOptional<z.ZodCustom<RegExp, RegExp>>;
16
13
  manifestTransforms: z.ZodOptional<z.ZodArray<z.ZodType<import("@serwist/build").ManifestTransform, import("@serwist/build").ManifestTransform, z.z.core.$ZodTypeInternals<import("@serwist/build").ManifestTransform, import("@serwist/build").ManifestTransform>>>>;
17
14
  maximumFileSizeToCacheInBytes: z.ZodDefault<z.ZodNumber>;
18
15
  modifyURLPrefix: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
16
+ globFollow: z.ZodDefault<z.ZodBoolean>;
17
+ globIgnores: z.ZodDefault<z.ZodArray<z.ZodString>>;
18
+ globPatterns: z.ZodPrefault<z.ZodArray<z.ZodString>>;
19
+ globStrict: z.ZodDefault<z.ZodBoolean>;
20
+ templatedURLs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
21
+ injectionPoint: z.ZodPrefault<z.ZodString>;
22
+ swSrc: z.ZodString;
23
+ globDirectory: z.ZodOptional<z.ZodString>;
19
24
  }, z.z.core.$strict>, z.ZodTransform<{
20
25
  swSrc: string;
21
26
  globDirectory: string;
22
27
  cwd: string;
28
+ esbuildOptions: Partial<Record<"bundle" | "splitting" | "preserveSymlinks" | "external" | "packages" | "alias" | "loader" | "resolveExtensions" | "mainFields" | "conditions" | "allowOverwrite" | "tsconfig" | "outExtension" | "publicPath" | "inject" | "banner" | "footer" | "plugins" | "sourcemap" | "legalComments" | "sourceRoot" | "sourcesContent" | "format" | "globalName" | "target" | "supported" | "mangleProps" | "reserveProps" | "mangleQuoted" | "mangleCache" | "drop" | "dropLabels" | "minify" | "minifyWhitespace" | "minifyIdentifiers" | "minifySyntax" | "lineLimit" | "charset" | "treeShaking" | "ignoreAnnotations" | "jsx" | "jsxFactory" | "jsxFragment" | "jsxImportSource" | "jsxDev" | "jsxSideEffects" | "define" | "pure" | "keepNames" | "absPaths" | "color" | "logLevel" | "logLimit" | "logOverride" | "tsconfigRaw", any>>;
23
29
  basePath: string;
24
- globPatterns: string[];
25
- injectionPoint: string;
30
+ maximumFileSizeToCacheInBytes: number;
26
31
  globFollow: boolean;
27
32
  globIgnores: string[];
33
+ globPatterns: string[];
28
34
  globStrict: boolean;
29
- disablePrecacheManifest: boolean;
30
- maximumFileSizeToCacheInBytes: number;
31
- templatedURLs?: Record<string, string | string[]> | undefined;
35
+ injectionPoint: string;
32
36
  additionalPrecacheEntries?: (string | import("@serwist/build").ManifestEntry)[] | undefined;
33
37
  dontCacheBustURLsMatching?: RegExp | undefined;
34
38
  manifestTransforms?: import("@serwist/build").ManifestTransform[] | undefined;
35
39
  modifyURLPrefix?: Record<string, string> | undefined;
40
+ templatedURLs?: Record<string, string | string[]> | undefined;
36
41
  }, {
37
42
  cwd: string;
43
+ esbuildOptions: Partial<Record<"bundle" | "splitting" | "preserveSymlinks" | "external" | "packages" | "alias" | "loader" | "resolveExtensions" | "mainFields" | "conditions" | "allowOverwrite" | "tsconfig" | "outExtension" | "publicPath" | "inject" | "banner" | "footer" | "plugins" | "sourcemap" | "legalComments" | "sourceRoot" | "sourcesContent" | "format" | "globalName" | "target" | "supported" | "mangleProps" | "reserveProps" | "mangleQuoted" | "mangleCache" | "drop" | "dropLabels" | "minify" | "minifyWhitespace" | "minifyIdentifiers" | "minifySyntax" | "lineLimit" | "charset" | "treeShaking" | "ignoreAnnotations" | "jsx" | "jsxFactory" | "jsxFragment" | "jsxImportSource" | "jsxDev" | "jsxSideEffects" | "define" | "pure" | "keepNames" | "absPaths" | "color" | "logLevel" | "logLimit" | "logOverride" | "tsconfigRaw", any>>;
38
44
  basePath: string;
39
- globPatterns: string[];
40
- injectionPoint: string;
41
- swSrc: string;
45
+ maximumFileSizeToCacheInBytes: number;
42
46
  globFollow: boolean;
43
47
  globIgnores: string[];
48
+ globPatterns: string[];
44
49
  globStrict: boolean;
45
- disablePrecacheManifest: boolean;
46
- maximumFileSizeToCacheInBytes: number;
47
- globDirectory?: string | undefined;
48
- templatedURLs?: Record<string, string | string[]> | undefined;
50
+ injectionPoint: string;
51
+ swSrc: string;
49
52
  additionalPrecacheEntries?: (string | import("@serwist/build").ManifestEntry)[] | undefined;
50
53
  dontCacheBustURLsMatching?: RegExp | undefined;
51
54
  manifestTransforms?: import("@serwist/build").ManifestTransform[] | undefined;
52
55
  modifyURLPrefix?: Record<string, string> | undefined;
56
+ templatedURLs?: Record<string, string | string[]> | undefined;
57
+ globDirectory?: string | undefined;
53
58
  }>>;
54
59
  //# sourceMappingURL=index.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.schema.d.ts","sourceRoot":"","sources":["../src/index.schema.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,KAAK,CAAC;AAGpB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgB9B,CAAC"}
1
+ {"version":3,"file":"index.schema.d.ts","sourceRoot":"","sources":["../src/index.schema.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,KAAK,CAAC;AAIpB,eAAO,MAAM,YAAY;;;;oBAIvB,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgB9B,CAAC"}
@@ -1,20 +1,83 @@
1
1
  import path from 'node:path';
2
- import { injectPartial, globPartial, basePartial } from '@serwist/build/schema';
2
+ import { injectPartial, globPartial, basePartial, assertType } from '@serwist/build/schema';
3
3
  import z from 'zod';
4
4
 
5
5
  const DEFAULT_GLOB_PATTERNS = [
6
6
  ".next/static/**/*.{js,css,html,ico,apng,png,avif,jpg,jpeg,jfif,pjpeg,pjp,gif,svg,webp,json,webmanifest}",
7
7
  "public/**/*"
8
8
  ];
9
+ const SUPPORTED_ESBUILD_OPTIONS = [
10
+ "sourcemap",
11
+ "legalComments",
12
+ "sourceRoot",
13
+ "sourcesContent",
14
+ "format",
15
+ "globalName",
16
+ "target",
17
+ "supported",
18
+ "define",
19
+ "treeShaking",
20
+ "minify",
21
+ "mangleProps",
22
+ "reserveProps",
23
+ "mangleQuoted",
24
+ "mangleCache",
25
+ "drop",
26
+ "dropLabels",
27
+ "minifyWhitespace",
28
+ "minifyIdentifiers",
29
+ "minifySyntax",
30
+ "lineLimit",
31
+ "charset",
32
+ "ignoreAnnotations",
33
+ "jsx",
34
+ "jsxFactory",
35
+ "jsxFragment",
36
+ "jsxImportSource",
37
+ "jsxDev",
38
+ "jsxSideEffects",
39
+ "pure",
40
+ "keepNames",
41
+ "absPaths",
42
+ "color",
43
+ "logLevel",
44
+ "logLimit",
45
+ "logOverride",
46
+ "tsconfigRaw",
47
+ "bundle",
48
+ "splitting",
49
+ "preserveSymlinks",
50
+ "external",
51
+ "packages",
52
+ "alias",
53
+ "loader",
54
+ "resolveExtensions",
55
+ "mainFields",
56
+ "conditions",
57
+ "allowOverwrite",
58
+ "tsconfig",
59
+ "outExtension",
60
+ "publicPath",
61
+ "inject",
62
+ "banner",
63
+ "footer",
64
+ "plugins"
65
+ ];
9
66
 
67
+ const turboPartial = z.strictObject({
68
+ cwd: z.string().prefault(process.cwd()),
69
+ basePath: z.string(),
70
+ esbuildOptions: z.partialRecord(z.literal(SUPPORTED_ESBUILD_OPTIONS), z.any()).prefault({})
71
+ });
10
72
  const injectManifestOptions = z.strictObject({
11
73
  ...basePartial.shape,
12
74
  ...globPartial.shape,
13
75
  ...injectPartial.shape,
14
- cwd: z.string().prefault(process.cwd()),
15
- basePath: z.string(),
76
+ ...turboPartial.shape,
16
77
  globPatterns: z.array(z.string()).prefault(DEFAULT_GLOB_PATTERNS),
17
78
  globDirectory: z.string().optional()
79
+ }).omit({
80
+ disablePrecacheManifest: true
18
81
  }).transform((input)=>{
19
82
  return {
20
83
  ...input,
@@ -22,5 +85,9 @@ const injectManifestOptions = z.strictObject({
22
85
  globDirectory: input.globDirectory ?? input.cwd
23
86
  };
24
87
  });
88
+ assertType();
89
+ assertType();
90
+ assertType();
91
+ assertType();
25
92
 
26
- export { injectManifestOptions };
93
+ export { injectManifestOptions, turboPartial };
@@ -1,2 +1,3 @@
1
1
  export declare const DEFAULT_GLOB_PATTERNS: string[];
2
+ export declare const SUPPORTED_ESBUILD_OPTIONS: readonly ["sourcemap", "legalComments", "sourceRoot", "sourcesContent", "format", "globalName", "target", "supported", "define", "treeShaking", "minify", "mangleProps", "reserveProps", "mangleQuoted", "mangleCache", "drop", "dropLabels", "minifyWhitespace", "minifyIdentifiers", "minifySyntax", "lineLimit", "charset", "ignoreAnnotations", "jsx", "jsxFactory", "jsxFragment", "jsxImportSource", "jsxDev", "jsxSideEffects", "pure", "keepNames", "absPaths", "color", "logLevel", "logLimit", "logOverride", "tsconfigRaw", "bundle", "splitting", "preserveSymlinks", "external", "packages", "alias", "loader", "resolveExtensions", "mainFields", "conditions", "allowOverwrite", "tsconfig", "outExtension", "publicPath", "inject", "banner", "footer", "plugins"];
2
3
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,UAGjC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,UAGjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,ovBA0Dc,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import type { BasePartial, BaseResolved, GlobPartial, GlobResolved, InjectPartial, InjectResolved, OptionalGlobDirectoryPartial, RequiredGlobDirectoryResolved } from "@serwist/build";
2
- import type { Prettify } from "@serwist/utils";
2
+ import type { Prettify, Require } from "@serwist/utils";
3
+ import type { BuildOptions } from "esbuild-wasm";
4
+ import type { SUPPORTED_ESBUILD_OPTIONS } from "./lib/constants.js";
5
+ export type EsbuildSupportedOptions = (typeof SUPPORTED_ESBUILD_OPTIONS)[number];
6
+ export type EsbuildOptions = Pick<BuildOptions, EsbuildSupportedOptions>;
3
7
  export interface TurboPartial {
4
8
  /**
5
9
  * The path to your working directory.
@@ -12,8 +16,9 @@ export interface TurboPartial {
12
16
  * is not configured, set to `/`.
13
17
  */
14
18
  basePath: string;
19
+ esbuildOptions?: EsbuildOptions;
15
20
  }
16
- export type TurboResolved = Required<TurboPartial>;
17
- export type InjectManifestOptions = Prettify<BasePartial & GlobPartial & InjectPartial & OptionalGlobDirectoryPartial & TurboPartial>;
18
- export type InjectManifestOptionsComplete = Prettify<BaseResolved & GlobResolved & InjectResolved & RequiredGlobDirectoryResolved & TurboResolved>;
21
+ export type TurboResolved = Require<TurboPartial, "cwd" | "esbuildOptions">;
22
+ export type InjectManifestOptions = Prettify<Omit<BasePartial & GlobPartial & InjectPartial & OptionalGlobDirectoryPartial & TurboPartial, "disablePrecacheManifest">>;
23
+ export type InjectManifestOptionsComplete = Prettify<Omit<BaseResolved & GlobResolved & InjectResolved & RequiredGlobDirectoryResolved & TurboResolved, "disablePrecacheManifest">>;
19
24
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI/C,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;AAEnD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,4BAA4B,GAAG,YAAY,CAAC,CAAC;AAEtI,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,6BAA6B,GAAG,aAAa,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,GAAG,gBAAgB,CAAC,CAAC;AAE5E,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAC1C,IAAI,CAAC,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,4BAA4B,GAAG,YAAY,EAAE,yBAAyB,CAAC,CACzH,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAClD,IAAI,CAAC,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,6BAA6B,GAAG,aAAa,EAAE,yBAAyB,CAAC,CAC9H,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serwist/turbopack",
3
- "version": "10.0.0-preview.11",
3
+ "version": "10.0.0-preview.13",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "A module that integrates Serwist into your Next.js / Turbopack application.",
@@ -63,30 +63,30 @@
63
63
  "./package.json": "./package.json"
64
64
  },
65
65
  "dependencies": {
66
- "@swc/core": "1.12.14",
67
- "esbuild-wasm": "0.25.8",
66
+ "@swc/core": "1.13.5",
68
67
  "kolorist": "1.8.0",
69
- "zod": "4.0.5",
70
- "@serwist/build": "10.0.0-preview.11",
71
- "@serwist/window": "10.0.0-preview.11",
72
- "serwist": "10.0.0-preview.11"
68
+ "zod": "4.1.1",
69
+ "@serwist/build": "10.0.0-preview.13",
70
+ "@serwist/window": "10.0.0-preview.13",
71
+ "serwist": "10.0.0-preview.13"
73
72
  },
74
73
  "devDependencies": {
75
- "@types/node": "24.0.14",
76
- "@types/react": "19.1.8",
77
- "next": "15.4.1",
78
- "react": "19.1.0",
79
- "react-dom": "19.1.0",
80
- "rollup": "4.45.1",
74
+ "@types/node": "24.3.0",
75
+ "@types/react": "19.1.11",
76
+ "next": "15.5.0",
77
+ "react": "19.1.1",
78
+ "react-dom": "19.1.1",
79
+ "rollup": "4.48.1",
81
80
  "type-fest": "4.41.0",
82
- "typescript": "5.8.3",
83
- "@serwist/utils": "10.0.0-preview.11",
84
- "@serwist/configs": "10.0.0-preview.11"
81
+ "typescript": "5.9.2",
82
+ "@serwist/configs": "10.0.0-preview.13",
83
+ "@serwist/utils": "10.0.0-preview.13"
85
84
  },
86
85
  "peerDependencies": {
87
86
  "next": ">=14.0.0",
88
87
  "react": ">=18.0.0",
89
- "typescript": ">=5.0.0"
88
+ "typescript": ">=5.0.0",
89
+ "esbuild-wasm": "^0.25.0"
90
90
  },
91
91
  "peerDependenciesMeta": {
92
92
  "typescript": {
@@ -21,7 +21,7 @@ export function SerwistProvider({ swUrl, register = true, reloadOnOnline = true,
21
21
  const [serwist] = useState(() => {
22
22
  if (typeof window === "undefined") return null;
23
23
  if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) {
24
- window.serwist = new Serwist(swUrl, { ...options, scope: options?.scope || "/" });
24
+ window.serwist = new Serwist(swUrl, { ...options, type: options?.type || "module", scope: options?.scope || "/" });
25
25
  }
26
26
  return window.serwist ?? null;
27
27
  });
@@ -1,18 +1,25 @@
1
1
  import path from "node:path";
2
- import { basePartial, globPartial, injectPartial } from "@serwist/build/schema";
2
+ import { assertType, type Equals, basePartial, globPartial, injectPartial } from "@serwist/build/schema";
3
3
  import z from "zod";
4
- import { DEFAULT_GLOB_PATTERNS } from "./lib/constants.js";
4
+ import { DEFAULT_GLOB_PATTERNS, SUPPORTED_ESBUILD_OPTIONS } from "./lib/constants.js";
5
+ import type { InjectManifestOptions, InjectManifestOptionsComplete, TurboPartial, TurboResolved } from "./types.js";
6
+
7
+ export const turboPartial = z.strictObject({
8
+ cwd: z.string().prefault(process.cwd()),
9
+ basePath: z.string(),
10
+ esbuildOptions: z.partialRecord(z.literal(SUPPORTED_ESBUILD_OPTIONS), z.any()).prefault({}),
11
+ });
5
12
 
6
13
  export const injectManifestOptions = z
7
14
  .strictObject({
8
15
  ...basePartial.shape,
9
16
  ...globPartial.shape,
10
17
  ...injectPartial.shape,
11
- cwd: z.string().prefault(process.cwd()),
12
- basePath: z.string(),
18
+ ...turboPartial.shape,
13
19
  globPatterns: z.array(z.string()).prefault(DEFAULT_GLOB_PATTERNS),
14
20
  globDirectory: z.string().optional(),
15
21
  })
22
+ .omit({ disablePrecacheManifest: true })
16
23
  .transform((input) => {
17
24
  return {
18
25
  ...input,
@@ -20,3 +27,8 @@ export const injectManifestOptions = z
20
27
  globDirectory: input.globDirectory ?? input.cwd,
21
28
  };
22
29
  });
30
+
31
+ assertType<Equals<TurboPartial, z.input<typeof turboPartial>>>();
32
+ assertType<Equals<TurboResolved, z.output<typeof turboPartial>>>();
33
+ assertType<Equals<InjectManifestOptions, z.input<typeof injectManifestOptions>>>();
34
+ assertType<Equals<InjectManifestOptionsComplete, z.output<typeof injectManifestOptions>>>();
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // Workaround for Next.js + Turbopack, while plugins are still
2
+ // not supported. This relies on Next.js Route Handlers and file
3
+ // name determinism.
1
4
  import path from "node:path";
2
5
  import { type BuildResult, getFileManifestEntries, rebasePath } from "@serwist/build";
3
6
  import { SerwistConfigError, validationErrorMap } from "@serwist/build/schema";
@@ -16,7 +19,7 @@ const logSerwistResult = (filePath: string, buildResult: Pick<BuildResult, "coun
16
19
  const hasWarnings = warnings && warnings.length > 0;
17
20
  // The route is reinitiated for each `path` param, so we only log results
18
21
  // if we're prerendering for sw.js.
19
- if (filePath === "sw.js") {
22
+ if (filePath === "sw.js" && (hasWarnings || count > 0)) {
20
23
  logger[hasWarnings ? "warn" : "event"](
21
24
  `${cyan(count)} precache entries ${dim(`(${(size / 1024).toFixed(2)} KiB)`)}${
22
25
  hasWarnings ? `\n${yellow(["⚠ warnings", ...warnings.map((w) => ` ${w}`), ""].join("\n"))}` : ""
@@ -54,32 +57,37 @@ export const createSerwistRoute = (options: InjectManifestOptions) => {
54
57
  dynamicParams = false as const,
55
58
  revalidate = false as const;
56
59
  const validation = validateGetManifestOptions(options).then((config) => {
57
- // Make sure we leave swSrc out of the precache manifest.
58
- config.globIgnores.push(
59
- rebasePath({
60
- file: config.swSrc,
61
- baseDirectory: config.globDirectory,
62
- }),
63
- );
64
- if (!config.manifestTransforms) {
65
- config.manifestTransforms = [];
66
- }
67
- config.manifestTransforms.push((manifestEntries) => {
68
- const manifest = manifestEntries.map((m) => {
69
- // Replace all references to .next/ with "/_next/".
70
- if (m.url.startsWith(".next/")) m.url = `/_next/${m.url.slice(6)}`;
71
- // Replace all references to public/ with "$(basePath)/".
72
- if (m.url.startsWith("public/")) m.url = path.posix.join(config.basePath, m.url.slice(7));
73
- return m;
74
- });
75
- return { manifest, warnings: [] };
76
- });
77
- return config;
60
+ return {
61
+ ...config,
62
+ disablePrecacheManifest: isDev,
63
+ additionalPrecacheEntries: isDev ? [] : config.additionalPrecacheEntries,
64
+ globIgnores: [
65
+ ...config.globIgnores,
66
+ // Make sure we leave swSrc out of the precache manifest.
67
+ rebasePath({
68
+ file: config.swSrc,
69
+ baseDirectory: config.globDirectory,
70
+ }),
71
+ ],
72
+ manifestTransforms: [
73
+ ...(config.manifestTransforms ?? []),
74
+ (manifestEntries) => {
75
+ const manifest = manifestEntries.map((m) => {
76
+ // Replace all references to .next/ with "/_next/".
77
+ if (m.url.startsWith(".next/")) m.url = `/_next/${m.url.slice(6)}`;
78
+ // Replace all references to public/ with "$(basePath)/".
79
+ if (m.url.startsWith("public/")) m.url = path.posix.join(config.basePath, m.url.slice(7));
80
+ return m;
81
+ });
82
+ return { manifest, warnings: [] };
83
+ },
84
+ ],
85
+ };
78
86
  });
79
- const generateStaticParams = () => {
80
- return [{ path: "sw.js" }, { path: "sw.js.map" }];
81
- };
82
87
  let map: Map<string, string> | null = null;
88
+ // NOTE: ALL FILES MUST HAVE DETERMINISTIC NAMES. THIS IS BECAUSE
89
+ // THE FOLLOWING MAP IS LOADED SEPARATELY FOR `generateStaticParams`
90
+ // AND EVERY `GET` REQUEST TO EACH OF THE FILES.
83
91
  const loadMap = async (filePath: string) => {
84
92
  const config = await validation;
85
93
  const { count, size, manifestEntries, warnings } = await getFileManifestEntries(config);
@@ -88,19 +96,27 @@ export const createSerwistRoute = (options: InjectManifestOptions) => {
88
96
  const manifestString = manifestEntries === undefined ? "undefined" : JSON.stringify(manifestEntries, null, 2);
89
97
  logSerwistResult(filePath, { count, size, warnings });
90
98
  const result = await (await esbuild).build({
91
- entryPoints: [{ in: config.swSrc, out: "sw" }],
92
- format: "esm",
93
99
  sourcemap: true,
100
+ format: "esm",
101
+ target: ["chrome64", "edge79", "firefox67", "opera51", "safari12"],
102
+ treeShaking: true,
103
+ minify: !isDev,
94
104
  bundle: true,
105
+ ...config.esbuildOptions,
106
+ platform: "browser",
107
+ define: {
108
+ ...config.esbuildOptions.define,
109
+ ...(injectionPoint ? { [injectionPoint]: manifestString } : {}),
110
+ },
111
+ outdir: config.cwd,
95
112
  write: false,
96
- minify: !isDev,
97
- define: injectionPoint
98
- ? {
99
- [injectionPoint]: manifestString,
100
- }
101
- : undefined,
102
- outdir: process.cwd(),
103
113
  entryNames: "[name]",
114
+ // Asset and chunk names must be at the top, as our path is `/serwist/[path]`,
115
+ // not `/serwist/[...path]`, meaning that we can't resolve paths deeper
116
+ // than one level.
117
+ assetNames: "[name]-[hash]",
118
+ chunkNames: "[name]-[hash]",
119
+ entryPoints: [{ in: config.swSrc, out: "sw" }],
104
120
  });
105
121
  if (result.errors.length) {
106
122
  console.error("Failed to build the service worker.", result.errors);
@@ -111,11 +127,17 @@ export const createSerwistRoute = (options: InjectManifestOptions) => {
111
127
  }
112
128
  return new Map(result.outputFiles.map((e) => [e.path, e.text]));
113
129
  };
130
+ const generateStaticParams = async () => {
131
+ const config = await validation;
132
+ if (!map) map = await loadMap("root");
133
+ return [...map.keys().map((e) => ({ path: path.relative(config.cwd, e) }))];
134
+ };
114
135
  const GET = async (_: Request, { params }: { params: Promise<{ path: string }> }) => {
115
136
  // TODO: obviously, files get stale in development when we pull this off.
116
137
  const { path: filePath } = await params;
138
+ const config = await validation;
117
139
  if (!map) map = await loadMap(filePath);
118
- return new NextResponse(map.get(path.join(process.cwd(), filePath)), {
140
+ return new NextResponse(map.get(path.join(config.cwd, filePath)), {
119
141
  headers: {
120
142
  "Content-Type": contentTypeMap[path.extname(filePath)] || "text/plain",
121
143
  "Service-Worker-Allowed": "/",
@@ -1,4 +1,66 @@
1
+ import type { BuildOptions } from "esbuild-wasm";
2
+
1
3
  export const DEFAULT_GLOB_PATTERNS = [
2
4
  ".next/static/**/*.{js,css,html,ico,apng,png,avif,jpg,jpeg,jfif,pjpeg,pjp,gif,svg,webp,json,webmanifest}",
3
5
  "public/**/*",
4
6
  ];
7
+
8
+ export const SUPPORTED_ESBUILD_OPTIONS = [
9
+ // CommonOptions
10
+ "sourcemap",
11
+ "legalComments",
12
+ "sourceRoot",
13
+ "sourcesContent",
14
+ "format",
15
+ "globalName",
16
+ "target",
17
+ "supported",
18
+ "define",
19
+ "treeShaking",
20
+ "minify",
21
+ "mangleProps",
22
+ "reserveProps",
23
+ "mangleQuoted",
24
+ "mangleCache",
25
+ "drop",
26
+ "dropLabels",
27
+ "minifyWhitespace",
28
+ "minifyIdentifiers",
29
+ "minifySyntax",
30
+ "lineLimit",
31
+ "charset",
32
+ "ignoreAnnotations",
33
+ "jsx",
34
+ "jsxFactory",
35
+ "jsxFragment",
36
+ "jsxImportSource",
37
+ "jsxDev",
38
+ "jsxSideEffects",
39
+ "pure",
40
+ "keepNames",
41
+ "absPaths",
42
+ "color",
43
+ "logLevel",
44
+ "logLimit",
45
+ "logOverride",
46
+ "tsconfigRaw",
47
+ // BuildOptions
48
+ "bundle",
49
+ "splitting",
50
+ "preserveSymlinks",
51
+ "external",
52
+ "packages",
53
+ "alias",
54
+ "loader",
55
+ "resolveExtensions",
56
+ "mainFields",
57
+ "conditions",
58
+ "allowOverwrite",
59
+ "tsconfig",
60
+ "outExtension",
61
+ "publicPath",
62
+ "inject",
63
+ "banner",
64
+ "footer",
65
+ "plugins",
66
+ ] as const satisfies readonly (keyof BuildOptions)[];
package/src/types.ts CHANGED
@@ -8,10 +8,13 @@ import type {
8
8
  OptionalGlobDirectoryPartial,
9
9
  RequiredGlobDirectoryResolved,
10
10
  } from "@serwist/build";
11
- import { assertType, type Equals } from "@serwist/build/schema";
12
- import type { Prettify } from "@serwist/utils";
13
- import type z from "zod";
14
- import type { injectManifestOptions } from "./index.schema.js";
11
+ import type { Prettify, Require } from "@serwist/utils";
12
+ import type { BuildOptions } from "esbuild-wasm";
13
+ import type { SUPPORTED_ESBUILD_OPTIONS } from "./lib/constants.js";
14
+
15
+ export type EsbuildSupportedOptions = (typeof SUPPORTED_ESBUILD_OPTIONS)[number];
16
+
17
+ export type EsbuildOptions = Pick<BuildOptions, EsbuildSupportedOptions>;
15
18
 
16
19
  export interface TurboPartial {
17
20
  /**
@@ -25,13 +28,15 @@ export interface TurboPartial {
25
28
  * is not configured, set to `/`.
26
29
  */
27
30
  basePath: string;
31
+ esbuildOptions?: EsbuildOptions;
28
32
  }
29
33
 
30
- export type TurboResolved = Required<TurboPartial>;
31
-
32
- export type InjectManifestOptions = Prettify<BasePartial & GlobPartial & InjectPartial & OptionalGlobDirectoryPartial & TurboPartial>;
34
+ export type TurboResolved = Require<TurboPartial, "cwd" | "esbuildOptions">;
33
35
 
34
- export type InjectManifestOptionsComplete = Prettify<BaseResolved & GlobResolved & InjectResolved & RequiredGlobDirectoryResolved & TurboResolved>;
36
+ export type InjectManifestOptions = Prettify<
37
+ Omit<BasePartial & GlobPartial & InjectPartial & OptionalGlobDirectoryPartial & TurboPartial, "disablePrecacheManifest">
38
+ >;
35
39
 
36
- assertType<Equals<InjectManifestOptions, z.input<typeof injectManifestOptions>>>();
37
- assertType<Equals<InjectManifestOptionsComplete, z.output<typeof injectManifestOptions>>>();
40
+ export type InjectManifestOptionsComplete = Prettify<
41
+ Omit<BaseResolved & GlobResolved & InjectResolved & RequiredGlobDirectoryResolved & TurboResolved, "disablePrecacheManifest">
42
+ >;