Skip to content

Commit

Permalink
fix(core): fixed invalid precache manifest and scope with basePath
Browse files Browse the repository at this point in the history
[bump]
  • Loading branch information
DuCanhGH committed Jan 29, 2024
1 parent e4c8af7 commit e5f1d14
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 9 deletions.
9 changes: 9 additions & 0 deletions .changeset/thick-pans-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@ducanh2912/next-pwa": patch
---

fix(core): fixed invalid precache manifest and scope with `basePath`

- A fast backport of https://github.com/serwist/serwist/pull/56.
- This is caused by "/\_next/../public" in modifyURLPrefix not being matched when basePath is set, since the URL is actually "${basePath}/\_next/../public/\*\*/\*". We now use `manifestTransforms` instead of `modifyURLPrefix`.
- Also, with the refactor to using a context, we mistakenly changed `scope` from "${scope}" (suffixed with / if originally not) to "${basePath}/${scope}". This reverts that change. Sorry for the inconvenience!
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const RootLayout = ({ children }: { children: React.ReactNode }) => (
<html lang="en">
<head />
<body>{children}</body>
</html>
);

export default RootLayout;
10 changes: 10 additions & 0 deletions packages/next-pwa/__tests__/integration/base-path/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Image from "next/image";

const Page = () => (
<main>
<p id="welcome-text">This is a Next.js PWA!</p>
<Image src="/next.svg" alt="Next.js Logo" width={180} height={37} priority />
</main>
);

export default Page;
26 changes: 26 additions & 0 deletions packages/next-pwa/__tests__/integration/base-path/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createDescribe } from "../../test-utils/index.ts";

createDescribe("integration basePath", { sourceDir: __dirname, skipInstall: false }, ({ next, testMode }) => {
it("should render", async () => {
const $ = await next.render("/next-pwa");
expect($("#welcome-text").text()).toBe("This is a Next.js PWA!");
});

it("should fetch image", async () => {
const image = await next.fetch("/next-pwa/next.svg");
expect(image.status).toBe(200);
const favicon = await next.fetch("/next-pwa/favicon.ico");
expect(favicon.status).toBe(200);
});

it("should be able to fetch service worker", async () => {
const sw = await next.fetch("/next-pwa/sw.js");
expect(sw.status).toBe(200);
expect(sw.headers.get("Content-Type")?.includes("application/javascript")).toBe(true);
const swContent = await sw.text();
if (testMode === "start") {
expect(/url:\"\/next-pwa\/swe-worker-(.*?).js\"/.test(swContent)).toBe(true);
expect(/url:\"\/next-pwa\/_next\/..\/public\/swe-worker-(.*?).js\"/.test(swContent)).toBe(false);
}
});
});
14 changes: 14 additions & 0 deletions packages/next-pwa/__tests__/integration/base-path/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @ts-check
import withPWAInit from "@ducanh2912/next-pwa";

const withPWA = withPWAInit({
dest: "public",
cacheOnFrontEndNav: true,
});

/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: "/next-pwa",
};

export default withPWA(nextConfig);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions packages/next-pwa/__tests__/integration/base-path/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
17 changes: 8 additions & 9 deletions packages/next-pwa/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url));

export interface PluginOptionsComplete extends Required<PluginOptions> {
disable: false;
workboxOptions: RequireFields<WorkboxOptions, "swDest" | "additionalManifestEntries" | "exclude" | "modifyURLPrefix" | "manifestTransforms">;
workboxOptions: RequireFields<WorkboxOptions, "swDest" | "additionalManifestEntries" | "exclude" | "manifestTransforms">;
}

type PublicPath = NonNullable<NonNullable<WebpackConfig["output"]>["publicPath"]>;
Expand Down Expand Up @@ -59,7 +59,6 @@ export const parseOptions = (
customWorkerPrefix = "worker",
workboxOptions: {
additionalManifestEntries,
modifyURLPrefix: _modifyURLPrefix = {},
manifestTransforms: _manifestTransforms = [],
exclude: _exclude = [/\/_next\/static\/.*(?<!\.p)\.woff2/, /\.map$/, /^manifest.*\.js$/],
...workbox
Expand All @@ -81,6 +80,8 @@ export const parseOptions = (
"!worker-*.js.map",
"!fallback-*.js",
"!fallback-*.js.map",
"!swe-worker-*.js",
"!swe-worker-*.js.map",
`!${sw.replace(/^\/+/, "")}`,
`!${sw.replace(/^\/+/, "")}.map`,
...publicExcludes,
Expand Down Expand Up @@ -135,7 +136,7 @@ export const parseOptions = (
cacheOnFrontEndNav,
aggressiveFrontEndNavCaching,
reloadOnOnline,
scope: path.posix.join(nextConfig.basePath, scope),
scope: path.posix.join(scope, "/"),
customWorkerSrc,
customWorkerDest: path.resolve(webpackContext.dir, customWorkerDest),
customWorkerPrefix,
Expand All @@ -155,16 +156,14 @@ export const parseOptions = (
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");
m.url = m.url
.replace("/_next//static/image", "/_next/static/image")
.replace("/_next//static/media", "/_next/static/media")
.replace("/_next/../public", "");
if (m.revision === null) {
let key = m.url;
if (typeof publicPath === "string" && key.startsWith(publicPath)) {
Expand Down

0 comments on commit e5f1d14

Please sign in to comment.