Skip to content

Commit a0e5d1b

Browse files
authored
chore(deps): upgrade vite-plus to 0.2.6 (#2694)
* chore(deps): upgrade vite-plus to 0.2.6 * fix(app-router): suppress benign AbortError from superseded navigations A fast follow-up navigation aborts the in-flight navigation's RSC fetch mid-stream. When the aborted stream still holds an un-consumed React Flight chunk (e.g. streamed metadata the superseded route never rendered), React reports the resulting AbortError globally as a window `error` event rather than to a specific consumer, which trips the "no console errors" e2e assertion (metadata-icons.spec.ts). Install a page-lifetime window listener at bootstrap that preventDefault()s these benign navigation AbortErrors, mirroring the existing redirect-error bridge. Installed once (not in a component effect) so there is no listener gap while the router tree re-renders mid-navigation. The vite-plus 0.2.6 toolchain shifted navigation timing enough to expose this latent race on CI. * chore: adapt to vite-plus 0.2.6 toolchain Follow-up to the vite-plus 0.2.6 bump; keeps CI green under the new oxfmt/oxlint/rolldown toolchain. No published runtime change. - Formatting: oxfmt 0.60.0 reformats README.md, apps/web/next.config.ts and tests/nextjs-compat/TRACKING.md (collapses empty-object-with-comment; unpads markdown tables). Applied `vp check --fix`. - Lint: oxlint 1.75.0 now flags dynamic `import("node:path")` under the existing no-restricted-imports rule. Disabled inline in loadStaticPrerender with a reason -- the resolved path feeds a dynamic import(), so pathslash's forward-slash canonicalization buys nothing there. - Test: rolldown code-splits the server build, so the font markers moved out of index.js into _next/static/* chunks. Scan the whole server output for the markers instead of index.js alone (verified they still exist). * Revert "fix(app-router): suppress benign AbortError from superseded navigations" Drop the runtime AbortError suppressor to keep this PR a pure toolchain bump. The metadata-icons "rapid icon replacement" failure it addressed is a pre-existing, timing-dependent race (not caused by the upgrade). Assessing whether it triggers stably on CI / locally before deciding how and where to fix it. This reverts commit 84454d5fd of this branch.
1 parent 795855e commit a0e5d1b

7 files changed

Lines changed: 910 additions & 589 deletions

File tree

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,7 @@ vinext({
638638
cache: {
639639
data: {
640640
adapter: require.resolve("./my-adapter.js"),
641-
options: {
642-
/**/
643-
},
641+
options: {/**/},
644642
},
645643
},
646644
});

apps/web/next.config.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import type { NextConfig } from "next";
22

3-
const nextConfig: NextConfig = {
4-
/* config options here */
5-
};
3+
const nextConfig: NextConfig = {/* config options here */};
64

75
export default nextConfig;

