Skip to content

Commit

Permalink
refactor(next-pwa, next-sw): use Next's swc bindings instead of `@swc…
Browse files Browse the repository at this point in the history
…/core` (#38)

[bump]
  • Loading branch information
DuCanhGH authored Jun 20, 2023
1 parent d060048 commit 7bd3ba7
Show file tree
Hide file tree
Showing 18 changed files with 370 additions and 230 deletions.
14 changes: 14 additions & 0 deletions .changeset/hungry-yaks-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@ducanh2912/next-pwa": major
"@ducanh2912/next-sw": minor
---

BREAKING CHANGE(next-pwa, next-sw): use next's swc bindings instead of swc/core

What: From now on we will try to resolve `next/dist/build/swc` in `swc-loader` (needed to use `cacheOnFrontEndNav`, custom workers and offline fallbacks). If it can't be resolved, we will fallback to `@swc/core` (needed to be installed manually).

Why: This is to save disk space (we don't need two `@swc/core`) and avoid exceeding Vercel's serverless size limit.

Why use Next's `next/dist/build/swc`: it seems that `@next/mdx` is also doing the same for their `mdx` Rust compiler.

How to upgrade: Usually you don't need to do anything. But if you see this line when you build your Next app: `Using @swc/core to compile next-pwa's features. Please install it if you haven't.`, please do as instructed.
11 changes: 11 additions & 0 deletions .changeset/serious-dodos-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@ducanh2912/next-pwa": major
---

BREAKING CHANGE(requirements): bump minimum Next.js version to v11

What: `next-pwa`'s minimum supported Next.js version is now 11.0.0.

Why: I noticed that `workbox-webpack-plugin` no longer works with Next.js 9 and 10, so this bumps the minimum supported Next.js version to v11.

How to upgrade: Bump `next` to at least 11.0.0.
1 change: 0 additions & 1 deletion contributing/core/developing.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,5 @@ To develop locally:
1. When you are ready to push, make a fork and then run:
```
git remote set-url origin https://github.com/YOUR_NAME/next-pwa
git branch -m MY_BRANCH_NAME
git push -u origin MY_BRANCH_NAME
```
5 changes: 5 additions & 0 deletions packages/next-pwa/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// @ts-check
/** @type {import("eslint").Linter.BaseConfig} */
module.exports = {
extends: ["plugin:jsdoc/recommended"],
plugins: ["jsdoc"],
rules: {
"jsdoc/require-param-type": "off",
},
};
4 changes: 1 addition & 3 deletions packages/next-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@
"typecheck": "tsc"
},
"dependencies": {
"@swc/core": "1.3.62",
"clean-webpack-plugin": "4.0.0",
"fast-glob": "3.2.12",
"semver": "7.5.1",
"swc-loader": "0.2.3",
"terser-webpack-plugin": "5.3.9",
"workbox-build": "7.0.0",
"workbox-core": "7.0.0",
Expand All @@ -87,7 +85,7 @@
"webpack": "5.86.0"
},
"peerDependencies": {
"next": ">=9.1.0",
"next": ">=11.0.0",
"webpack": ">=5.9.0"
}
}
8 changes: 8 additions & 0 deletions packages/next-pwa/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ const files = [
format: "esm",
},
},
{
input: "src/swc-loader.ts",
output: {
file: "dist/swc-loader.cjs",
format: "cjs",
},
external: ["semver"],
},
];

/** @type {FileEntry[]} */
Expand Down
5 changes: 1 addition & 4 deletions packages/next-pwa/src/build-custom-worker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import fs from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";

import { CleanWebpackPlugin } from "clean-webpack-plugin";
Expand All @@ -11,8 +10,6 @@ import webpack from "webpack";

import swcRc from "./.swcrc.json";

const require = createRequire(import.meta.url);

export const buildCustomWorker = ({
id,
baseDir,
Expand Down Expand Up @@ -103,7 +100,7 @@ export const buildCustomWorker = ({
},
resolveLoader: {
alias: {
"swc-loader": require.resolve("swc-loader"),
"swc-loader": path.join(__dirname, "swc-loader.cjs"),
},
},
module: {
Expand Down
4 changes: 1 addition & 3 deletions packages/next-pwa/src/build-fallback-worker/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createRequire } from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";

Expand All @@ -12,7 +11,6 @@ import type { FallbackRoutes } from "../types.js";
import { getFallbackEnvs } from "./get-fallback-envs.js";

const __dirname = fileURLToPath(new URL(".", import.meta.url));
const require = createRequire(import.meta.url);

export const buildFallbackWorker = ({
id,
Expand Down Expand Up @@ -63,7 +61,7 @@ export const buildFallbackWorker = ({
},
resolveLoader: {
alias: {
"swc-loader": require.resolve("swc-loader"),
"swc-loader": path.join(__dirname, "swc-loader.cjs"),
},
},
module: {
Expand Down
4 changes: 1 addition & 3 deletions packages/next-pwa/src/build-sw-entry-worker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createRequire } from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";

Expand All @@ -10,7 +9,6 @@ import webpack from "webpack";
import swcRc from "./.swcrc.json";

const __dirname = fileURLToPath(new URL(".", import.meta.url));
const require = createRequire(import.meta.url);

export const buildSWEntryWorker = ({
id,
Expand Down Expand Up @@ -55,7 +53,7 @@ export const buildSWEntryWorker = ({
},
resolveLoader: {
alias: {
"swc-loader": require.resolve("swc-loader"),
"swc-loader": path.join(__dirname, "swc-loader.cjs"),
},
},
module: {
Expand Down
1 change: 1 addition & 0 deletions packages/next-pwa/src/swc-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { swcLoader as default } from "utils";
2 changes: 0 additions & 2 deletions packages/next-sw/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@
"typecheck": "tsc"
},
"dependencies": {
"@swc/core": "1.3.62",
"clean-webpack-plugin": "4.0.0",
"swc-loader": "0.2.3",
"terser-webpack-plugin": "5.3.9"
},
"devDependencies": {
Expand Down
8 changes: 8 additions & 0 deletions packages/next-sw/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ const files = [
},
external: ["workbox-window"],
},
{
input: "src/swc-loader.ts",
output: {
file: "dist/swc-loader.cjs",
format: "cjs",
},
external: ["semver"],
},
];

/** @type {FileEntry[]} */
Expand Down
4 changes: 1 addition & 3 deletions packages/next-sw/src/build/generate-sw/core.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createRequire } from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";

Expand All @@ -14,7 +13,6 @@ import { getFallbackEnvs } from "./core-utils.js";
import { runtimeCachingConverter } from "./runtime-caching-converter.js";

const __dirname = fileURLToPath(new URL(".", import.meta.url));
const require = createRequire(import.meta.url);

export type ImportScripts = string[] | undefined;

Expand Down Expand Up @@ -94,7 +92,7 @@ export const generateSW = ({
},
resolveLoader: {
alias: {
"swc-loader": require.resolve("swc-loader"),
"swc-loader": path.join(__dirname, "swc-loader.cjs"),
},
},
module: {
Expand Down
1 change: 1 addition & 0 deletions packages/next-sw/src/swc-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { swcLoader as default } from "utils";
1 change: 1 addition & 0 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"devDependencies": {
"@rollup/plugin-node-resolve": "15.1.0",
"@rollup/plugin-typescript": "11.1.1",
"@swc/core": "1.3.62",
"@types/semver": "7.5.0",
"rollup": "3.24.1",
"type-fest": "3.11.1",
Expand Down
1 change: 1 addition & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { findFirstTruthy } from "./find-first-truthy.js";
export { getPackageVersion } from "./get-package-version.js";
export { loadTSConfig } from "./load-tsconfig.js";
export * as logger from "./logger.js";
export { swcLoader } from "./swc-loader.js";
133 changes: 133 additions & 0 deletions packages/utils/src/swc-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { createRequire } from "node:module";

import type { Compiler } from "@swc/core";

import * as logger from "./logger.js";

const require = createRequire(import.meta.url);

/**
* swc-loader
* @param source Source code
* @param inputSourceMap Source map
*/
export function swcLoader(this: any, source: string, inputSourceMap: string) {
// Make the loader async
const callback = this.async();
const filename = this.resourcePath;

let loaderOptions =
(typeof this.getOptions === "function"
? this.getOptions()
: require("loader-utils").getOptions(this)) || {};

// Standardize on 'sourceMaps' as the key passed through to Webpack, so that
// users may safely use either one alongside our default use of
// 'this.sourceMap' below without getting error about conflicting aliases.
if (
Object.prototype.hasOwnProperty.call(loaderOptions, "sourceMap") &&
!Object.prototype.hasOwnProperty.call(loaderOptions, "sourceMaps")
) {
loaderOptions = Object.assign({}, loaderOptions, {
sourceMaps: loaderOptions.sourceMap,
});
delete loaderOptions.sourceMap;
}

if (inputSourceMap && typeof inputSourceMap === "object") {
inputSourceMap = JSON.stringify(inputSourceMap);
}

const programmaticOptions = Object.assign({}, loaderOptions, {
filename,
inputSourceMap: inputSourceMap || undefined,

// Set the default sourcemap behavior based on Webpack's mapping flag,
// but allow users to override if they want.
sourceMaps:
loaderOptions.sourceMaps === undefined
? this.sourceMap
: loaderOptions.sourceMaps,

// Ensure that Webpack will get a full absolute path in the sourcemap
// so that it can properly map the module back to its internal cached
// modules.
sourceFileName: filename,
});
if (!programmaticOptions.inputSourceMap) {
delete programmaticOptions.inputSourceMap;
}
const sync = programmaticOptions.sync;
const parseMap = programmaticOptions.parseMap;

let swc: Compiler;
try {
// avoid installing @swc/core
swc = require("next/dist/build/swc");
} catch {
logger.info(
"Using @swc/core to compile next-pwa's features. Please install it if you haven't."
);
swc = require("@swc/core");
}

// Remove loader related options
delete programmaticOptions.sync;
delete programmaticOptions.parseMap;
delete programmaticOptions.customize;
delete programmaticOptions.cacheDirectory;
delete programmaticOptions.cacheIdentifier;
delete programmaticOptions.cacheCompression;
delete programmaticOptions.metadataSubscribers;

// auto detect development mode
if (
this.mode &&
programmaticOptions.jsc &&
programmaticOptions.jsc.transform &&
programmaticOptions.jsc.transform.react &&
!Object.prototype.hasOwnProperty.call(
programmaticOptions.jsc.transform.react,
"development"
)
) {
programmaticOptions.jsc.transform.react.development =
this.mode === "development";
}

if (programmaticOptions.sourceMaps === "inline") {
// Babel has this weird behavior where if you set "inline", we
// inline the sourcemap, and set 'result.map = null'. This results
// in bad behavior from Babel since the maps get put into the code,
// which Webpack does not expect, and because the map we return to
// Webpack is null, which is also bad. To avoid that, we override the
// behavior here so "inline" just behaves like 'true'.
programmaticOptions.sourceMaps = true;
}

try {
if (sync) {
const output = swc.transformSync(source, programmaticOptions);
callback(
null,
output.code,
parseMap && output.map ? JSON.parse(output.map) : output.map
);
} else {
swc.transform(source, programmaticOptions).then(
(output) => {
callback(
null,
output.code,
parseMap && output.map ? JSON.parse(output.map) : output.map
);
},
(err) => {
callback(err);
}
);
}
} catch (e) {
callback(e);
}
}
Loading

0 comments on commit 7bd3ba7

Please sign in to comment.