Skip to content

Commit

Permalink
fix(next-pwa): fixed build crashing when swcMinify is set to false (#49)
Browse files Browse the repository at this point in the history
[bump]
  • Loading branch information
DuCanhGH authored Jul 1, 2023
1 parent c05c014 commit b53cf03
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 143 deletions.
5 changes: 5 additions & 0 deletions .changeset/eighty-bags-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ducanh2912/next-pwa": patch
---

fix(next-pwa): fixed build crashing when swcMinify is set to false
2 changes: 2 additions & 0 deletions docs/content/next-pwa/configuring.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<link rel="stylesheet" />` and `<script />` on frontend navigation. Requires `cacheOnFrontEndNav` to be enabled.
Expand Down
4 changes: 2 additions & 2 deletions packages/next-pwa/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
22 changes: 0 additions & 22 deletions packages/next-pwa/src/webpack-builders/constants.ts

This file was deleted.

32 changes: 26 additions & 6 deletions packages/next-pwa/src/webpack-builders/utils.ts
Original file line number Diff line number Diff line change
@@ -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<TerserOptions> & {
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,
}: {
Expand All @@ -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(),
}),
],
};
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
112 changes: 0 additions & 112 deletions packages/utils/src/swc-minify.ts

This file was deleted.

124 changes: 124 additions & 0 deletions packages/utils/src/terser-minify.ts
Original file line number Diff line number Diff line change
@@ -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<MinimizedResult> => {
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();
};

0 comments on commit b53cf03

Please sign in to comment.