vinext 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -10
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +8 -81
- package/dist/build/prerender.js +33 -8
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +81 -82
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +14 -0
- package/dist/config/next-config.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +6 -0
- package/dist/entries/app-rsc-entry.js +84 -49
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +7 -2
- package/dist/index.js +193 -73
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +19 -8
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +19 -3
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +6 -1
- package/dist/server/app-page-cache.js +28 -8
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +51 -33
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +3 -3
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +54 -17
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +57 -35
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +7 -3
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +6 -3
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +27 -8
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +11 -0
- package/dist/server/app-rsc-handler.js +291 -125
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +10 -6
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +8 -5
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +7 -2
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/cacheability-request.js +11 -7
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +50 -29
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +18 -1
- package/dist/server/headers.js +19 -2
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +54 -0
- package/dist/server/image-optimization.js +118 -9
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +43 -8
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +19 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +209 -130
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +79 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +20 -7
- package/dist/server/prod-server.js +343 -129
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +24 -9
- package/dist/server/request-pipeline.js +24 -9
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +15 -11
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +23 -1
- package/dist/server/socket-error-backstop.js +69 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +6 -42
- package/dist/shims/cache-callable-runtime.js +65 -174
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +12 -20
- package/dist/shims/cache-runtime.js +166 -225
- package/dist/shims/cache.d.ts +4 -4
- package/dist/shims/cache.js +44 -16
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -61
- package/dist/shims/fetch-cache.js +161 -108
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +45 -9
- package/dist/shims/request-context.d.ts +11 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +9 -5
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
|
+
import { magicStringTransformResult } from "./transform-result.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import MagicString from "magic-string";
|
|
5
|
+
//#region src/plugins/cache-flight-codec.ts
|
|
6
|
+
const CLIENT_CODEC = /\/react-server-dom-(?:webpack|turbopack)-client\.edge\.(?:development|production)\.js$/;
|
|
7
|
+
const ELEMENT_CASE = /case REACT_ELEMENT_TYPE:[\s\S]*?throw Error\(\s*"React Element cannot be passed/;
|
|
8
|
+
/**
|
|
9
|
+
* Version of the Flight codec package that owns `id`. plugin-rsc resolves the
|
|
10
|
+
* app's own react-server-dom-webpack when installed and its vendored copy
|
|
11
|
+
* otherwise; reading the codec file's own package.json follows that choice.
|
|
12
|
+
*/
|
|
13
|
+
function readFlightCodecVersion(id) {
|
|
14
|
+
for (let dir = path.dirname(id);; dir = path.dirname(dir)) {
|
|
15
|
+
const manifest = path.join(dir, "package.json");
|
|
16
|
+
if (fs.existsSync(manifest)) {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(manifest, "utf8"));
|
|
18
|
+
if (/^react-server-dom-(?:webpack|turbopack)$/.test(pkg.name ?? "") && pkg.version) return pkg.version;
|
|
19
|
+
}
|
|
20
|
+
if (path.dirname(dir) === dir) throw new Error(`vinext: cannot find the react-server-dom package version for ${id}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** React 19.3 ships the branch; 0.0.0-* experimental builds track main. */
|
|
24
|
+
function needsElementTemporaryReferenceBackport(version) {
|
|
25
|
+
const match = /^(\d+)\.(\d+)\./.exec(version);
|
|
26
|
+
if (!match || version.startsWith("0.0.0-")) return false;
|
|
27
|
+
const [major, minor] = [Number(match[1]), Number(match[2])];
|
|
28
|
+
return major < 19 || major === 19 && minor < 3;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Backport React 19.3's root-element temporary reference branch to older Flight
|
|
32
|
+
* codecs, so a "use cache" argument like `Promise<ReactElement>` encodes as a
|
|
33
|
+
* temporary reference instead of throwing. Remove it once React 19.3 is the
|
|
34
|
+
* minimum supported version.
|
|
35
|
+
* https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
|
|
36
|
+
*/
|
|
37
|
+
function patchCacheFlightCodec(code, id, version = readFlightCodecVersion(id)) {
|
|
38
|
+
if (!needsElementTemporaryReferenceBackport(version)) return null;
|
|
39
|
+
const elementCase = ELEMENT_CASE.exec(code);
|
|
40
|
+
if (!elementCase) throw new Error(`vinext: react-server-dom-webpack ${version} (${id}) is not supported. Upgrade react, react-dom, and react-server-dom-webpack to 19.3 or later. If your app does not depend on react-server-dom-webpack directly, upgrade @vitejs/plugin-rsc to 0.5.35 or later instead.`);
|
|
41
|
+
const output = new MagicString(code);
|
|
42
|
+
output.appendLeft(elementCase.index + elementCase[0].lastIndexOf("throw Error("), "if (void 0 !== temporaryReferences && modelRoot === value) return (modelRoot = null), \"$T\";\n");
|
|
43
|
+
return magicStringTransformResult(output, {
|
|
44
|
+
hires: "boundary",
|
|
45
|
+
source: id
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function cacheFlightCodecPlugin() {
|
|
49
|
+
const transform = {
|
|
50
|
+
filter: { id: CLIENT_CODEC },
|
|
51
|
+
handler: (code, id) => patchCacheFlightCodec(code, id)
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
name: "vinext:cache-flight-codec",
|
|
55
|
+
enforce: "pre",
|
|
56
|
+
applyToEnvironment: (environment) => environment.name === "rsc",
|
|
57
|
+
configEnvironment(name) {
|
|
58
|
+
if (name !== "rsc") return;
|
|
59
|
+
return { optimizeDeps: { rolldownOptions: { plugins: [{
|
|
60
|
+
name: "vinext:cache-flight-codec-optimizer",
|
|
61
|
+
transform
|
|
62
|
+
}] } } };
|
|
63
|
+
},
|
|
64
|
+
transform
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { cacheFlightCodecPlugin, patchCacheFlightCodec, readFlightCodecVersion };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
//#region src/plugins/commonjs-esm-facade.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Removes the export facade vite-plugin-commonjs appended to `output` when the
|
|
5
|
+
* module it transformed is ESM. Returns `undefined` when there is nothing to
|
|
6
|
+
* remove.
|
|
7
|
+
*
|
|
8
|
+
* Next.js treats a module with ESM syntax as ESM: `require()` still works, but
|
|
9
|
+
* `module` / `exports` never become its exports. The plugin's analyzer is not
|
|
10
|
+
* scope-aware, so for bundled ESM that inlines CommonJS wrappers
|
|
11
|
+
* (`__commonJS((exports, module) => …)`) it exports the wrappers' assignments
|
|
12
|
+
* too, which duplicates the module's own exports. Its `require()` rewrite and
|
|
13
|
+
* its local `module` / `exports` polyfill stay, so free CommonJS assignments
|
|
14
|
+
* still run without becoming exports.
|
|
15
|
+
*
|
|
16
|
+
* Besides the facade, the plugin only prepends imports and its polyfill and
|
|
17
|
+
* rewrites `require()` calls, so the module's own top-level exports are still
|
|
18
|
+
* in `output`. Classifying the output rather than rereading the source keeps
|
|
19
|
+
* the decision tied to the exact code the plugin transformed.
|
|
20
|
+
*
|
|
21
|
+
* The facade is appended after the module's code (only dynamic-require
|
|
22
|
+
* runtimes, which have no source mappings, may follow it), so removing it
|
|
23
|
+
* leaves the plugin's source map valid.
|
|
24
|
+
*/
|
|
25
|
+
export declare function stripEsmCommonJsExportFacade(output: string): string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Applies {@link stripEsmCommonJsExportFacade} in the client dependency
|
|
28
|
+
* optimizer's Rolldown builds (scan and pre-bundle). vite-plugin-commonjs's
|
|
29
|
+
* pre-bundle plugin loads and converts files there without vinext's transform
|
|
30
|
+
* wrapper, so its output reaches this hook as the loaded code. That code is
|
|
31
|
+
* the optimizer's source, so the removal needs its own map for anything the
|
|
32
|
+
* plugin appended after the facade.
|
|
33
|
+
*/
|
|
34
|
+
export declare const commonJsEsmFacadeOptimizeDepsPlugin: Plugin;
|
|
35
|
+
//#endregion
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { parseAst } from "vite";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
//#region src/plugins/commonjs-esm-facade.ts
|
|
4
|
+
const EXPORT_FACADE_START = "/* [vite-plugin-commonjs] export-statement-S */";
|
|
5
|
+
const EXPORT_FACADE_END = "/* [vite-plugin-commonjs] export-statement-E */";
|
|
6
|
+
const EXPORT_KEYWORD_RE = /\bexport\b(?!-)/;
|
|
7
|
+
/** Whether `code` has a top-level ESM export statement. */
|
|
8
|
+
function hasEsmExports(code) {
|
|
9
|
+
if (!EXPORT_KEYWORD_RE.test(code)) return false;
|
|
10
|
+
let ast;
|
|
11
|
+
try {
|
|
12
|
+
ast = parseAst(code);
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return ast.body.some((statement) => statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration" || statement.type === "ExportAllDeclaration");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Removes the export facade vite-plugin-commonjs appended to `output` when the
|
|
20
|
+
* module it transformed is ESM. Returns `undefined` when there is nothing to
|
|
21
|
+
* remove.
|
|
22
|
+
*
|
|
23
|
+
* Next.js treats a module with ESM syntax as ESM: `require()` still works, but
|
|
24
|
+
* `module` / `exports` never become its exports. The plugin's analyzer is not
|
|
25
|
+
* scope-aware, so for bundled ESM that inlines CommonJS wrappers
|
|
26
|
+
* (`__commonJS((exports, module) => …)`) it exports the wrappers' assignments
|
|
27
|
+
* too, which duplicates the module's own exports. Its `require()` rewrite and
|
|
28
|
+
* its local `module` / `exports` polyfill stay, so free CommonJS assignments
|
|
29
|
+
* still run without becoming exports.
|
|
30
|
+
*
|
|
31
|
+
* Besides the facade, the plugin only prepends imports and its polyfill and
|
|
32
|
+
* rewrites `require()` calls, so the module's own top-level exports are still
|
|
33
|
+
* in `output`. Classifying the output rather than rereading the source keeps
|
|
34
|
+
* the decision tied to the exact code the plugin transformed.
|
|
35
|
+
*
|
|
36
|
+
* The facade is appended after the module's code (only dynamic-require
|
|
37
|
+
* runtimes, which have no source mappings, may follow it), so removing it
|
|
38
|
+
* leaves the plugin's source map valid.
|
|
39
|
+
*/
|
|
40
|
+
function stripEsmCommonJsExportFacade(output) {
|
|
41
|
+
const facade = findEsmCommonJsExportFacade(output);
|
|
42
|
+
return facade && output.slice(0, facade[0]) + output.slice(facade[1]);
|
|
43
|
+
}
|
|
44
|
+
/** The `[start, end)` range of the facade {@link stripEsmCommonJsExportFacade} removes. */
|
|
45
|
+
function findEsmCommonJsExportFacade(output) {
|
|
46
|
+
const start = output.lastIndexOf(EXPORT_FACADE_START);
|
|
47
|
+
if (start === -1) return void 0;
|
|
48
|
+
const end = output.indexOf(EXPORT_FACADE_END, start);
|
|
49
|
+
if (end === -1) return void 0;
|
|
50
|
+
const facadeEnd = end + 47;
|
|
51
|
+
return hasEsmExports(output.slice(0, start) + output.slice(facadeEnd)) ? [start, facadeEnd] : void 0;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Applies {@link stripEsmCommonJsExportFacade} in the client dependency
|
|
55
|
+
* optimizer's Rolldown builds (scan and pre-bundle). vite-plugin-commonjs's
|
|
56
|
+
* pre-bundle plugin loads and converts files there without vinext's transform
|
|
57
|
+
* wrapper, so its output reaches this hook as the loaded code. That code is
|
|
58
|
+
* the optimizer's source, so the removal needs its own map for anything the
|
|
59
|
+
* plugin appended after the facade.
|
|
60
|
+
*/
|
|
61
|
+
const commonJsEsmFacadeOptimizeDepsPlugin = {
|
|
62
|
+
name: "vinext:commonjs-esm-facade:optimize-deps",
|
|
63
|
+
transform: {
|
|
64
|
+
filter: { code: { include: EXPORT_FACADE_START } },
|
|
65
|
+
handler(code, id) {
|
|
66
|
+
const facade = findEsmCommonJsExportFacade(code);
|
|
67
|
+
if (!facade) return null;
|
|
68
|
+
const output = new MagicString(code).remove(facade[0], facade[1]);
|
|
69
|
+
return {
|
|
70
|
+
code: output.toString(),
|
|
71
|
+
map: output.generateMap({
|
|
72
|
+
source: id,
|
|
73
|
+
hires: "boundary"
|
|
74
|
+
})
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { commonJsEsmFacadeOptimizeDepsPlugin, stripEsmCommonJsExportFacade };
|
|
@@ -7,5 +7,5 @@ type TransformResult = {
|
|
|
7
7
|
};
|
|
8
8
|
type ResolveDynamicImport = (specifier: string, importer: string) => Promise<string | null>;
|
|
9
9
|
export declare function transformNextDynamicPreloadMetadata(code: string, id: string, root: string, resolveDynamicImport: ResolveDynamicImport): Promise<TransformResult | null>;
|
|
10
|
-
export declare function createDynamicPreloadMetadataPlugin(): Plugin;
|
|
10
|
+
export declare function createDynamicPreloadMetadataPlugin(getTranspiledPackages: () => readonly string[]): Plugin;
|
|
11
11
|
//#endregion
|
|
@@ -3,7 +3,8 @@ import { collectBindingNames, forEachAstChild, stringLiteralValue, walkAst } fro
|
|
|
3
3
|
import { hasTrailingComma } from "../utils/has-trailing-comma.js";
|
|
4
4
|
import { magicStringTransformResult } from "./transform-result.js";
|
|
5
5
|
import { stripViteModuleQuery } from "../utils/path.js";
|
|
6
|
-
import {
|
|
6
|
+
import { isForeignNodeModule } from "../utils/package-name.js";
|
|
7
|
+
import { relativeToRoot, relativeWithinRoot, tryRealpathSync } from "../build/ssr-manifest.js";
|
|
7
8
|
import { parseAst } from "vite";
|
|
8
9
|
import MagicString from "magic-string";
|
|
9
10
|
//#region src/plugins/dynamic-preload-metadata.ts
|
|
@@ -204,7 +205,7 @@ function toManifestModuleId(root, resolvedId) {
|
|
|
204
205
|
const relative = relativeWithinRoot(rootCandidate, moduleCandidate);
|
|
205
206
|
if (relative) return relative;
|
|
206
207
|
}
|
|
207
|
-
return null;
|
|
208
|
+
return relativeToRoot(root, cleaned) || null;
|
|
208
209
|
}
|
|
209
210
|
async function resolveManifestModuleIds(specifiers, importer, root, resolveDynamicImport) {
|
|
210
211
|
const resolvedIds = [];
|
|
@@ -262,24 +263,24 @@ async function transformNextDynamicPreloadMetadata(code, id, root, resolveDynami
|
|
|
262
263
|
if (!changed) return null;
|
|
263
264
|
return magicStringTransformResult(output);
|
|
264
265
|
}
|
|
265
|
-
function createDynamicPreloadMetadataPlugin() {
|
|
266
|
+
function createDynamicPreloadMetadataPlugin(getTranspiledPackages) {
|
|
266
267
|
let root = toSlash(process.cwd());
|
|
268
|
+
let isBuild = false;
|
|
267
269
|
return {
|
|
268
270
|
name: "vinext:dynamic-preload-metadata",
|
|
269
271
|
configResolved(config) {
|
|
270
272
|
root = config.root;
|
|
273
|
+
isBuild = config.command === "build";
|
|
271
274
|
},
|
|
272
275
|
transform: {
|
|
273
276
|
filter: {
|
|
274
|
-
id:
|
|
275
|
-
include: /\.(tsx?|jsx?|mjs)$/,
|
|
276
|
-
exclude: /node_modules/
|
|
277
|
-
},
|
|
277
|
+
id: /\.(tsx?|jsx?|mjs)$/,
|
|
278
278
|
code: "next/dynamic"
|
|
279
279
|
},
|
|
280
280
|
async handler(code, id) {
|
|
281
|
-
if (id.
|
|
281
|
+
if (id.startsWith("\0")) return null;
|
|
282
282
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return null;
|
|
283
|
+
if (id.includes("node_modules") && (!isBuild || isForeignNodeModule(id, getTranspiledPackages()))) return null;
|
|
283
284
|
const result = await transformNextDynamicPreloadMetadata(code, id, root, async (specifier, importer) => {
|
|
284
285
|
return (await this.resolve(specifier, importer, { skipSelf: true }))?.id ?? null;
|
|
285
286
|
});
|
package/dist/plugins/fonts.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { Plugin } from "vite";
|
|
|
3
3
|
export declare const VIRTUAL_GOOGLE_FONTS = "virtual:vinext-google-fonts";
|
|
4
4
|
export declare const RESOLVED_VIRTUAL_GOOGLE_FONTS: string;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Point the `@font-face { src: url(...) }` references of cached Google Fonts
|
|
7
|
+
* CSS at the served URL the plugin's `writeBundle` hook copies the font
|
|
8
|
+
* files to (and the dev middleware serves them from), by replacing
|
|
9
|
+
* `CACHED_FONT_DIR_TOKEN` with `/<assetsDir>/_vinext_fonts`.
|
|
9
10
|
*
|
|
10
11
|
* This is called once per transform, before the CSS string is embedded in
|
|
11
12
|
* the bundle as `_vinext.font.selfHostedCSS`. Every downstream consumer reads
|
|
@@ -14,9 +15,9 @@ export declare const RESOLVED_VIRTUAL_GOOGLE_FONTS: string;
|
|
|
14
15
|
* in `shims/font-google-base.ts`), and the HTTP `Link:` response header
|
|
15
16
|
* (via `buildAppPageFontLinkHeader` in `server/app-page-execution.ts`).
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
* (
|
|
19
|
-
*
|
|
18
|
+
* The token is substituted with plain split/join: it is a fixed string
|
|
19
|
+
* vinext wrote itself, so nothing about the checkout's path (spaces, quotes,
|
|
20
|
+
* parentheses, regex metacharacters, Windows separators) is parsed here.
|
|
20
21
|
*
|
|
21
22
|
* `assetsDir` must match whatever Vite has resolved for
|
|
22
23
|
* `build.assetsDir` on the client environment — otherwise the embedded
|
|
@@ -26,12 +27,8 @@ export declare const RESOLVED_VIRTUAL_GOOGLE_FONTS: string;
|
|
|
26
27
|
* passes the resolved value through from plugin state. The default is
|
|
27
28
|
* kept only so the exported helper can be driven directly from unit
|
|
28
29
|
* tests without synthesizing a full plugin context.
|
|
29
|
-
*
|
|
30
|
-
* Uses split/join rather than regex because `cacheDir` is an absolute
|
|
31
|
-
* filesystem path that may contain regex metacharacters on unusual
|
|
32
|
-
* filesystems.
|
|
33
30
|
*/
|
|
34
|
-
export declare function _rewriteCachedFontCssToServedUrls(css: string,
|
|
31
|
+
export declare function _rewriteCachedFontCssToServedUrls(css: string, assetsDir?: string): string;
|
|
35
32
|
/**
|
|
36
33
|
* Safely parse a static JS object literal string into a plain object.
|
|
37
34
|
* Uses Vite's parseAst (Rollup/acorn) so no code is ever evaluated.
|
package/dist/plugins/fonts.js
CHANGED
|
@@ -43,15 +43,15 @@ const GOOGLE_FONT_UTILITY_EXPORTS = /* @__PURE__ */ new Set([
|
|
|
43
43
|
/**
|
|
44
44
|
* Served URL prefix for self-hosted Google Font files.
|
|
45
45
|
*
|
|
46
|
-
* `fetchAndCacheFont()` downloads
|
|
46
|
+
* `fetchAndCacheFont()` downloads font files into `<root>/.vinext/fonts/`
|
|
47
47
|
* and writes an `@font-face` CSS snippet whose `src: url(...)` references
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
48
|
+
* name each file relative to that cache directory, behind
|
|
49
|
+
* `CACHED_FONT_DIR_TOKEN`. Before the CSS is embedded in the bundle as
|
|
50
|
+
* `_vinext.font.selfHostedCSS`, `_rewriteCachedFontCssToServedUrls()`
|
|
51
|
+
* replaces the token with this URL prefix, and the matching `writeBundle`
|
|
52
|
+
* hook in `createGoogleFontsPlugin` copies the font files into
|
|
53
|
+
* `<clientOutDir>/<assetsDir>/_vinext_fonts/` so the URL actually resolves
|
|
54
|
+
* against the origin at request time.
|
|
55
55
|
*
|
|
56
56
|
* The leading `_` keeps the namespace distinct from Vite's content-hashed
|
|
57
57
|
* asset names (which are emitted flat into `<assetsDir>/`) and from any
|
|
@@ -59,6 +59,25 @@ const GOOGLE_FONT_UTILITY_EXPORTS = /* @__PURE__ */ new Set([
|
|
|
59
59
|
*/
|
|
60
60
|
const VINEXT_FONT_URL_NAMESPACE = "_vinext_fonts";
|
|
61
61
|
const MAX_GOOGLE_FONTS_ERROR_BODY_LENGTH = 500;
|
|
62
|
+
/**
|
|
63
|
+
* Stands in for the font cache directory in every `url()` of a cached
|
|
64
|
+
* stylesheet, so the file on disk holds no absolute path and reads the same
|
|
65
|
+
* wherever the checkout's `.vinext/` ends up: a moved or copied project, a
|
|
66
|
+
* CI cache restored into another workspace, or a Docker build that copies
|
|
67
|
+
* in a host's `.vinext/`. Next.js has no such cache (its Google font loader
|
|
68
|
+
* keeps fetched CSS in memory and emits `/_next/static/media` URLs), so the
|
|
69
|
+
* parity target is output that does not depend on where the cache was
|
|
70
|
+
* written.
|
|
71
|
+
*/
|
|
72
|
+
const CACHED_FONT_DIR_TOKEN = "__VINEXT_FONT_CACHE_DIR__";
|
|
73
|
+
/**
|
|
74
|
+
* Cached stylesheet whose `url()` references use `CACHED_FONT_DIR_TOKEN`.
|
|
75
|
+
* The suffix ties the cache to that format: a `style.css` written by an
|
|
76
|
+
* earlier vinext holds the writing checkout's absolute paths, which would
|
|
77
|
+
* 404 once embedded, so it is never read and the font is fetched again.
|
|
78
|
+
* Change the suffix whenever the cached CSS format changes.
|
|
79
|
+
*/
|
|
80
|
+
const CACHED_FONT_CSS_FILE = "style-q7f3kd.css";
|
|
62
81
|
function formatGoogleFontsErrorBody(body) {
|
|
63
82
|
const trimmed = body.trim();
|
|
64
83
|
if (!trimmed) return "(empty response body)";
|
|
@@ -67,9 +86,10 @@ function formatGoogleFontsErrorBody(body) {
|
|
|
67
86
|
return `${trimmed.slice(0, MAX_GOOGLE_FONTS_ERROR_BODY_LENGTH)}\n... (truncated ${omitted} characters)`;
|
|
68
87
|
}
|
|
69
88
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
89
|
+
* Point the `@font-face { src: url(...) }` references of cached Google Fonts
|
|
90
|
+
* CSS at the served URL the plugin's `writeBundle` hook copies the font
|
|
91
|
+
* files to (and the dev middleware serves them from), by replacing
|
|
92
|
+
* `CACHED_FONT_DIR_TOKEN` with `/<assetsDir>/_vinext_fonts`.
|
|
73
93
|
*
|
|
74
94
|
* This is called once per transform, before the CSS string is embedded in
|
|
75
95
|
* the bundle as `_vinext.font.selfHostedCSS`. Every downstream consumer reads
|
|
@@ -78,9 +98,9 @@ function formatGoogleFontsErrorBody(body) {
|
|
|
78
98
|
* in `shims/font-google-base.ts`), and the HTTP `Link:` response header
|
|
79
99
|
* (via `buildAppPageFontLinkHeader` in `server/app-page-execution.ts`).
|
|
80
100
|
*
|
|
81
|
-
*
|
|
82
|
-
* (
|
|
83
|
-
*
|
|
101
|
+
* The token is substituted with plain split/join: it is a fixed string
|
|
102
|
+
* vinext wrote itself, so nothing about the checkout's path (spaces, quotes,
|
|
103
|
+
* parentheses, regex metacharacters, Windows separators) is parsed here.
|
|
84
104
|
*
|
|
85
105
|
* `assetsDir` must match whatever Vite has resolved for
|
|
86
106
|
* `build.assetsDir` on the client environment — otherwise the embedded
|
|
@@ -90,16 +110,9 @@ function formatGoogleFontsErrorBody(body) {
|
|
|
90
110
|
* passes the resolved value through from plugin state. The default is
|
|
91
111
|
* kept only so the exported helper can be driven directly from unit
|
|
92
112
|
* tests without synthesizing a full plugin context.
|
|
93
|
-
*
|
|
94
|
-
* Uses split/join rather than regex because `cacheDir` is an absolute
|
|
95
|
-
* filesystem path that may contain regex metacharacters on unusual
|
|
96
|
-
* filesystems.
|
|
97
113
|
*/
|
|
98
|
-
function _rewriteCachedFontCssToServedUrls(css,
|
|
99
|
-
|
|
100
|
-
if (!normalizedCacheDir || !css.includes(normalizedCacheDir)) return css;
|
|
101
|
-
const prefix = assetsDir || DEFAULT_ASSETS_DIR;
|
|
102
|
-
return css.split(normalizedCacheDir).join(`/${prefix}/${VINEXT_FONT_URL_NAMESPACE}`);
|
|
114
|
+
function _rewriteCachedFontCssToServedUrls(css, assetsDir = DEFAULT_ASSETS_DIR) {
|
|
115
|
+
return css.split(CACHED_FONT_DIR_TOKEN).join(`/${assetsDir || DEFAULT_ASSETS_DIR}/${VINEXT_FONT_URL_NAMESPACE}`);
|
|
103
116
|
}
|
|
104
117
|
/**
|
|
105
118
|
* Default `build.assetsDir` — matches vinext's resolved default in
|
|
@@ -274,24 +287,49 @@ function propertyNameToGoogleFontFamily(prop) {
|
|
|
274
287
|
}
|
|
275
288
|
/**
|
|
276
289
|
* Fetch Google Fonts CSS, download .woff2 files, cache locally, and return
|
|
277
|
-
* @font-face CSS
|
|
290
|
+
* @font-face CSS whose `url()` references use `CACHED_FONT_DIR_TOKEN`.
|
|
278
291
|
*
|
|
279
292
|
* Cache dir structure: .vinext/fonts/<family-hash>/
|
|
280
|
-
* - style
|
|
293
|
+
* - style-<suffix>.css (the rewritten @font-face CSS, see `CACHED_FONT_CSS_FILE`)
|
|
281
294
|
* - *.woff2 (downloaded font files)
|
|
282
295
|
*/
|
|
283
296
|
async function fetchAndCacheFont(cssUrl, family, cacheDir) {
|
|
284
297
|
const { createHash } = await import("node:crypto");
|
|
285
298
|
const urlHash = createHash("md5").update(cssUrl).digest("hex").slice(0, 12);
|
|
286
|
-
const
|
|
287
|
-
const
|
|
299
|
+
const fontDirName = `${family.toLowerCase().replace(/\s+/g, "-")}-${urlHash}`;
|
|
300
|
+
const fontDir = path.join(cacheDir, fontDirName);
|
|
301
|
+
const cachedCSSPath = path.join(fontDir, CACHED_FONT_CSS_FILE);
|
|
288
302
|
if (fs.existsSync(cachedCSSPath)) return fs.readFileSync(cachedCSSPath, "utf-8");
|
|
303
|
+
const css = await downloadGoogleFont(cssUrl, family, fontDir, fontDirName);
|
|
304
|
+
try {
|
|
305
|
+
writeFileAtomically(cachedCSSPath, css);
|
|
306
|
+
} catch {}
|
|
307
|
+
return css;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Write-then-rename, so a write that fails midway never leaves a partial
|
|
311
|
+
* file for a later build to trust: both font files and the stylesheet are
|
|
312
|
+
* reused as soon as they exist.
|
|
313
|
+
*/
|
|
314
|
+
function writeFileAtomically(filePath, data) {
|
|
315
|
+
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
316
|
+
try {
|
|
317
|
+
fs.writeFileSync(tempPath, data);
|
|
318
|
+
fs.renameSync(tempPath, filePath);
|
|
319
|
+
} catch (err) {
|
|
320
|
+
fs.rmSync(tempPath, { force: true });
|
|
321
|
+
throw err;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async function downloadGoogleFont(cssUrl, family, fontDir, fontDirName) {
|
|
325
|
+
const { createHash } = await import("node:crypto");
|
|
289
326
|
const cssResponse = await fetch(cssUrl, { headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" } });
|
|
290
327
|
if (!cssResponse.ok) {
|
|
291
328
|
const body = await cssResponse.text().catch(() => "");
|
|
292
329
|
throw new GoogleFontsHttpError(cssUrl, cssResponse.status, body);
|
|
293
330
|
}
|
|
294
331
|
let css = await cssResponse.text();
|
|
332
|
+
if (!css.trim()) throw new Error(`Google Fonts returned an empty stylesheet: ${cssUrl}`);
|
|
295
333
|
const urlRe = /url\((https:\/\/fonts\.gstatic\.com\/[^)]+)\)/g;
|
|
296
334
|
const urls = /* @__PURE__ */ new Map();
|
|
297
335
|
let urlMatch;
|
|
@@ -308,14 +346,13 @@ async function fetchAndCacheFont(cssUrl, family, cacheDir) {
|
|
|
308
346
|
const filePath = path.join(fontDir, filename);
|
|
309
347
|
if (!fs.existsSync(filePath)) {
|
|
310
348
|
const fontResponse = await fetch(fontUrl);
|
|
311
|
-
if (fontResponse.ok) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
349
|
+
if (!fontResponse.ok) throw new Error(`Font file download failed with HTTP ${fontResponse.status}: ${fontUrl}`);
|
|
350
|
+
const buffer = Buffer.from(await fontResponse.arrayBuffer());
|
|
351
|
+
if (buffer.byteLength === 0) throw new Error(`Font file download returned an empty body: ${fontUrl}`);
|
|
352
|
+
writeFileAtomically(filePath, buffer);
|
|
315
353
|
}
|
|
316
|
-
css = css.split(fontUrl).join(
|
|
354
|
+
css = css.split(fontUrl).join(`${CACHED_FONT_DIR_TOKEN}/${fontDirName}/${filename}`);
|
|
317
355
|
}
|
|
318
|
-
fs.writeFileSync(cachedCSSPath, css);
|
|
319
356
|
return css;
|
|
320
357
|
}
|
|
321
358
|
/**
|
|
@@ -546,7 +583,7 @@ function createGoogleFontsPlugin(fontGoogleShimPath, shimsDir) {
|
|
|
546
583
|
if (err instanceof GoogleFontsHttpError) throw new Error(`[vinext:google-fonts] ${id}: Google Fonts returned HTTP ${err.status} for ${err.url}.\n${formatGoogleFontsErrorBody(err.responseBody)}`);
|
|
547
584
|
return;
|
|
548
585
|
}
|
|
549
|
-
const servedCSS = _rewriteCachedFontCssToServedUrls(localCSS,
|
|
586
|
+
const servedCSS = _rewriteCachedFontCssToServedUrls(localCSS, transformAssetsDir);
|
|
550
587
|
const preloadUrls = findFontFilesInCss(servedCSS, validated.preload ? validated.subsets : void 0).filter((file) => file.preloadFontFile).map((file) => file.googleFontFileUrl);
|
|
551
588
|
const fallbackMetrics = validated.adjustFontFallback === false ? void 0 : getFallbackFontOverrideMetrics(family);
|
|
552
589
|
const adjustedFallbackCSS = fallbackMetrics ? buildFallbackFontFace(family, fallbackMetrics) : void 0;
|
|
@@ -11,7 +11,7 @@ import { Plugin } from "vite";
|
|
|
11
11
|
* identifiers, falls through to the AST pass.
|
|
12
12
|
*/
|
|
13
13
|
declare function mayContainVeryDynamicRequest(code: string): boolean;
|
|
14
|
-
declare function transformVeryDynamicRequests(code: string, id: string): MagicStringTransformResult | null;
|
|
14
|
+
declare function transformVeryDynamicRequests(code: string, id: string): MagicStringTransformResult<import("magic-string").SourceMap> | null;
|
|
15
15
|
export declare function createIgnoreDynamicRequestsPlugin(getTranspiledPackages?: () => readonly string[]): Plugin;
|
|
16
16
|
export declare const _transformVeryDynamicRequests: typeof transformVeryDynamicRequests;
|
|
17
17
|
export declare const _mayContainVeryDynamicRequest: typeof mayContainVeryDynamicRequest;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import path
|
|
1
|
+
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { DYNAMIC_IMPORT_PRESCAN, SCRIPT_MODULE_ID_RE, collectBindingNames, forEachAstChild, isIdentifierNamed, mayContainDynamicImport, scriptParserLanguage, stringLiteralValue, unwrapExpression } from "./ast-utils.js";
|
|
3
3
|
import { magicStringTransformResult, omitUnusedBuildSourcemap } from "./transform-result.js";
|
|
4
4
|
import { stripViteModuleQuery } from "../utils/path.js";
|
|
5
|
+
import { isForeignNodeModule } from "../utils/package-name.js";
|
|
5
6
|
import { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, hasAstBinding, isFunctionNode } from "./ast-scope.js";
|
|
6
7
|
import { createTransformCache } from "./transform-cache.js";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
@@ -543,9 +544,7 @@ function createIgnoreDynamicRequestsPlugin(getTranspiledPackages = () => []) {
|
|
|
543
544
|
}
|
|
544
545
|
function shouldTransformVeryDynamicRequests(environment, id, transpiledPackages) {
|
|
545
546
|
if (environment.config.consumer === "server") return true;
|
|
546
|
-
|
|
547
|
-
if (!normalizedId.includes("/node_modules/")) return false;
|
|
548
|
-
return !transpiledPackages.some((packageName) => normalizedId.includes(`/node_modules/${packageName}/`));
|
|
547
|
+
return isForeignNodeModule(id, transpiledPackages);
|
|
549
548
|
}
|
|
550
549
|
const _transformVeryDynamicRequests = transformVeryDynamicRequests;
|
|
551
550
|
const _mayContainVeryDynamicRequest = mayContainVeryDynamicRequest;
|
|
@@ -29,10 +29,11 @@ import { Plugin } from "vite";
|
|
|
29
29
|
* to the tainted set. This propagates the taint along the import graph
|
|
30
30
|
* synchronously, before plugin-rsc's `order: "pre"` validate-imports
|
|
31
31
|
* handler sees the next `server-only` request.
|
|
32
|
-
* 3. When a tainted module imports `server-only` in a non-RSC
|
|
33
|
-
* short-circuit to the no-op shim path so plugin-rsc's
|
|
34
|
-
* matches the bare `^server-only$` specifier) never fires
|
|
35
|
-
* import.
|
|
32
|
+
* 3. When a tainted module imports `server-only` in a non-RSC server
|
|
33
|
+
* environment, short-circuit to the no-op shim path so plugin-rsc's
|
|
34
|
+
* filter (which matches the bare `^server-only$` specifier) never fires
|
|
35
|
+
* for that import. Browser environments are skipped entirely, so the
|
|
36
|
+
* client `server-only` validators still see every import there.
|
|
36
37
|
*
|
|
37
38
|
* The taint set is scoped to the middleware chain only — `server-only`
|
|
38
39
|
* imports from anywhere else (including client component code traversing
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { stripViteModuleQuery } from "../utils/path.js";
|
|
3
|
+
import { isServerEnvironment } from "./environment.js";
|
|
3
4
|
//#region src/plugins/middleware-server-only.ts
|
|
4
5
|
/**
|
|
5
6
|
* Allow `import 'server-only'` from neutral server targets (and any module
|
|
@@ -30,10 +31,11 @@ import { stripViteModuleQuery } from "../utils/path.js";
|
|
|
30
31
|
* to the tainted set. This propagates the taint along the import graph
|
|
31
32
|
* synchronously, before plugin-rsc's `order: "pre"` validate-imports
|
|
32
33
|
* handler sees the next `server-only` request.
|
|
33
|
-
* 3. When a tainted module imports `server-only` in a non-RSC
|
|
34
|
-
* short-circuit to the no-op shim path so plugin-rsc's
|
|
35
|
-
* matches the bare `^server-only$` specifier) never fires
|
|
36
|
-
* import.
|
|
34
|
+
* 3. When a tainted module imports `server-only` in a non-RSC server
|
|
35
|
+
* environment, short-circuit to the no-op shim path so plugin-rsc's
|
|
36
|
+
* filter (which matches the bare `^server-only$` specifier) never fires
|
|
37
|
+
* for that import. Browser environments are skipped entirely, so the
|
|
38
|
+
* client `server-only` validators still see every import there.
|
|
37
39
|
*
|
|
38
40
|
* The taint set is scoped to the middleware chain only — `server-only`
|
|
39
41
|
* imports from anywhere else (including client component code traversing
|
|
@@ -71,7 +73,8 @@ function createMiddlewareServerOnlyPlugin(options) {
|
|
|
71
73
|
resolveId: {
|
|
72
74
|
order: "pre",
|
|
73
75
|
async handler(id, importer, opts) {
|
|
74
|
-
|
|
76
|
+
const environment = this.environment;
|
|
77
|
+
if (!environment || !isServerEnvironment(environment) || environment.name === "rsc") return;
|
|
75
78
|
if (!importer) return;
|
|
76
79
|
if (!isTainted(importer) && !options.isNeutralServerModule?.(canonicalizeId(importer))) return;
|
|
77
80
|
if (id === "server-only") return {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { SCRIPT_MODULE_ID_RE, mayContainDynamicImport, scriptParserLanguage, staticStringValue, walkAst } from "./ast-utils.js";
|
|
3
3
|
import { canonicalizeFilePath, isPathInsideOrEqual, stripViteModuleQuery } from "../utils/path.js";
|
|
4
|
-
import { packageNameFromSpecifier } from "../utils/package-name.js";
|
|
5
4
|
import { isServerEnvironment } from "./environment.js";
|
|
5
|
+
import { packageNameFromSpecifier } from "../utils/package-name.js";
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import { parseAst } from "vite";
|
|
8
8
|
//#region src/plugins/pages-node-externals.ts
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Plugin, ResolvedConfig } from "vite";
|
|
2
|
+
import { RscPluginManager } from "@vitejs/plugin-rsc";
|
|
3
|
+
//#region src/plugins/rsc-scan-glob-imports.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* @vitejs/plugin-rsc 0.5.36 and 0.5.37 reduce scan-build modules to their
|
|
6
|
+
* import specifiers with es-module-lexer v3, which reports template-literal
|
|
7
|
+
* dynamic imports as glob patterns (``import(`file://${p}`)`` becomes
|
|
8
|
+
* `"file://*"`). The scan then emits them as plain imports, which fail to
|
|
9
|
+
* resolve (e.g. in @module-federation/vite). Other versions skip these
|
|
10
|
+
* specifiers (0.5.38 via vitejs/vite-plugin-react#1506), so for the affected
|
|
11
|
+
* ones keep the specifiers that don't resolve external during the scan. A real
|
|
12
|
+
* module whose specifier contains `*` still resolves and stays in the scan
|
|
13
|
+
* graph. The scan's output is discarded, so nothing else changes.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isRscScanGlobImportsAffected(version: string): boolean;
|
|
16
|
+
export declare function createRscScanGlobImportsPlugin(options: {
|
|
17
|
+
getManager: (config: ResolvedConfig) => Promise<RscPluginManager | undefined>;
|
|
18
|
+
}): Plugin;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isVersionBelow } from "../utils/react-version.js";
|
|
2
|
+
//#region src/plugins/rsc-scan-glob-imports.ts
|
|
3
|
+
/**
|
|
4
|
+
* @vitejs/plugin-rsc 0.5.36 and 0.5.37 reduce scan-build modules to their
|
|
5
|
+
* import specifiers with es-module-lexer v3, which reports template-literal
|
|
6
|
+
* dynamic imports as glob patterns (``import(`file://${p}`)`` becomes
|
|
7
|
+
* `"file://*"`). The scan then emits them as plain imports, which fail to
|
|
8
|
+
* resolve (e.g. in @module-federation/vite). Other versions skip these
|
|
9
|
+
* specifiers (0.5.38 via vitejs/vite-plugin-react#1506), so for the affected
|
|
10
|
+
* ones keep the specifiers that don't resolve external during the scan. A real
|
|
11
|
+
* module whose specifier contains `*` still resolves and stays in the scan
|
|
12
|
+
* graph. The scan's output is discarded, so nothing else changes.
|
|
13
|
+
*/
|
|
14
|
+
function isRscScanGlobImportsAffected(version) {
|
|
15
|
+
return !isVersionBelow(version, [
|
|
16
|
+
0,
|
|
17
|
+
5,
|
|
18
|
+
36
|
|
19
|
+
]) && isVersionBelow(version, [
|
|
20
|
+
0,
|
|
21
|
+
5,
|
|
22
|
+
38
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
function createRscScanGlobImportsPlugin(options) {
|
|
26
|
+
return {
|
|
27
|
+
name: "vinext:rsc-scan-glob-imports",
|
|
28
|
+
apply: "build",
|
|
29
|
+
enforce: "pre",
|
|
30
|
+
resolveId: {
|
|
31
|
+
filter: { id: /\*/ },
|
|
32
|
+
async handler(source, importer, resolveOptions) {
|
|
33
|
+
if (!(await options.getManager(this.environment.config))?.isScanBuild) return;
|
|
34
|
+
try {
|
|
35
|
+
const resolved = await this.resolve(source, importer, {
|
|
36
|
+
...resolveOptions,
|
|
37
|
+
skipSelf: true
|
|
38
|
+
});
|
|
39
|
+
if (resolved) return resolved;
|
|
40
|
+
} catch {}
|
|
41
|
+
return {
|
|
42
|
+
id: source,
|
|
43
|
+
external: true
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { createRscScanGlobImportsPlugin, isRscScanGlobImportsAffected };
|