@serwist/next 9.4.0 → 9.4.2

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.
@@ -1 +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"}
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,EAAoB,MAAM,uBAAuB,CAAC;AAI/E,eAAO,MAAM,OAAO,GAAU,SAAS,cAAc,KAAG,OAAO,CAAC,YAAY,CAiF3E,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -2,19 +2,87 @@ import { createRequire } from 'module';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { rebasePath } from '@serwist/build';
5
- import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from 'next/constants.js';
5
+ import { MODERN_BROWSERSLIST_TARGET, PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from 'next/constants.js';
6
+ import browserslist from 'browserslist';
7
+
8
+ const SUPPORTED_ESBUILD_TARGETS = [
9
+ "chrome",
10
+ "deno",
11
+ "edge",
12
+ "firefox",
13
+ "hermes",
14
+ "ie",
15
+ "ios",
16
+ "node",
17
+ "opera",
18
+ "rhino",
19
+ "safari"
20
+ ];
21
+ const UNSUPPORTED_BROWSERLIST_TARGETS = [
22
+ "android 4",
23
+ "android 3",
24
+ "android 2"
25
+ ];
6
26
 
7
27
  const generateGlobPatterns = (distDir)=>[
8
28
  `${distDir}static/**/*.{js,css,html,ico,apng,png,avif,jpg,jpeg,jfif,pjpeg,pjp,gif,svg,webp,json,webmanifest}`,
9
29
  "public/**/*"
10
30
  ];
31
+ const compare = (a, b)=>{
32
+ if (a < b) return -1;
33
+ if (a > b) return 1;
34
+ return 0;
35
+ };
36
+ const compareSemver = (a, b)=>{
37
+ return compare(Number.parseInt(a[0], 10), Number.parseInt(b[0], 10)) || compare(Number.parseInt(a[1] || "0", 10), Number.parseInt(b[1] || "0", 10)) || compare(Number.parseInt(a[2] || "0", 10), Number.parseInt(b[2] || "0", 10));
38
+ };
39
+ const loadBrowserslist = (cwd)=>{
40
+ const browserslistConfig = browserslist.loadConfig({
41
+ path: cwd
42
+ }) ?? MODERN_BROWSERSLIST_TARGET;
43
+ return browserslist(browserslistConfig).filter((query)=>!UNSUPPORTED_BROWSERLIST_TARGETS.some((target)=>query.startsWith(target))).map((query)=>{
44
+ const modified = query === "safari TP" ? browserslist("last 1 safari version")[0] : query;
45
+ const split = modified.split(" ");
46
+ if (split[0] === "android" || split[0] === "and_chr") {
47
+ split[0] = "chrome";
48
+ }
49
+ if (split[0] === "and_ff") {
50
+ split[0] = "firefox";
51
+ }
52
+ if (split[0] === "ios_saf" || split[0] === "ios") {
53
+ split[0] = "safari";
54
+ }
55
+ if (split[1].includes("-")) {
56
+ split[1] = split[1].slice(0, split[1].indexOf("-"));
57
+ }
58
+ if (split[1].endsWith(".0")) {
59
+ split[1] = split[1].slice(0, -2);
60
+ }
61
+ return split;
62
+ }).filter((split)=>SUPPORTED_ESBUILD_TARGETS.includes(split[0]) && /^\d+(\.\d+)*$/.test(split[1])).sort((a, b)=>{
63
+ if (a[0] === b[0]) {
64
+ return compareSemver(b[1].split("."), a[1].split("."));
65
+ } else {
66
+ return compare(a[0], b[0]);
67
+ }
68
+ }).reduce((acc, browser)=>{
69
+ const existingIndex = acc.findIndex((br)=>br[0] === browser[0]);
70
+ if (existingIndex !== -1) {
71
+ acc[existingIndex][1] = browser[1];
72
+ } else {
73
+ acc.push(browser);
74
+ }
75
+ return acc;
76
+ }, []).map((split)=>split.join(""));
77
+ };
11
78
 
12
79
  const __require = createRequire(import.meta.url);
13
80
  const loadNextConfig = __require("next/dist/server/config.js");
14
81
  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(), {
82
+ const cwd = process.cwd();
83
+ const isDev = process.env.NODE_ENV === "development";
84
+ const nextPhase = isDev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD;
85
+ const config = await loadNextConfig.default(nextPhase, cwd, {
18
86
  silent: false
19
87
  });
20
88
  const basePath = config.basePath || "/";
@@ -24,7 +92,7 @@ const serwist = async (options)=>{
24
92
  const distServerDir = `${distDir}server/`;
25
93
  const distAppDir = `${distServerDir}app/`;
26
94
  const distPagesDir = `${distServerDir}pages/`;
27
- const { precachePrerendered = true, globDirectory = process.cwd(), ...cliOptions } = options;
95
+ const { precachePrerendered = true, globDirectory = cwd, ...cliOptions } = options;
28
96
  for (const file of [
29
97
  cliOptions.swDest,
30
98
  `${cliOptions.swDest}.map`
@@ -35,7 +103,7 @@ const serwist = async (options)=>{
35
103
  }
36
104
  return {
37
105
  dontCacheBustURLsMatching: new RegExp(`^${distDir}static/`),
38
- disablePrecacheManifest: isWatch,
106
+ disablePrecacheManifest: isDev,
39
107
  ...cliOptions,
40
108
  globDirectory,
41
109
  globPatterns: [
@@ -93,7 +161,11 @@ const serwist = async (options)=>{
93
161
  warnings: []
94
162
  };
95
163
  }
96
- ]
164
+ ],
165
+ esbuildOptions: {
166
+ ...cliOptions.esbuildOptions,
167
+ target: cliOptions.esbuildOptions?.target ?? loadBrowserslist(cwd)
168
+ }
97
169
  };
98
170
  };
99
171
 
@@ -0,0 +1,4 @@
1
+ /** @see https://esbuild.github.io/api/#target */
2
+ export declare const SUPPORTED_ESBUILD_TARGETS: string[];
3
+ export declare const UNSUPPORTED_BROWSERLIST_TARGETS: string[];
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/config/constants.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,eAAO,MAAM,yBAAyB,UAAmG,CAAC;AAE1I,eAAO,MAAM,+BAA+B,UAA0C,CAAC"}
@@ -1,2 +1,9 @@
1
1
  export declare const generateGlobPatterns: (distDir: string) => string[];
2
+ /**
3
+ * Loads and converts Browserslist into esbuild's `target` option.
4
+ *
5
+ * @param cwd
6
+ * @returns
7
+ */
8
+ export declare const loadBrowserslist: (cwd: string) => string[];
2
9
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/config/utils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,aAGnD,CAAC;AAmBF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,EAqDpD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serwist/next",
3
- "version": "9.4.0",
3
+ "version": "9.4.2",
4
4
  "type": "module",
5
5
  "description": "A module that integrates Serwist into your Next.js application.",
6
6
  "files": [
@@ -76,14 +76,15 @@
76
76
  "./package.json": "./package.json"
77
77
  },
78
78
  "dependencies": {
79
+ "browserslist": "4.28.1",
79
80
  "glob": "10.5.0",
80
81
  "kolorist": "1.8.0",
81
82
  "semver": "7.7.3",
82
83
  "zod": "4.2.1",
83
- "@serwist/build": "9.4.0",
84
- "@serwist/webpack-plugin": "9.4.0",
85
- "@serwist/window": "9.4.0",
86
- "serwist": "9.4.0"
84
+ "@serwist/build": "9.4.2",
85
+ "@serwist/webpack-plugin": "9.4.2",
86
+ "@serwist/window": "9.4.2",
87
+ "serwist": "9.4.2"
87
88
  },
88
89
  "devDependencies": {
89
90
  "@types/node": "25.0.3",
@@ -96,15 +97,15 @@
96
97
  "type-fest": "5.3.1",
97
98
  "typescript": "5.9.3",
98
99
  "webpack": "5.104.1",
99
- "@serwist/cli": "9.4.0",
100
- "@serwist/configs": "9.4.0",
101
- "@serwist/utils": "9.4.0"
100
+ "@serwist/cli": "9.4.2",
101
+ "@serwist/configs": "9.4.2",
102
+ "@serwist/utils": "9.4.2"
102
103
  },
103
104
  "peerDependencies": {
104
105
  "next": ">=14.0.0",
105
106
  "react": ">=18.0.0",
106
107
  "typescript": ">=5.0.0",
107
- "@serwist/cli": "^9.4.0"
108
+ "@serwist/cli": "^9.4.2"
108
109
  },
109
110
  "peerDependenciesMeta": {
110
111
  "@serwist/cli": {
@@ -4,14 +4,15 @@ import { rebasePath } from "@serwist/build";
4
4
  import type { BuildOptions } from "@serwist/cli";
5
5
  import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "next/constants.js";
6
6
  import type { SerwistOptions } from "./lib/config/types.js";
7
- import { generateGlobPatterns } from "./lib/config/utils.js";
7
+ import { generateGlobPatterns, loadBrowserslist } from "./lib/config/utils.js";
8
8
 
9
9
  import loadNextConfig = require("next/dist/server/config.js");
10
10
 
11
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(), {
12
+ const cwd = process.cwd();
13
+ const isDev = process.env.NODE_ENV === "development";
14
+ const nextPhase = isDev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD;
15
+ const config = await loadNextConfig.default(nextPhase, cwd, {
15
16
  silent: false,
16
17
  });
17
18
  const basePath = config.basePath || "/";
@@ -21,13 +22,13 @@ export const serwist = async (options: SerwistOptions): Promise<BuildOptions> =>
21
22
  const distServerDir = `${distDir}server/`;
22
23
  const distAppDir = `${distServerDir}app/`;
23
24
  const distPagesDir = `${distServerDir}pages/`;
24
- const { precachePrerendered = true, globDirectory = process.cwd(), ...cliOptions } = options;
25
+ const { precachePrerendered = true, globDirectory = cwd, ...cliOptions } = options;
25
26
  for (const file of [cliOptions.swDest, `${cliOptions.swDest}.map`]) {
26
27
  fs.rmSync(file, { force: true });
27
28
  }
28
29
  return {
29
30
  dontCacheBustURLsMatching: new RegExp(`^${distDir}static/`),
30
- disablePrecacheManifest: isWatch,
31
+ disablePrecacheManifest: isDev,
31
32
  ...cliOptions,
32
33
  globDirectory,
33
34
  globPatterns: [
@@ -83,6 +84,10 @@ export const serwist = async (options: SerwistOptions): Promise<BuildOptions> =>
83
84
  return { manifest, warnings: [] };
84
85
  },
85
86
  ],
87
+ esbuildOptions: {
88
+ ...cliOptions.esbuildOptions,
89
+ target: cliOptions.esbuildOptions?.target ?? loadBrowserslist(cwd),
90
+ },
86
91
  };
87
92
  };
88
93
 
@@ -0,0 +1,4 @@
1
+ /** @see https://esbuild.github.io/api/#target */
2
+ export const SUPPORTED_ESBUILD_TARGETS = ["chrome", "deno", "edge", "firefox", "hermes", "ie", "ios", "node", "opera", "rhino", "safari"];
3
+
4
+ export const UNSUPPORTED_BROWSERLIST_TARGETS = ["android 4", "android 3", "android 2"];
@@ -1,4 +1,86 @@
1
+ import browserslist from "browserslist";
2
+ import { MODERN_BROWSERSLIST_TARGET } from "next/constants.js";
3
+ import { SUPPORTED_ESBUILD_TARGETS, UNSUPPORTED_BROWSERLIST_TARGETS } from "./constants.js";
4
+
1
5
  export const generateGlobPatterns = (distDir: string) => [
2
6
  `${distDir}static/**/*.{js,css,html,ico,apng,png,avif,jpg,jpeg,jfif,pjpeg,pjp,gif,svg,webp,json,webmanifest}`,
3
7
  "public/**/*",
4
8
  ];
9
+
10
+ // Source: https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/index.js#L139-L151
11
+ // License: MIT
12
+ const compare = <T extends string | number>(a: T, b: T) => {
13
+ if (a < b) return -1;
14
+ if (a > b) return +1;
15
+ return 0;
16
+ };
17
+ const compareSemver = (a: string[], b: string[]) => {
18
+ return (
19
+ compare(Number.parseInt(a[0], 10), Number.parseInt(b[0], 10)) ||
20
+ compare(Number.parseInt(a[1] || "0", 10), Number.parseInt(b[1] || "0", 10)) ||
21
+ compare(Number.parseInt(a[2] || "0", 10), Number.parseInt(b[2] || "0", 10))
22
+ );
23
+ };
24
+
25
+ // Original: https://github.com/marcofugaro/browserslist-to-esbuild/blob/0875f1a4ec71f206a634ba406c3528ca5ecf04de/src/index.js
26
+ // License: MIT
27
+ /**
28
+ * Loads and converts Browserslist into esbuild's `target` option.
29
+ *
30
+ * @param cwd
31
+ * @returns
32
+ */
33
+ export const loadBrowserslist = (cwd: string): string[] => {
34
+ const browserslistConfig = browserslist.loadConfig({ path: cwd }) ?? MODERN_BROWSERSLIST_TARGET;
35
+ return (
36
+ browserslist(browserslistConfig)
37
+ // Filter out legacy Android webview to avoid converting them into Chrome targets
38
+ .filter((query) => !UNSUPPORTED_BROWSERLIST_TARGETS.some((target) => query.startsWith(target)))
39
+ .map((query) => {
40
+ const modified = query === "safari TP" ? browserslist("last 1 safari version")[0] : query;
41
+ const split = modified.split(" ");
42
+ // https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/README.md?plain=1#L329-L350
43
+ // https://esbuild.github.io/api/#target
44
+ if (split[0] === "android" || split[0] === "and_chr") {
45
+ split[0] = "chrome";
46
+ }
47
+ if (split[0] === "and_ff") {
48
+ split[0] = "firefox";
49
+ }
50
+ if (split[0] === "ios_saf" || split[0] === "ios") {
51
+ split[0] = "safari";
52
+ }
53
+ // Remove upper version bound
54
+ if (split[1].includes("-")) {
55
+ split[1] = split[1].slice(0, split[1].indexOf("-"));
56
+ }
57
+ // Trim ending .0
58
+ if (split[1].endsWith(".0")) {
59
+ split[1] = split[1].slice(0, -2);
60
+ }
61
+ return split;
62
+ })
63
+ // Remove unsupported browsers and invalid versions
64
+ .filter((split) => SUPPORTED_ESBUILD_TARGETS.includes(split[0]) && /^\d+(\.\d+)*$/.test(split[1]))
65
+ // Re-sort the result such that the oldest versions end up the latest, same as how
66
+ // Browserslist does it.
67
+ .sort((a, b) => {
68
+ if (a[0] === b[0]) {
69
+ return compareSemver(b[1].split("."), a[1].split("."));
70
+ } else {
71
+ return compare(a[0], b[0]);
72
+ }
73
+ })
74
+ // Only pick the oldest included version for each browser to avoid duplications.
75
+ .reduce((acc, browser) => {
76
+ const existingIndex = acc.findIndex((br) => br[0] === browser[0]);
77
+ if (existingIndex !== -1) {
78
+ acc[existingIndex][1] = browser[1];
79
+ } else {
80
+ acc.push(browser);
81
+ }
82
+ return acc;
83
+ }, [] as string[][])
84
+ .map((split) => split.join(""))
85
+ );
86
+ };