From 4c6aa5824ca20d15e7cf28ec28a5991f1f64ecc9 Mon Sep 17 00:00:00 2001
From: DuCanhGH <75556609+DuCanhGH@users.noreply.github.com>
Date: Sat, 1 Jul 2023 11:36:01 +0700
Subject: [PATCH] fix(next-pwa): fixed build crashing when swcMinify is set to
false
---
.changeset/eighty-bags-beg.md | 5 +
docs/content/next-pwa/configuring.mdx | 2 +
packages/next-pwa/src/types.ts | 4 +-
.../src/webpack-builders/constants.ts | 22 ----
.../next-pwa/src/webpack-builders/utils.ts | 32 ++++-
packages/utils/src/index.ts | 2 +-
packages/utils/src/swc-minify.ts | 112 ----------------
packages/utils/src/terser-minify.ts | 124 ++++++++++++++++++
8 files changed, 160 insertions(+), 143 deletions(-)
create mode 100644 .changeset/eighty-bags-beg.md
delete mode 100644 packages/next-pwa/src/webpack-builders/constants.ts
delete mode 100644 packages/utils/src/swc-minify.ts
create mode 100644 packages/utils/src/terser-minify.ts
diff --git a/.changeset/eighty-bags-beg.md b/.changeset/eighty-bags-beg.md
new file mode 100644
index 00000000..11ba7236
--- /dev/null
+++ b/.changeset/eighty-bags-beg.md
@@ -0,0 +1,5 @@
+---
+"@ducanh2912/next-pwa": patch
+---
+
+fix(next-pwa): fixed build crashing when swcMinify is set to false
diff --git a/docs/content/next-pwa/configuring.mdx b/docs/content/next-pwa/configuring.mdx
index bec650a9..7d33ec36 100644
--- a/docs/content/next-pwa/configuring.mdx
+++ b/docs/content/next-pwa/configuring.mdx
@@ -79,6 +79,8 @@ export default withPWA({
- `extendDefaultRuntimeCaching` — Extend the default `runtimeCaching` array. Only effective when `runtimeCaching` is specified.
+- `swcMinify` — Use [`swc`](https://swc.rs) to minify the custom worker, fallback worker,...
+
### Experimental
- `aggressiveFrontEndNavCaching` — Cache every `` and `` on frontend navigation. Requires `cacheOnFrontEndNav` to be enabled.
diff --git a/packages/next-pwa/src/types.ts b/packages/next-pwa/src/types.ts
index 0ba7d764..e2d18075 100644
--- a/packages/next-pwa/src/types.ts
+++ b/packages/next-pwa/src/types.ts
@@ -174,8 +174,8 @@ export interface PluginOptions {
*/
extendDefaultRuntimeCaching?: boolean;
/**
- * Use `swc` to minify custom workers, the fallback worker,...
- * @default nextConfig.swcMinify // or true if undefined
+ * Use [`swc`](https://swc.rs) to minify the custom worker, fallback worker,...
+ * @default nextConfig.swcMinify
*/
swcMinify?: boolean;
}
diff --git a/packages/next-pwa/src/webpack-builders/constants.ts b/packages/next-pwa/src/webpack-builders/constants.ts
deleted file mode 100644
index 5ce6d2a6..00000000
--- a/packages/next-pwa/src/webpack-builders/constants.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { MinimizerOptions, TerserOptions } from "terser-webpack-plugin";
-import { resolveSwc } from "utils";
-
-export const TERSER_OPTIONS: MinimizerOptions & {
- resolveSwc: typeof resolveSwc;
-} = {
- compress: {
- ecma: 5,
- comparisons: false,
- inline: 2,
- },
- mangle: {
- safari10: true,
- },
- format: {
- ecma: 5,
- safari10: true,
- comments: false,
- ascii_only: true,
- },
- resolveSwc,
-};
diff --git a/packages/next-pwa/src/webpack-builders/utils.ts b/packages/next-pwa/src/webpack-builders/utils.ts
index 59da9621..ae9f22f8 100644
--- a/packages/next-pwa/src/webpack-builders/utils.ts
+++ b/packages/next-pwa/src/webpack-builders/utils.ts
@@ -1,16 +1,38 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
+import type { MinimizerOptions, TerserOptions } from "terser-webpack-plugin";
import TerserPlugin from "terser-webpack-plugin";
-import { swcMinify } from "utils";
+import { resolveSwc, terserMinify } from "utils";
import type { Configuration } from "webpack";
import defaultSwcRc from "../.swcrc.json";
-import { TERSER_OPTIONS } from "./constants.js";
import { NextPWAContext } from "./context.js";
const __dirname = fileURLToPath(new URL(".", import.meta.url));
+const resolveTerserOptions = (): MinimizerOptions & {
+ resolveSwc: typeof resolveSwc;
+ useSwcMinify: boolean | undefined;
+} => ({
+ compress: {
+ ecma: 5,
+ comparisons: false,
+ inline: 2,
+ },
+ mangle: {
+ safari10: true,
+ },
+ format: {
+ ecma: 5,
+ safari10: true,
+ comments: false,
+ ascii_only: true,
+ },
+ resolveSwc,
+ useSwcMinify: NextPWAContext.useSwcMinify,
+});
+
export const getSharedWebpackConfig = ({
swcRc = defaultSwcRc,
}: {
@@ -20,10 +42,8 @@ export const getSharedWebpackConfig = ({
minimize: true,
minimizer: [
new TerserPlugin({
- minify: NextPWAContext.useSwcMinify
- ? swcMinify
- : TerserPlugin.terserMinify,
- terserOptions: TERSER_OPTIONS,
+ minify: terserMinify,
+ terserOptions: resolveTerserOptions(),
}),
],
};
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 0c763dff..2d412487 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -5,4 +5,4 @@ export { loadTSConfig } from "./load-tsconfig.js";
export * as logger from "./logger.js";
export { resolveSwc } from "./resolve-swc.js";
export { swcLoader } from "./swc-loader.js";
-export { swcMinify } from "./swc-minify.js";
+export { terserMinify } from "./terser-minify.js";
diff --git a/packages/utils/src/swc-minify.ts b/packages/utils/src/swc-minify.ts
deleted file mode 100644
index af61d726..00000000
--- a/packages/utils/src/swc-minify.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import type {
- Compiler,
- JsMinifyOptions,
- TerserCompressOptions,
-} from "@swc/core";
-import type {
- CustomOptions,
- default as TerserWebpack,
- Input,
- MinimizedResult,
- PredefinedOptions,
- SourceMapInput,
-} from "terser-webpack-plugin";
-
-/**
- * Custom `terser-webpack-plugin` minifier (with `@swc/core`).
- * @param input
- * @param sourceMap
- * @param minimizerOptions
- * @return
- */
-export const swcMinify = async (
- input: Input,
- sourceMap: SourceMapInput | undefined,
- options: PredefinedOptions & CustomOptions
-): Promise => {
- const { resolveSwc, ...minimizerOptions } = options;
-
- const buildSwcOptions = (
- swcOptions: PredefinedOptions & JsMinifyOptions
- ): JsMinifyOptions & {
- sourceMap: boolean | undefined;
- compress: TerserCompressOptions;
- } => {
- return {
- ...swcOptions,
- compress:
- typeof swcOptions.compress === "boolean"
- ? swcOptions.compress
- ? {}
- : false
- : { ...swcOptions.compress },
- mangle:
- swcOptions.mangle == null
- ? true
- : typeof swcOptions.mangle === "boolean"
- ? swcOptions.mangle
- : { ...swcOptions.mangle },
- sourceMap: undefined,
- };
- };
-
- const fallbackToTerser = () => {
- return (
- require("terser-webpack-plugin") as typeof TerserWebpack
- ).terserMinify(input, sourceMap, minimizerOptions, false);
- };
-
- let swc: Compiler;
- try {
- swc = resolveSwc();
- } catch {
- // swc might not be available, fallback to terser
- return fallbackToTerser();
- }
-
- if (!swc.minify) {
- // turns out that older versions of Next had `next/dist/build/swc` with no `swc.minify`...
- return fallbackToTerser();
- }
-
- // Copy `swc` options
- const swcOptions = buildSwcOptions(minimizerOptions);
-
- // Let `swc` generate a SourceMap
- if (sourceMap) {
- swcOptions.sourceMap = true;
- }
-
- if (swcOptions.compress) {
- // More optimizations
- if (typeof swcOptions.compress.ecma === "undefined") {
- swcOptions.compress.ecma = swcOptions.ecma;
- }
-
- if (
- swcOptions.ecma === 5 &&
- typeof swcOptions.compress.arrows === "undefined"
- ) {
- swcOptions.compress.arrows = false;
- }
- }
-
- const [[filename, code]] = Object.entries(input);
- const result = await swc.minify(code, swcOptions);
-
- let map;
-
- if (result.map) {
- map = JSON.parse(result.map);
-
- // TODO workaround for swc because `filename` is not preset as in `swc` signature as for `terser`
- map.sources = [filename];
-
- delete map.sourcesContent;
- }
-
- return {
- code: result.code,
- map,
- };
-};
diff --git a/packages/utils/src/terser-minify.ts b/packages/utils/src/terser-minify.ts
new file mode 100644
index 00000000..67ea481b
--- /dev/null
+++ b/packages/utils/src/terser-minify.ts
@@ -0,0 +1,124 @@
+import type {
+ Compiler,
+ JsMinifyOptions,
+ TerserCompressOptions,
+} from "@swc/core";
+import type {
+ CustomOptions,
+ default as TerserWebpack,
+ ExtractCommentsOptions,
+ Input,
+ MinimizedResult,
+ PredefinedOptions,
+ SourceMapInput,
+} from "terser-webpack-plugin";
+
+import type { resolveSwc as SwcResolver } from "./resolve-swc.js";
+
+/**
+ * Custom `terser-webpack-plugin` minifier
+ * @param input
+ * @param sourceMap
+ * @param minimizerOptions
+ * @return
+ */
+export const terserMinify = async (
+ input: Input,
+ sourceMap: SourceMapInput | undefined,
+ options: PredefinedOptions & CustomOptions,
+ extractComments: ExtractCommentsOptions | undefined
+): Promise => {
+ const { resolveSwc, useSwcMinify, ...minimizerOptions } =
+ options as typeof options & {
+ resolveSwc: typeof SwcResolver;
+ useSwcMinify: boolean | undefined;
+ };
+
+ const buildSwcOptions = (
+ swcOptions: PredefinedOptions & JsMinifyOptions
+ ): JsMinifyOptions & {
+ sourceMap: boolean | undefined;
+ compress: TerserCompressOptions;
+ } => {
+ return {
+ ...swcOptions,
+ compress:
+ typeof swcOptions.compress === "boolean"
+ ? swcOptions.compress
+ ? {}
+ : false
+ : { ...swcOptions.compress },
+ mangle:
+ swcOptions.mangle == null
+ ? true
+ : typeof swcOptions.mangle === "boolean"
+ ? swcOptions.mangle
+ : { ...swcOptions.mangle },
+ sourceMap: undefined,
+ };
+ };
+
+ const fallbackToTerser = () => {
+ return (
+ require("terser-webpack-plugin") as typeof TerserWebpack
+ ).terserMinify(input, sourceMap, minimizerOptions, extractComments);
+ };
+
+ if (useSwcMinify) {
+ let swc: Compiler;
+ try {
+ swc = resolveSwc();
+ } catch {
+ // swc might not be available, fallback to terser
+ return fallbackToTerser();
+ }
+
+ if (!swc.minify) {
+ // turns out that older versions of Next had `next/dist/build/swc` with no `swc.minify`...
+ return fallbackToTerser();
+ }
+
+ // Copy `swc` options
+ const swcOptions = buildSwcOptions(minimizerOptions);
+
+ // Let `swc` generate a SourceMap
+ if (sourceMap) {
+ swcOptions.sourceMap = true;
+ }
+
+ if (swcOptions.compress) {
+ // More optimizations
+ if (typeof swcOptions.compress.ecma === "undefined") {
+ swcOptions.compress.ecma = swcOptions.ecma;
+ }
+
+ if (
+ swcOptions.ecma === 5 &&
+ typeof swcOptions.compress.arrows === "undefined"
+ ) {
+ swcOptions.compress.arrows = false;
+ }
+ }
+
+ const [[filename, code]] = Object.entries(input);
+ const result = await swc.minify(code, swcOptions);
+
+ let map;
+
+ if (result.map) {
+ map = JSON.parse(result.map);
+
+ // TODO workaround for swc because `filename` is not preset as in `swc` signature as for `terser`
+ map.sources = [filename];
+
+ delete map.sourcesContent;
+ }
+
+ return {
+ code: result.code,
+ map,
+ };
+ }
+
+ return fallbackToTerser();
+};