Skip to content

Commit

Permalink
fix(next-pwa,compatibility): remove node: protocol from imports
Browse files Browse the repository at this point in the history
[bump]
  • Loading branch information
DuCanhGH committed May 25, 2023
1 parent 808bbd9 commit 9045662
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 108 deletions.
7 changes: 7 additions & 0 deletions .changeset/quiet-cameras-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@ducanh2912/next-pwa": patch
---

fix(next-pwa,compatibility): remove `node:` protocol from imports

- We currently don't have a clear version requirement for Node.js, and as such we should support as many versions as possible. It seems that only Node.js 16 and later support `node:` protocol imports for CJS, so we remove this protocol by using `@rollup/plugin-alias`. This compatibility patch might be removed in the future though.
27 changes: 19 additions & 8 deletions packages/next-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,31 @@
"source": "./src/index.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/ducanh2912-next-pwa.cjs",
"default": "./dist/ducanh2912-next-pwa.module.js"
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"default": {
"types": "./dist/index.module.d.ts",
"default": "./dist/index.module.js"
}
},
"./workbox": {
"types": "./dist/sw-entry.d.ts"
"require": {
"types": "./dist/sw-entry.d.cts"
},
"default": {
"types": "./dist/sw-entry.module.d.ts"
}
}
},
"main": "./dist/ducanh2912-next-pwa.cjs",
"module": "./dist/ducanh2912-next-pwa.module.js",
"types": "./dist/index.d.ts",
"main": "./dist/index.cjs",
"module": "./dist/index.module.js",
"types": "./dist/index.module.d.ts",
"typesVersions": {
"*": {
"workbox": [
"./dist/sw-entry.d.ts"
"./dist/sw-entry.module.d.ts"
]
}
},
Expand Down Expand Up @@ -58,6 +68,7 @@
"workbox-window": "6.5.4"
},
"devDependencies": {
"@rollup/plugin-alias": "5.0.0",
"@rollup/plugin-json": "6.0.0",
"@rollup/plugin-node-resolve": "15.0.2",
"@rollup/plugin-terser": "0.4.3",
Expand Down
30 changes: 16 additions & 14 deletions packages/next-pwa/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* "input" | "output" | "external" | "plugins"
* >} FileEntry
*/
import alias from "@rollup/plugin-alias";
import json from "@rollup/plugin-json";
import nodeResolve from "@rollup/plugin-node-resolve";
import terser from "@rollup/plugin-terser";
Expand All @@ -20,12 +21,12 @@ const files = [
input: "src/index.ts",
output: [
{
file: "dist/ducanh2912-next-pwa.cjs",
file: "dist/index.cjs",
format: "cjs",
exports: "named",
},
{
file: "dist/ducanh2912-next-pwa.module.js",
file: "dist/index.module.js",
format: "esm",
},
],
Expand Down Expand Up @@ -66,11 +67,17 @@ const files = [
const declarations = [
{
input: "dist/dts/index.d.ts",
output: [{ format: "es", file: "dist/index.d.ts" }],
output: [
{ format: "es", file: "dist/index.module.d.ts" },
{ format: "cjs", file: "dist/index.d.cts" },
],
},
{
input: "dist/dts/sw-entry.d.ts",
output: [{ format: "es", file: "dist/sw-entry.d.ts" }],
output: [
{ format: "es", file: "dist/sw-entry.module.d.ts" },
{ format: "cjs", file: "dist/sw-entry.d.cts" },
],
},
];

Expand All @@ -85,16 +92,16 @@ for (const { input, output, external, plugins } of files) {
input,
output,
external,
watch: {
chokidar: {
usePolling: false,
},
},
plugins: [
nodeResolve({
exportConditions: ["node"],
preferBuiltins: true,
}),
// ensure compatibility by removing `node:` protocol (this MUST
// exclude "node: protocol"-only core modules such as `node:test`).
alias({
entries: [{ find: /node:(?!test)(.*)$/, replacement: "$1" }],
}),
typescript({
noForceEmit: true,
noEmitOnError: !isDev,
Expand All @@ -117,11 +124,6 @@ for (const { input, output, external, plugins } of declarations) {
input,
output,
external,
watch: {
chokidar: {
usePolling: false,
},
},
plugins: [dts(), ...[plugins ?? []]],
})
);
Expand Down
100 changes: 27 additions & 73 deletions packages/next-pwa/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import { CleanWebpackPlugin } from "clean-webpack-plugin";
import fg from "fast-glob";
import type { NextConfig } from "next";
import { loadTSConfig, logger } from "utils";
import type { Asset, Configuration, default as webpackType } from "webpack";
import type { GenerateSWConfig } from "workbox-webpack-plugin";
import type { Configuration, default as WebpackType } from "webpack";
import type { RuntimeCaching } from "workbox-build";
import WorkboxPlugin from "workbox-webpack-plugin";

import { buildCustomWorker } from "./build-custom-worker.js";
import { getDefaultDocumentPage } from "./build-fallback-worker/get-default-document-page.js";
import { buildFallbackWorker } from "./build-fallback-worker/index.js";
import defaultCache from "./cache.js";
import type { SharedWorkboxOptionsKeys } from "./private-types.js";
import { resolveRuntimeCaching } from "./resolve-runtime-caching.js";
import { resolveWorkboxCommon } from "./resolve-workbox-common.js";
import type { PluginOptions } from "./types.js";
import { isInjectManifestConfig, overrideAfterCalledMethod } from "./utils.js";

Expand All @@ -25,16 +25,16 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url));
const getRevision = (file: fs.PathOrFileDescriptor) =>
crypto.createHash("md5").update(fs.readFileSync(file)).digest("hex");

const withPWAInit = (
pluginOptions: PluginOptions = {}
): ((_?: NextConfig) => NextConfig) => {
type WithPWA = (_?: NextConfig) => NextConfig;

const withPWAInit = (pluginOptions: PluginOptions = {}): WithPWA => {
return (nextConfig = {}) => ({
...nextConfig,
...({
webpack(config: Configuration, options) {
const isAppDirEnabled = !!nextConfig.experimental?.appDir;

const webpack: typeof webpackType = options.webpack;
const webpack: typeof WebpackType = options.webpack;
const {
buildId,
dev,
Expand Down Expand Up @@ -288,65 +288,17 @@ const withPWAInit = (
}
}

const workboxCommon: Pick<
GenerateSWConfig,
SharedWorkboxOptionsKeys
> = {
swDest: path.join(_dest, sw),
additionalManifestEntries: dev ? [] : manifestEntries,
exclude: [
...buildExcludes,
({ asset }: { asset: Asset }) => {
if (
asset.name.startsWith("server/") ||
asset.name.match(
/^((app-|^)build-manifest\.json|react-loadable-manifest\.json)$/
)
) {
return true;
}
if (dev && !asset.name.startsWith("static/runtime/")) {
return true;
}
return false;
},
],
modifyURLPrefix: {
...modifyURLPrefix,
"/_next/../public/": "/",
},
manifestTransforms: [
...manifestTransforms,
async (manifestEntries, compilation) => {
const manifest = manifestEntries.map((m) => {
m.url = m.url.replace(
"/_next//static/image",
"/_next/static/image"
);
m.url = m.url.replace(
"/_next//static/media",
"/_next/static/media"
);
if (m.revision === null) {
let key = m.url;
if (
config.output &&
config.output.publicPath &&
typeof config.output.publicPath === "string" &&
key.startsWith(config.output.publicPath)
) {
key = m.url.substring(config.output.publicPath.length);
}
const asset = (compilation as any).assetsInfo.get(key);
m.revision = asset ? asset.contenthash || buildId : buildId;
}
m.url = m.url.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
return m;
});
return { manifest, warnings: [] };
},
],
};
const workboxCommon = resolveWorkboxCommon({
dest: _dest,
sw,
dev,
buildId,
buildExcludes,
manifestEntries,
manifestTransforms,
modifyURLPrefix,
publicPath: config.output?.publicPath,
});

if (isInjectManifestConfig(workboxOptions)) {
const swSrc = path.join(options.dir, workboxOptions.swSrc);
Expand All @@ -370,18 +322,15 @@ const withPWAInit = (
runtimeCaching: userSpecifiedRuntimeCaching,
} = workboxOptions;

let runtimeCaching = resolveRuntimeCaching(
userSpecifiedRuntimeCaching,
extendDefaultRuntimeCaching
);
let runtimeCaching: RuntimeCaching[];

if (userSpecifiedImportScripts) {
for (const script of userSpecifiedImportScripts) {
importScripts.push(script);
}
}

let shutWorkboxAfterCalledMessageUp = false;
let shutWorkboxAfterCalledUp = false;

if (dev) {
logger.info(
Expand All @@ -397,7 +346,12 @@ const withPWAInit = (
},
},
];
shutWorkboxAfterCalledMessageUp = true;
shutWorkboxAfterCalledUp = true;
} else {
runtimeCaching = resolveRuntimeCaching(
userSpecifiedRuntimeCaching,
extendDefaultRuntimeCaching
);
}

if (dynamicStartUrl) {
Expand Down Expand Up @@ -460,7 +414,7 @@ const withPWAInit = (
runtimeCaching,
});

if (shutWorkboxAfterCalledMessageUp) {
if (shutWorkboxAfterCalledUp) {
overrideAfterCalledMethod(workboxPlugin);
}

Expand Down
79 changes: 79 additions & 0 deletions packages/next-pwa/src/resolve-workbox-common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import path from "node:path";

import type { Asset, Configuration } from "webpack";
import type { ManifestEntry, ManifestTransform } from "workbox-build";
import type { GenerateSWConfig } from "workbox-webpack-plugin";

import type { SharedWorkboxOptionsKeys } from "./private-types.js";
import type { PluginOptions } from "./types.js";

interface ResolveWorkboxCommonOptions {
dest: string;
sw: string;
dev: boolean;
buildId: string;
buildExcludes: NonNullable<PluginOptions["buildExcludes"]>;
manifestEntries: (string | ManifestEntry)[];
manifestTransforms: ManifestTransform[];
modifyURLPrefix: Record<string, string>;
publicPath: NonNullable<Configuration["output"]>["publicPath"];
}

export const resolveWorkboxCommon = ({
dest,
sw,
dev,
buildId,
buildExcludes,
manifestEntries,
manifestTransforms,
modifyURLPrefix,
publicPath,
}: ResolveWorkboxCommonOptions): Pick<
GenerateSWConfig,
SharedWorkboxOptionsKeys
> => ({
swDest: path.join(dest, sw),
additionalManifestEntries: dev ? [] : manifestEntries,
exclude: [
...buildExcludes,
({ asset }: { asset: Asset }) => {
if (
asset.name.startsWith("server/") ||
asset.name.match(
/^((app-|^)build-manifest\.json|react-loadable-manifest\.json)$/
)
) {
return true;
}
if (dev && !asset.name.startsWith("static/runtime/")) {
return true;
}
return false;
},
],
modifyURLPrefix: {
...modifyURLPrefix,
"/_next/../public/": "/",
},
manifestTransforms: [
...manifestTransforms,
async (manifestEntries, compilation) => {
const manifest = manifestEntries.map((m) => {
m.url = m.url.replace("/_next//static/image", "/_next/static/image");
m.url = m.url.replace("/_next//static/media", "/_next/static/media");
if (m.revision === null) {
let key = m.url;
if (typeof publicPath === "string" && key.startsWith(publicPath)) {
key = m.url.substring(publicPath.length);
}
const asset = (compilation as any).assetsInfo.get(key);
m.revision = asset ? asset.contenthash || buildId : buildId;
}
m.url = m.url.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
return m;
});
return { manifest, warnings: [] };
},
],
});
Loading

0 comments on commit 9045662

Please sign in to comment.