packages/vinext/src/server/app-ssr-entry.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ async function loadStaticPrerender(): Promise<StaticPrerender> {
127127
try {
128128
const [{ createRequire }, path] = await Promise.all([
129129
import("node:module"),
130+
// Native node:path is fine here: the resolved path is fed straight into
131+
// a dynamic import() and never compared against pathslash-normalized
132+
// ids, so forward-slash canonicalization buys nothing.
133+
// oxlint-disable-next-line no-restricted-imports
130134
import("node:path"),
131135
]);
132136
const require = createRequire(import.meta.url);

pnpm-lock.yaml

Lines changed: 843 additions & 539 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ catalog:
8787
typescript: ^7.0.0
8888
use-count-up: 3.0.1
8989
validator: ^13.15.26
90-
vite: npm:@voidzero-dev/vite-plus-core@0.2.2
90+
vite: npm:@voidzero-dev/vite-plus-core@0.2.6
9191
vite-plugin-commonjs: ^0.10.4
92-
vite-plus: 0.2.2
92+
vite-plus: 0.2.6
9393
vitest: 4.1.9
9494
web-vitals: ^4.2.4
9595
wrangler: ^4.80.0

tests/font-google-build.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ async function buildFontGoogleMultipleFixture(): Promise<string> {
6868
}
6969
}
7070

71+
// Concatenate every emitted `.js` file under `dir`. The server build is
72+
// code-split across `_next/static/*` chunks, so the transformed font output is
73+
// no longer guaranteed to live in `index.js` alone — the markers can land in
74+
// any chunk (e.g. the layout/page chunks).
75+
async function readAllJs(dir: string): Promise<string> {
76+
const entries = await fs.readdir(dir, { withFileTypes: true });
77+
const parts = await Promise.all(
78+
entries.map(async (entry) => {
79+
const full = path.join(dir, entry.name);
80+
if (entry.isDirectory()) return readAllJs(full);
81+
if (entry.name.endsWith(".js")) return fs.readFile(full, "utf-8");
82+
return "";
83+
}),
84+
);
85+
return parts.join("\n");
86+
}
87+
7188
describe("font-google build integration", () => {
7289
let buildOutputPath: string;
7390
let outDir: string;
@@ -82,7 +99,7 @@ describe("font-google build integration", () => {
8299
buildOutputPath = await buildFontGoogleMultipleFixture();
83100
outDir = path.dirname(path.dirname(buildOutputPath));
84101

85-
const content = await fs.readFile(buildOutputPath, "utf-8");
102+
const content = await readAllJs(path.dirname(buildOutputPath));
86103
expect(content).toContain("Geist");
87104
expect(content).toContain("_vinext");
88105
expect(content).toContain("selfHostedCSS");

tests/nextjs-compat/TRACKING.md

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -187,39 +187,39 @@ Ported from: https://github.com/vercel/next.js/tree/canary/test/e2e/app-dir
187187
**Local**: `tests/nextjs-compat/metadata.test.ts`
188188
**Fixtures**: `fixtures/app-basic/app/nextjs-compat/metadata-*`
189189

190-
| # | Next.js Test | Vinext Status | Notes |
190+
| # | Next.js Test | Vinext Status | Notes |
191191
| ----- | ------------------------------------------ | ------------- | -------------------------------------------------------------------- | ----------------------------------- |
192-
| 1 | Title in head | PASS | `<title>this is the page title</title>` |
193-
| 2 | Description meta tag | PASS | |
194-
| 3 | Title template from layout | PASS | `"%s | Layout"` template applied correctly |
195-
| 4 | Title template to child page | PASS | `"Extra Page | Layout"` |
196-
| 5 | Generator meta tag | PASS | |
197-
| 6 | Application-name meta tag | PASS | |
198-
| 7 | Referrer meta tag | PASS | |
199-
| 8 | Keywords meta tag | PASS | Joins with ", " (space after comma) vs Next.js "," — both valid |
200-
| 9 | Author meta tags | PASS | Multiple author tags rendered |
201-
| 10 | Creator meta tag | PASS | |
202-
| 11 | Publisher meta tag | PASS | |
203-
| 12 | Robots meta tag | PASS | |
204-
| 13 | Format-detection meta tag | PASS | |
205-
| 14 | og:title | PASS | |
206-
| 15 | og:description | PASS | |
207-
| 16 | og:url | PASS | |
208-
| 17 | og:site_name | PASS | |
209-
| 18 | og:type | PASS | |
210-
| 19 | og:image | PASS | |
211-
| 20 | og:image:width/height | PASS | |
212-
| 21 | twitter:card | PASS | |
213-
| 22 | twitter:title | PASS | |
214-
| 23 | twitter:description | PASS | |
215-
| 24 | twitter:image | PASS | |
216-
| 25 | Complex robots (noindex, googlebot) | PASS | |
217-
| 26 | Googlebot meta tag | PASS | |
218-
| 27 | Canonical link | PASS | |
219-
| 28 | Hreflang alternate links | PASS | React renders as `hrefLang` (camelCase) |
220-
| 29 | generateMetadata with params (title) | PASS | Dynamic slug resolved |
221-
| 30 | generateMetadata with params (description) | PASS | |
222-
| 31-45 | Various N/A tests | N/A (x15) | Browser-only (client nav), file-based images, HMR, cache dedup, etc. |
192+
| 1 | Title in head | PASS | `<title>this is the page title</title>` |
193+
| 2 | Description meta tag | PASS | |
194+
| 3 | Title template from layout | PASS | `"%s | Layout"` template applied correctly |
195+
| 4 | Title template to child page | PASS | `"Extra Page | Layout"` |
196+
| 5 | Generator meta tag | PASS | |
197+
| 6 | Application-name meta tag | PASS | |
198+
| 7 | Referrer meta tag | PASS | |
199+
| 8 | Keywords meta tag | PASS | Joins with ", " (space after comma) vs Next.js "," — both valid |
200+
| 9 | Author meta tags | PASS | Multiple author tags rendered |
201+
| 10 | Creator meta tag | PASS | |
202+
| 11 | Publisher meta tag | PASS | |
203+
| 12 | Robots meta tag | PASS | |
204+
| 13 | Format-detection meta tag | PASS | |
205+
| 14 | og:title | PASS | |
206+
| 15 | og:description | PASS | |
207+
| 16 | og:url | PASS | |
208+
| 17 | og:site_name | PASS | |
209+
| 18 | og:type | PASS | |
210+
| 19 | og:image | PASS | |
211+
| 20 | og:image:width/height | PASS | |
212+
| 21 | twitter:card | PASS | |
213+
| 22 | twitter:title | PASS | |
214+
| 23 | twitter:description | PASS | |
215+
| 24 | twitter:image | PASS | |
216+
| 25 | Complex robots (noindex, googlebot) | PASS | |
217+
| 26 | Googlebot meta tag | PASS | |
218+
| 27 | Canonical link | PASS | |
219+
| 28 | Hreflang alternate links | PASS | React renders as `hrefLang` (camelCase) |
220+
| 29 | generateMetadata with params (title) | PASS | Dynamic slug resolved |
221+
| 30 | generateMetadata with params (description) | PASS | |
222+
| 31-45 | Various N/A tests | N/A (x15) | Browser-only (client nav), file-based images, HMR, cache dedup, etc. |
223223

224224
**Result: 30/30 pass, 0 skip, 15 N/A (browser-only, file-based images, HMR)**
225225

@@ -318,16 +318,16 @@ Three Playwright spec files cover client-side behaviors that cannot be tested vi
318318

319319
**Local**: `tests/e2e/app-router/nextjs-compat/metadata.spec.ts`
320320

321-
| # | Test | Status | Notes |
321+
| # | Test | Status | Notes |
322322
| --- | -------------------------------------------------------- | ------ | --------------------------------------------------- | -------------------------- |
323-
| 1 | document.title matches metadata export | PASS | `toHaveTitle("this is the page title")` |
324-
| 2 | description meta tag is present in DOM | PASS | `meta[name="description"]` queried in browser |
325-
| 3 | title template applies correctly | PASS | `"Page | Layout"` in document.title |
326-
| 4 | title template applies to child page | PASS | `"Extra Page | Layout"` |
327-
| 5 | OpenGraph meta tags present in DOM | PASS | og:title, og:description, og:type verified |
328-
| 6 | Twitter card meta tags present in DOM | PASS | twitter:card, twitter:title verified |
329-
| 7 | generateMetadata renders correct title for dynamic route | PASS | `"params - my-slug"` |
330-
| 8 | title updates on client-side navigation | PASS | Link click -> document.title updates without reload |
323+
| 1 | document.title matches metadata export | PASS | `toHaveTitle("this is the page title")` |
324+
| 2 | description meta tag is present in DOM | PASS | `meta[name="description"]` queried in browser |
325+
| 3 | title template applies correctly | PASS | `"Page | Layout"` in document.title |
326+
| 4 | title template applies to child page | PASS | `"Extra Page | Layout"` |
327+
| 5 | OpenGraph meta tags present in DOM | PASS | og:title, og:description, og:type verified |
328+
| 6 | Twitter card meta tags present in DOM | PASS | twitter:card, twitter:title verified |
329+
| 7 | generateMetadata renders correct title for dynamic route | PASS | `"params - my-slug"` |
330+
| 8 | title updates on client-side navigation | PASS | Link click -> document.title updates without reload |
331331

332332
**Result: 8/8 pass, 0 skip**
333333

0 commit comments

Comments
 (0)