Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(next-pwa): fixed build crashing when swcMinify is set to false #49

Merged
merged 1 commit into from
Jul 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
};