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

refactor(next-pwa, next-sw): use Next's swc bindings instead of @swc/core #38

Merged
merged 4 commits into from
Jun 20, 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
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