vinext 0.1.1 → 0.1.3
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 +2 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/check.js +4 -3
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/window-next.d.ts +8 -5
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +88 -16
- package/dist/config/next-config.d.ts +59 -4
- package/dist/config/next-config.js +149 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +189 -101
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +71 -6
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +54 -9
- package/dist/entries/pages-server-entry.js +48 -11
- package/dist/index.d.ts +0 -2
- package/dist/index.js +285 -139
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +10 -5
- package/dist/plugins/optimize-imports.js +27 -21
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +25 -2
- package/dist/routing/app-route-graph.js +91 -22
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +23 -2
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +19 -10
- package/dist/server/app-browser-entry.js +269 -297
- package/dist/server/app-browser-error.d.ts +10 -3
- package/dist/server/app-browser-error.js +47 -6
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +7 -4
- package/dist/server/app-browser-navigation-controller.js +33 -9
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +3 -1
- package/dist/server/app-fallback-renderer.js +6 -2
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +24 -3
- package/dist/server/app-page-boundary-render.d.ts +3 -1
- package/dist/server/app-page-boundary-render.js +31 -16
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +71 -8
- package/dist/server/app-page-dispatch.d.ts +34 -0
- package/dist/server/app-page-dispatch.js +167 -97
- package/dist/server/app-page-element-builder.d.ts +23 -2
- package/dist/server/app-page-element-builder.js +42 -10
- package/dist/server/app-page-execution.d.ts +7 -2
- package/dist/server/app-page-execution.js +53 -18
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +13 -2
- package/dist/server/app-page-render.js +48 -17
- package/dist/server/app-page-request.d.ts +3 -0
- package/dist/server/app-page-request.js +5 -3
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +5 -1
- package/dist/server/app-page-route-wiring.js +21 -11
- package/dist/server/app-page-stream.d.ts +16 -9
- package/dist/server/app-page-stream.js +12 -9
- package/dist/server/app-pages-bridge.d.ts +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +25 -0
- package/dist/server/app-rsc-handler.js +153 -53
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +12 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +81 -8
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +287 -63
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +186 -22
- package/dist/server/navigation-planner.js +302 -0
- package/dist/server/navigation-trace.d.ts +18 -1
- package/dist/server/navigation-trace.js +18 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +20 -3
- package/dist/server/pages-api-route.js +19 -3
- package/dist/server/pages-asset-tags.d.ts +16 -4
- package/dist/server/pages-asset-tags.js +22 -12
- package/dist/server/pages-data-route.d.ts +8 -1
- package/dist/server/pages-data-route.js +16 -3
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +175 -122
- package/dist/server/pages-page-data.d.ts +39 -2
- package/dist/server/pages-page-data.js +261 -46
- package/dist/server/pages-page-handler.d.ts +5 -2
- package/dist/server/pages-page-handler.js +78 -25
- package/dist/server/pages-page-response.d.ts +47 -2
- package/dist/server/pages-page-response.js +73 -9
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +16 -1
- package/dist/server/pages-request-pipeline.js +96 -38
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +107 -37
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/cache-runtime.js +12 -4
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +79 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +6 -4
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +38 -11
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +11 -1
- package/dist/shims/fetch-cache.js +55 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +66 -5
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +18 -23
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +12 -5
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +14 -17
- package/dist/shims/navigation.js +93 -46
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +13 -2
- package/dist/shims/router.js +434 -116
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +33 -2
- package/dist/shims/server.js +75 -18
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +8 -1
- package/dist/utils/path.js +13 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/dynamic-preload-metadata.d.ts
|
|
5
|
+
type TransformResult = {
|
|
6
|
+
code: string;
|
|
7
|
+
map: ReturnType<MagicString["generateMap"]>;
|
|
8
|
+
};
|
|
9
|
+
type ResolveDynamicImport = (specifier: string, importer: string) => Promise<string | null>;
|
|
10
|
+
declare function transformNextDynamicPreloadMetadata(code: string, id: string, root: string, resolveDynamicImport: ResolveDynamicImport): Promise<TransformResult | null>;
|
|
11
|
+
declare function createDynamicPreloadMetadataPlugin(): Plugin;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createDynamicPreloadMetadataPlugin, transformNextDynamicPreloadMetadata };
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
2
|
+
import { relativeWithinRoot, tryRealpathSync } from "../build/ssr-manifest.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseAst } from "vite";
|
|
5
|
+
import MagicString from "magic-string";
|
|
6
|
+
//#region src/plugins/dynamic-preload-metadata.ts
|
|
7
|
+
function getString(node, key) {
|
|
8
|
+
const value = node[key];
|
|
9
|
+
return typeof value === "string" ? value : null;
|
|
10
|
+
}
|
|
11
|
+
function getNumber(node, key) {
|
|
12
|
+
const value = node[key];
|
|
13
|
+
return typeof value === "number" ? value : null;
|
|
14
|
+
}
|
|
15
|
+
function getArray(node, key) {
|
|
16
|
+
const value = node[key];
|
|
17
|
+
return Array.isArray(value) ? value : [];
|
|
18
|
+
}
|
|
19
|
+
function getBoolean(node, key) {
|
|
20
|
+
return node[key] === true;
|
|
21
|
+
}
|
|
22
|
+
function nodeName(node) {
|
|
23
|
+
if (!isUnknownRecord(node)) return null;
|
|
24
|
+
const name = node.name;
|
|
25
|
+
if (typeof name === "string") return name;
|
|
26
|
+
const value = node.value;
|
|
27
|
+
return typeof value === "string" ? value : null;
|
|
28
|
+
}
|
|
29
|
+
function nodeStringValue(node) {
|
|
30
|
+
if (!isUnknownRecord(node)) return null;
|
|
31
|
+
const value = node.value;
|
|
32
|
+
return typeof value === "string" ? value : null;
|
|
33
|
+
}
|
|
34
|
+
function walkAst(value, visitor) {
|
|
35
|
+
if (!isUnknownRecord(value)) return;
|
|
36
|
+
visitor(value);
|
|
37
|
+
for (const [key, child] of Object.entries(value)) {
|
|
38
|
+
if (key === "parent") continue;
|
|
39
|
+
if (Array.isArray(child)) for (const item of child) walkAst(item, visitor);
|
|
40
|
+
else if (isUnknownRecord(child)) walkAst(child, visitor);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function importSource(node) {
|
|
44
|
+
const source = node.source;
|
|
45
|
+
if (!isUnknownRecord(source)) return null;
|
|
46
|
+
return nodeStringValue(source);
|
|
47
|
+
}
|
|
48
|
+
function isNextDynamicSource(source) {
|
|
49
|
+
return source === "next/dynamic" || source === "next/dynamic.js";
|
|
50
|
+
}
|
|
51
|
+
function collectDynamicImportLocals(ast) {
|
|
52
|
+
const locals = /* @__PURE__ */ new Set();
|
|
53
|
+
if (!isUnknownRecord(ast)) return locals;
|
|
54
|
+
for (const node of getArray(ast, "body")) {
|
|
55
|
+
if (!isUnknownRecord(node)) continue;
|
|
56
|
+
if (getString(node, "type") !== "ImportDeclaration") continue;
|
|
57
|
+
if (!isNextDynamicSource(importSource(node))) continue;
|
|
58
|
+
for (const specifier of getArray(node, "specifiers")) {
|
|
59
|
+
if (!isUnknownRecord(specifier)) continue;
|
|
60
|
+
if (getString(specifier, "type") !== "ImportDefaultSpecifier") continue;
|
|
61
|
+
const local = nodeName(specifier.local);
|
|
62
|
+
if (local) locals.add(local);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return locals;
|
|
66
|
+
}
|
|
67
|
+
function isIdentifierNameInSet(node, names) {
|
|
68
|
+
if (!isUnknownRecord(node)) return false;
|
|
69
|
+
return getString(node, "type") === "Identifier" && names.has(getString(node, "name") ?? "");
|
|
70
|
+
}
|
|
71
|
+
function isDynamicCall(node, dynamicLocals) {
|
|
72
|
+
if (getString(node, "type") !== "CallExpression") return false;
|
|
73
|
+
return isIdentifierNameInSet(node.callee, dynamicLocals);
|
|
74
|
+
}
|
|
75
|
+
function addBindingName(pattern, names) {
|
|
76
|
+
if (!isUnknownRecord(pattern)) return;
|
|
77
|
+
const type = getString(pattern, "type");
|
|
78
|
+
if (type === null) return;
|
|
79
|
+
switch (type) {
|
|
80
|
+
case "Identifier": {
|
|
81
|
+
const name = getString(pattern, "name");
|
|
82
|
+
if (name) names.add(name);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
case "AssignmentPattern":
|
|
86
|
+
addBindingName(pattern.left, names);
|
|
87
|
+
return;
|
|
88
|
+
case "RestElement":
|
|
89
|
+
addBindingName(pattern.argument, names);
|
|
90
|
+
return;
|
|
91
|
+
case "ArrayPattern":
|
|
92
|
+
for (const element of getArray(pattern, "elements")) addBindingName(element, names);
|
|
93
|
+
return;
|
|
94
|
+
case "ObjectPattern":
|
|
95
|
+
for (const property of getArray(pattern, "properties")) {
|
|
96
|
+
if (!isUnknownRecord(property)) continue;
|
|
97
|
+
if (getString(property, "type") === "RestElement") {
|
|
98
|
+
addBindingName(property.argument, names);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
addBindingName(property.value, names);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
default: return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function addVariableDeclarationBindingNames(node, names) {
|
|
108
|
+
if (!isUnknownRecord(node) || getString(node, "type") !== "VariableDeclaration") return;
|
|
109
|
+
for (const declaration of getArray(node, "declarations")) if (isUnknownRecord(declaration)) addBindingName(declaration.id, names);
|
|
110
|
+
}
|
|
111
|
+
function collectBlockScopedBindingNames(body) {
|
|
112
|
+
const names = /* @__PURE__ */ new Set();
|
|
113
|
+
for (const statement of body) {
|
|
114
|
+
if (!isUnknownRecord(statement)) continue;
|
|
115
|
+
const type = getString(statement, "type");
|
|
116
|
+
if (type === "VariableDeclaration") {
|
|
117
|
+
if (getString(statement, "kind") !== "var") addVariableDeclarationBindingNames(statement, names);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (type === "FunctionDeclaration" || type === "ClassDeclaration") {
|
|
121
|
+
const name = nodeName(statement.id);
|
|
122
|
+
if (name) names.add(name);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return names;
|
|
126
|
+
}
|
|
127
|
+
function collectSwitchScopedBindingNames(node) {
|
|
128
|
+
const names = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const switchCase of getArray(node, "cases")) {
|
|
130
|
+
if (!isUnknownRecord(switchCase)) continue;
|
|
131
|
+
for (const statement of getArray(switchCase, "consequent")) for (const name of collectBlockScopedBindingNames([statement])) names.add(name);
|
|
132
|
+
}
|
|
133
|
+
return names;
|
|
134
|
+
}
|
|
135
|
+
function collectVarBindingNames(value, names) {
|
|
136
|
+
if (!isUnknownRecord(value)) return;
|
|
137
|
+
const type = getString(value, "type");
|
|
138
|
+
if (type === "FunctionDeclaration" || type === "FunctionExpression" || type === "ArrowFunctionExpression") return;
|
|
139
|
+
if (type === "VariableDeclaration" && getString(value, "kind") === "var") addVariableDeclarationBindingNames(value, names);
|
|
140
|
+
for (const [key, child] of Object.entries(value)) {
|
|
141
|
+
if (key === "parent") continue;
|
|
142
|
+
if (Array.isArray(child)) for (const item of child) collectVarBindingNames(item, names);
|
|
143
|
+
else if (isUnknownRecord(child)) collectVarBindingNames(child, names);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function collectFunctionScopeBindingNames(node) {
|
|
147
|
+
const names = /* @__PURE__ */ new Set();
|
|
148
|
+
if (getString(node, "type") === "FunctionExpression") {
|
|
149
|
+
const name = nodeName(node.id);
|
|
150
|
+
if (name) names.add(name);
|
|
151
|
+
}
|
|
152
|
+
for (const param of getArray(node, "params")) addBindingName(param, names);
|
|
153
|
+
collectVarBindingNames(node.body, names);
|
|
154
|
+
return names;
|
|
155
|
+
}
|
|
156
|
+
function collectForBindingNames(node) {
|
|
157
|
+
const names = /* @__PURE__ */ new Set();
|
|
158
|
+
addVariableDeclarationBindingNames(node.init, names);
|
|
159
|
+
addVariableDeclarationBindingNames(node.left, names);
|
|
160
|
+
return names;
|
|
161
|
+
}
|
|
162
|
+
function withoutBindings(activeNames, localNames) {
|
|
163
|
+
if (activeNames.size === 0 || localNames.size === 0) return activeNames;
|
|
164
|
+
let scoped = null;
|
|
165
|
+
for (const name of localNames) {
|
|
166
|
+
if (!activeNames.has(name)) continue;
|
|
167
|
+
scoped ??= new Set(activeNames);
|
|
168
|
+
scoped.delete(name);
|
|
169
|
+
}
|
|
170
|
+
return scoped ?? activeNames;
|
|
171
|
+
}
|
|
172
|
+
function visitChildren(node, dynamicLocals, visitor) {
|
|
173
|
+
for (const [key, child] of Object.entries(node)) {
|
|
174
|
+
if (key === "parent") continue;
|
|
175
|
+
if (Array.isArray(child)) for (const item of child) visitDynamicCalls(item, dynamicLocals, visitor);
|
|
176
|
+
else if (isUnknownRecord(child)) visitDynamicCalls(child, dynamicLocals, visitor);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function visitDynamicCalls(value, dynamicLocals, visitor) {
|
|
180
|
+
if (!isUnknownRecord(value) || dynamicLocals.size === 0) return;
|
|
181
|
+
const type = getString(value, "type");
|
|
182
|
+
if (type === "Program") {
|
|
183
|
+
const scoped = withoutBindings(dynamicLocals, collectBlockScopedBindingNames(getArray(value, "body")));
|
|
184
|
+
for (const statement of getArray(value, "body")) visitDynamicCalls(statement, scoped, visitor);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (type === "BlockStatement") {
|
|
188
|
+
const scoped = withoutBindings(dynamicLocals, collectBlockScopedBindingNames(getArray(value, "body")));
|
|
189
|
+
for (const statement of getArray(value, "body")) visitDynamicCalls(statement, scoped, visitor);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (type === "SwitchStatement") {
|
|
193
|
+
visitDynamicCalls(value.discriminant, dynamicLocals, visitor);
|
|
194
|
+
const scoped = withoutBindings(dynamicLocals, collectSwitchScopedBindingNames(value));
|
|
195
|
+
for (const switchCase of getArray(value, "cases")) visitDynamicCalls(switchCase, scoped, visitor);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (type === "FunctionDeclaration" || type === "FunctionExpression" || type === "ArrowFunctionExpression") {
|
|
199
|
+
visitChildren(value, withoutBindings(dynamicLocals, collectFunctionScopeBindingNames(value)), visitor);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (type === "ClassDeclaration" || type === "ClassExpression") {
|
|
203
|
+
const names = /* @__PURE__ */ new Set();
|
|
204
|
+
const name = nodeName(value.id);
|
|
205
|
+
if (name) names.add(name);
|
|
206
|
+
visitChildren(value, withoutBindings(dynamicLocals, names), visitor);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (type === "ForStatement" || type === "ForInStatement" || type === "ForOfStatement") {
|
|
210
|
+
visitChildren(value, withoutBindings(dynamicLocals, collectForBindingNames(value)), visitor);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (type === "CatchClause") {
|
|
214
|
+
const names = /* @__PURE__ */ new Set();
|
|
215
|
+
addBindingName(value.param, names);
|
|
216
|
+
visitChildren(value, withoutBindings(dynamicLocals, names), visitor);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (isDynamicCall(value, dynamicLocals)) visitor(value);
|
|
220
|
+
visitChildren(value, dynamicLocals, visitor);
|
|
221
|
+
}
|
|
222
|
+
function collectImportSpecifiers(node) {
|
|
223
|
+
const specifiers = [];
|
|
224
|
+
const seen = /* @__PURE__ */ new Set();
|
|
225
|
+
walkAst(node, (item) => {
|
|
226
|
+
if (getString(item, "type") === "ImportExpression") {
|
|
227
|
+
const specifier = nodeStringValue(item.source);
|
|
228
|
+
if (specifier && !seen.has(specifier)) {
|
|
229
|
+
seen.add(specifier);
|
|
230
|
+
specifiers.push(specifier);
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (getString(item, "type") !== "CallExpression") return;
|
|
235
|
+
const callee = item.callee;
|
|
236
|
+
if (!isUnknownRecord(callee) || getString(callee, "type") !== "Import") return;
|
|
237
|
+
const firstArg = getArray(item, "arguments")[0];
|
|
238
|
+
const specifier = nodeStringValue(firstArg);
|
|
239
|
+
if (specifier && !seen.has(specifier)) {
|
|
240
|
+
seen.add(specifier);
|
|
241
|
+
specifiers.push(specifier);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
return specifiers;
|
|
245
|
+
}
|
|
246
|
+
function propertyKeyName(property) {
|
|
247
|
+
if (!isUnknownRecord(property)) return null;
|
|
248
|
+
if (getBoolean(property, "computed")) return null;
|
|
249
|
+
return nodeName(property.key);
|
|
250
|
+
}
|
|
251
|
+
function objectProperties(node) {
|
|
252
|
+
if (!isUnknownRecord(node) || getString(node, "type") !== "ObjectExpression") return [];
|
|
253
|
+
return getArray(node, "properties").filter(isUnknownRecord);
|
|
254
|
+
}
|
|
255
|
+
function hasObjectProperty(node, name) {
|
|
256
|
+
return objectProperties(node).some((property) => propertyKeyName(property) === name);
|
|
257
|
+
}
|
|
258
|
+
function findObjectProperty(node, name) {
|
|
259
|
+
return objectProperties(node).find((property) => propertyKeyName(property) === name) ?? null;
|
|
260
|
+
}
|
|
261
|
+
function dynamicLoaderNode(firstArg) {
|
|
262
|
+
if (!isUnknownRecord(firstArg) || getString(firstArg, "type") !== "ObjectExpression") return firstArg;
|
|
263
|
+
return (findObjectProperty(firstArg, "loader") ?? findObjectProperty(firstArg, "modules"))?.value;
|
|
264
|
+
}
|
|
265
|
+
function findLastEndedProperty(node) {
|
|
266
|
+
const properties = objectProperties(node);
|
|
267
|
+
for (let index = properties.length - 1; index >= 0; index -= 1) if (getNumber(properties[index], "end") !== null) return properties[index];
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
function appendObjectProperty(output, objectNode, property) {
|
|
271
|
+
const start = getNumber(objectNode, "start");
|
|
272
|
+
const end = getNumber(objectNode, "end");
|
|
273
|
+
if (start === null || end === null) return false;
|
|
274
|
+
const lastProperty = findLastEndedProperty(objectNode);
|
|
275
|
+
if (!lastProperty) {
|
|
276
|
+
output.appendLeft(start + 1, property);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
const propertyEnd = getNumber(lastProperty, "end");
|
|
280
|
+
if (propertyEnd === null) return false;
|
|
281
|
+
output.appendLeft(propertyEnd, `, ${property}`);
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
function stripComments(source) {
|
|
285
|
+
return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
286
|
+
}
|
|
287
|
+
function insertSecondOptionsArgument(output, code, callNode, firstArg, optionsLiteral) {
|
|
288
|
+
const callEnd = getNumber(callNode, "end");
|
|
289
|
+
const firstArgEnd = getNumber(firstArg, "end");
|
|
290
|
+
if (callEnd === null || firstArgEnd === null) return false;
|
|
291
|
+
const closeParen = callEnd - 1;
|
|
292
|
+
const separator = stripComments(code.slice(firstArgEnd, closeParen)).trimEnd().endsWith(",") ? " " : ", ";
|
|
293
|
+
output.appendLeft(closeParen, `${separator}${optionsLiteral}`);
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
function cleanResolvedId(id) {
|
|
297
|
+
let start = 0;
|
|
298
|
+
while (start < id.length && id.charCodeAt(start) === 0) start += 1;
|
|
299
|
+
return id.slice(start).replace(/^\/@fs\//, "/").split("?")[0].replace(/\\/g, "/");
|
|
300
|
+
}
|
|
301
|
+
const rootRealpathCache = /* @__PURE__ */ new Map();
|
|
302
|
+
function cachedRootRealpath(root) {
|
|
303
|
+
if (!rootRealpathCache.has(root)) rootRealpathCache.set(root, tryRealpathSync(root));
|
|
304
|
+
return rootRealpathCache.get(root) ?? null;
|
|
305
|
+
}
|
|
306
|
+
/** `code` offset -> human `:line:column` (1-based), for build error messages. */
|
|
307
|
+
function formatNodeLocation(code, node) {
|
|
308
|
+
const start = getNumber(node, "start");
|
|
309
|
+
if (start === null) return "";
|
|
310
|
+
const before = code.slice(0, start);
|
|
311
|
+
return `:${before.split("\n").length}:${start - before.lastIndexOf("\n")}`;
|
|
312
|
+
}
|
|
313
|
+
function toManifestModuleId(root, resolvedId) {
|
|
314
|
+
const cleaned = cleanResolvedId(resolvedId);
|
|
315
|
+
if (!path.isAbsolute(cleaned)) return cleaned.replace(/^\/+/, "");
|
|
316
|
+
const rootCandidates = new Set([root]);
|
|
317
|
+
const realRoot = cachedRootRealpath(root);
|
|
318
|
+
if (realRoot) rootCandidates.add(realRoot);
|
|
319
|
+
const moduleCandidates = new Set([cleaned]);
|
|
320
|
+
const realCleaned = tryRealpathSync(cleaned);
|
|
321
|
+
if (realCleaned) moduleCandidates.add(realCleaned.replace(/\\/g, "/"));
|
|
322
|
+
for (const rootCandidate of rootCandidates) for (const moduleCandidate of moduleCandidates) {
|
|
323
|
+
const relative = relativeWithinRoot(rootCandidate, moduleCandidate);
|
|
324
|
+
if (relative) return relative;
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
async function resolveManifestModuleIds(specifiers, importer, root, resolveDynamicImport) {
|
|
329
|
+
const resolvedIds = [];
|
|
330
|
+
const seen = /* @__PURE__ */ new Set();
|
|
331
|
+
for (const specifier of specifiers) {
|
|
332
|
+
const resolved = await resolveDynamicImport(specifier, importer);
|
|
333
|
+
const moduleId = resolved ? toManifestModuleId(root, resolved) : null;
|
|
334
|
+
if (!moduleId || seen.has(moduleId)) continue;
|
|
335
|
+
seen.add(moduleId);
|
|
336
|
+
resolvedIds.push(moduleId);
|
|
337
|
+
}
|
|
338
|
+
return resolvedIds;
|
|
339
|
+
}
|
|
340
|
+
function shouldSkipCall(firstArg, secondArg) {
|
|
341
|
+
if (hasObjectProperty(firstArg, "loadableGenerated")) return true;
|
|
342
|
+
return hasObjectProperty(secondArg, "loadableGenerated");
|
|
343
|
+
}
|
|
344
|
+
function applyLoadableGenerated(output, code, callNode, moduleIds) {
|
|
345
|
+
const args = getArray(callNode, "arguments");
|
|
346
|
+
const firstArg = args[0];
|
|
347
|
+
const secondArg = args[1];
|
|
348
|
+
if (!isUnknownRecord(firstArg)) return false;
|
|
349
|
+
if (shouldSkipCall(firstArg, secondArg)) return false;
|
|
350
|
+
const property = `loadableGenerated: { modules: ${JSON.stringify(moduleIds)} }`;
|
|
351
|
+
if (getString(firstArg, "type") === "ObjectExpression") return appendObjectProperty(output, firstArg, property);
|
|
352
|
+
if (secondArg === void 0) return insertSecondOptionsArgument(output, code, callNode, firstArg, `{ ${property} }`);
|
|
353
|
+
if (isUnknownRecord(secondArg) && getString(secondArg, "type") === "ObjectExpression") return appendObjectProperty(output, secondArg, property);
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
async function transformNextDynamicPreloadMetadata(code, id, root, resolveDynamicImport) {
|
|
357
|
+
if (!code.includes("next/dynamic")) return null;
|
|
358
|
+
let ast;
|
|
359
|
+
try {
|
|
360
|
+
ast = parseAst(code);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
if (typeof process !== "undefined" && process.env?.DEBUG?.includes("vinext")) console.debug(`[vinext] dynamic-preload-metadata: failed to parse ${id}:`, error);
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
const dynamicLocals = collectDynamicImportLocals(ast);
|
|
366
|
+
if (dynamicLocals.size === 0) return null;
|
|
367
|
+
const output = new MagicString(code);
|
|
368
|
+
let changed = false;
|
|
369
|
+
const pending = [];
|
|
370
|
+
visitDynamicCalls(ast, dynamicLocals, (node) => {
|
|
371
|
+
const args = getArray(node, "arguments");
|
|
372
|
+
if (args.length > 2) throw new Error(`next/dynamic only accepts 2 arguments (${id}${formatNodeLocation(code, node)})`);
|
|
373
|
+
const specifiers = collectImportSpecifiers(dynamicLoaderNode(args[0]));
|
|
374
|
+
if (specifiers.length === 0) return;
|
|
375
|
+
pending.push(resolveManifestModuleIds(specifiers, id, root, resolveDynamicImport).then((moduleIds) => {
|
|
376
|
+
if (moduleIds.length === 0) return;
|
|
377
|
+
if (applyLoadableGenerated(output, code, node, moduleIds)) changed = true;
|
|
378
|
+
}));
|
|
379
|
+
});
|
|
380
|
+
await Promise.all(pending);
|
|
381
|
+
if (!changed) return null;
|
|
382
|
+
return {
|
|
383
|
+
code: output.toString(),
|
|
384
|
+
map: output.generateMap({ hires: "boundary" })
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function createDynamicPreloadMetadataPlugin() {
|
|
388
|
+
let root = process.cwd();
|
|
389
|
+
return {
|
|
390
|
+
name: "vinext:dynamic-preload-metadata",
|
|
391
|
+
configResolved(config) {
|
|
392
|
+
root = config.root;
|
|
393
|
+
},
|
|
394
|
+
transform: {
|
|
395
|
+
filter: {
|
|
396
|
+
id: {
|
|
397
|
+
include: /\.(tsx?|jsx?|mjs)$/,
|
|
398
|
+
exclude: /node_modules/
|
|
399
|
+
},
|
|
400
|
+
code: "next/dynamic"
|
|
401
|
+
},
|
|
402
|
+
async handler(code, id) {
|
|
403
|
+
if (id.includes("node_modules") || id.startsWith("\0")) return null;
|
|
404
|
+
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return null;
|
|
405
|
+
const result = await transformNextDynamicPreloadMetadata(code, id, root, async (specifier, importer) => {
|
|
406
|
+
return (await this.resolve(specifier, importer, { skipSelf: true }))?.id ?? null;
|
|
407
|
+
});
|
|
408
|
+
if (!result) return null;
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
415
|
+
export { createDynamicPreloadMetadataPlugin, transformNextDynamicPreloadMetadata };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { forEachAstChild, hasRange, isAstRecord, nodeArray } from "./ast-utils.js";
|
|
2
|
+
import { parseAst } from "vite";
|
|
3
|
+
import MagicString from "magic-string";
|
|
4
|
+
//#region src/plugins/extensionless-dynamic-import.ts
|
|
5
|
+
const MODULE_EXTENSIONS = [
|
|
6
|
+
".mjs",
|
|
7
|
+
".js",
|
|
8
|
+
".mts",
|
|
9
|
+
".ts",
|
|
10
|
+
".jsx",
|
|
11
|
+
".tsx",
|
|
12
|
+
".json"
|
|
13
|
+
];
|
|
14
|
+
const TRANSFORMABLE_EXTENSIONS = new Set([
|
|
15
|
+
".mjs",
|
|
16
|
+
".js",
|
|
17
|
+
".mts",
|
|
18
|
+
".ts",
|
|
19
|
+
".jsx",
|
|
20
|
+
".tsx",
|
|
21
|
+
".cjs",
|
|
22
|
+
".cts"
|
|
23
|
+
]);
|
|
24
|
+
function createExtensionlessDynamicImportPlugin() {
|
|
25
|
+
let moduleExtensions = MODULE_EXTENSIONS;
|
|
26
|
+
return {
|
|
27
|
+
name: "vinext:extensionless-dynamic-import",
|
|
28
|
+
enforce: "pre",
|
|
29
|
+
configResolved(config) {
|
|
30
|
+
moduleExtensions = getModuleExtensions(config);
|
|
31
|
+
},
|
|
32
|
+
transform(code, id) {
|
|
33
|
+
if (!/\bimport\s*\(/.test(code)) return null;
|
|
34
|
+
if (isDependencyId(id)) return null;
|
|
35
|
+
const lang = langForId(id);
|
|
36
|
+
if (!lang) return null;
|
|
37
|
+
let ast;
|
|
38
|
+
try {
|
|
39
|
+
ast = parseAst(code, { lang });
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const imports = collectExtensionlessImports(ast, code, moduleExtensions);
|
|
44
|
+
if (imports.length === 0) return null;
|
|
45
|
+
const output = new MagicString(code);
|
|
46
|
+
for (const dynamicImport of imports) {
|
|
47
|
+
const source = code.slice(dynamicImport.sourceStart, dynamicImport.sourceEnd);
|
|
48
|
+
output.overwrite(dynamicImport.start, dynamicImport.end, buildReplacement(source, dynamicImport.globPattern, dynamicImport.moduleExtensions));
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
code: output.toString(),
|
|
52
|
+
map: output.generateMap({ hires: "boundary" })
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function langForId(id) {
|
|
58
|
+
const clean = id.split("?", 1)[0];
|
|
59
|
+
const dot = clean.lastIndexOf(".");
|
|
60
|
+
if (dot < 0) return null;
|
|
61
|
+
const ext = clean.slice(dot).toLowerCase();
|
|
62
|
+
if (!TRANSFORMABLE_EXTENSIONS.has(ext)) return null;
|
|
63
|
+
if (ext === ".ts" || ext === ".mts" || ext === ".cts") return "ts";
|
|
64
|
+
if (ext === ".tsx") return "tsx";
|
|
65
|
+
return "jsx";
|
|
66
|
+
}
|
|
67
|
+
function isDependencyId(id) {
|
|
68
|
+
return id.split("?", 1)[0].replaceAll("\\", "/").includes("/node_modules/");
|
|
69
|
+
}
|
|
70
|
+
function collectExtensionlessImports(ast, code, moduleExtensions) {
|
|
71
|
+
const imports = [];
|
|
72
|
+
function visit(value) {
|
|
73
|
+
if (!isAstRecord(value)) return;
|
|
74
|
+
const parsed = parseExtensionlessImport(value, code, moduleExtensions);
|
|
75
|
+
if (parsed) {
|
|
76
|
+
imports.push(parsed);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
forEachAstChild(value, visit);
|
|
80
|
+
}
|
|
81
|
+
visit(ast);
|
|
82
|
+
return imports;
|
|
83
|
+
}
|
|
84
|
+
function parseExtensionlessImport(node, code, moduleExtensions) {
|
|
85
|
+
if (node.type !== "ImportExpression" || !hasRange(node)) return null;
|
|
86
|
+
if (node.options != null) return null;
|
|
87
|
+
const source = node.source;
|
|
88
|
+
if (!isAstRecord(source) || source.type !== "TemplateLiteral" || !hasRange(source)) return null;
|
|
89
|
+
if (nodeArray(source.expressions).length === 0) return null;
|
|
90
|
+
const quasiTexts = nodeArray(source.quasis).map(templateElementText);
|
|
91
|
+
if (quasiTexts.some((text) => text == null)) return null;
|
|
92
|
+
const texts = quasiTexts;
|
|
93
|
+
const first = texts[0];
|
|
94
|
+
if (!isImportPrefix(code.slice(node.start, source.start))) return null;
|
|
95
|
+
if (!(first.startsWith("./") || first.startsWith("../"))) return null;
|
|
96
|
+
if (texts.some((text) => /[*?[\]{}()!?#]/.test(text))) return null;
|
|
97
|
+
if (texts.slice(1).some((text) => text.includes("."))) return null;
|
|
98
|
+
const directoryEnd = first.lastIndexOf("/") + 1;
|
|
99
|
+
const directory = first.slice(0, directoryEnd);
|
|
100
|
+
const filenamePrefix = first.slice(directoryEnd);
|
|
101
|
+
if (filenamePrefix.includes(".")) return null;
|
|
102
|
+
return {
|
|
103
|
+
start: node.start,
|
|
104
|
+
end: node.end,
|
|
105
|
+
sourceStart: source.start,
|
|
106
|
+
sourceEnd: source.end,
|
|
107
|
+
globPattern: filenamePrefix.length > 0 ? [`${first}*`, `${first}*/**/*`] : `${directory}**/*`,
|
|
108
|
+
moduleExtensions
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function isImportPrefix(value) {
|
|
112
|
+
const prefix = value.match(/^import\s*\(/)?.[0];
|
|
113
|
+
if (!prefix) return false;
|
|
114
|
+
let index = prefix.length;
|
|
115
|
+
while (index < value.length) {
|
|
116
|
+
const char = value[index];
|
|
117
|
+
if (/\s/.test(char)) {
|
|
118
|
+
index += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (value.startsWith("/*", index)) {
|
|
122
|
+
const commentEnd = value.indexOf("*/", index + 2);
|
|
123
|
+
if (commentEnd < 0) return false;
|
|
124
|
+
index = commentEnd + 2;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (value.startsWith("//", index)) {
|
|
128
|
+
const lineEnd = value.indexOf("\n", index + 2);
|
|
129
|
+
if (lineEnd < 0) return true;
|
|
130
|
+
index = lineEnd + 1;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
function templateElementText(value) {
|
|
138
|
+
if (!isAstRecord(value) || value.type !== "TemplateElement") return null;
|
|
139
|
+
const templateValue = value.value;
|
|
140
|
+
if (typeof templateValue !== "object" || templateValue === null) return null;
|
|
141
|
+
const cooked = Reflect.get(templateValue, "cooked");
|
|
142
|
+
return typeof cooked === "string" ? cooked : null;
|
|
143
|
+
}
|
|
144
|
+
function getModuleExtensions(config) {
|
|
145
|
+
return config.resolve.extensions.filter((extension) => extension !== ".node");
|
|
146
|
+
}
|
|
147
|
+
function buildReplacement(source, globPattern, moduleExtensions) {
|
|
148
|
+
const extensions = JSON.stringify(moduleExtensions);
|
|
149
|
+
return `((__vinextPath, __vinextModules = import.meta.glob(${JSON.stringify(globPattern)}), __vinextExtensions = ${extensions}) => { const __vinextLoader = __vinextModules[__vinextPath] ?? __vinextExtensions.map((__vinextExtension) => __vinextModules[__vinextPath + __vinextExtension]).find(Boolean) ?? __vinextExtensions.map((__vinextExtension) => __vinextModules[__vinextPath + "/index" + __vinextExtension]).find(Boolean); return __vinextLoader ? __vinextLoader() : Promise.reject(new Error("Cannot find module '" + __vinextPath + "'")); })(${source})`;
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
export { createExtensionlessDynamicImportPlugin };
|
|
@@ -42,7 +42,7 @@ function createOgInlineFetchAssetsPlugin() {
|
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(
|
|
45
|
+
if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)(?:\.then\(\s*(?:function\s*\([^)]*\)|\([^)]*\)\s*=>)\s*\{?\s*return\s+[^.]+\.arrayBuffer\(\)\s*;?\s*\}?\s*,?\s*\)|\.then\(\s*\([^)]*\)\s*=>\s*[^.]+\.arrayBuffer\(\)\s*,?\s*\))/g)) {
|
|
46
46
|
const fullMatch = match[0];
|
|
47
47
|
const relPath = match[2];
|
|
48
48
|
const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
|
|
@@ -59,7 +59,7 @@ function createOgInlineFetchAssetsPlugin() {
|
|
|
59
59
|
newCode = newCode.replaceAll(fullMatch, inlined);
|
|
60
60
|
didReplace = true;
|
|
61
61
|
}
|
|
62
|
-
if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(
|
|
62
|
+
if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
|
|
63
63
|
const fullMatch = match[0];
|
|
64
64
|
const relPath = match[2];
|
|
65
65
|
const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
|
|
@@ -14,6 +14,7 @@ type BarrelExportMap = Map<string, BarrelExportEntry>;
|
|
|
14
14
|
* @see https://github.com/vercel/next.js/blob/9c31bbdaa/packages/next/src/server/config.ts#L1301
|
|
15
15
|
*/
|
|
16
16
|
declare const DEFAULT_OPTIMIZE_PACKAGES: string[];
|
|
17
|
+
declare function createOptimizedImportSourceMatcher(packages: Iterable<string>): (code: string) => boolean;
|
|
17
18
|
/**
|
|
18
19
|
* Build a map of exported names → source sub-module for a barrel package.
|
|
19
20
|
*
|
|
@@ -21,11 +22,15 @@ declare const DEFAULT_OPTIMIZE_PACKAGES: string[];
|
|
|
21
22
|
* Handles: `export * as X from`, `export { A } from`, `import * as X; export { X }`,
|
|
22
23
|
* and `export * from "./sub"` (recursively resolves wildcard re-exports).
|
|
23
24
|
*
|
|
24
|
-
* Returns null if
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* Returns null if `entryPath` is empty, the file cannot be read, or the file
|
|
26
|
+
* has a parse error. Returns an empty map if the file is valid but exports
|
|
27
|
+
* nothing.
|
|
28
|
+
*
|
|
29
|
+
* @param entryPath - Pre-resolved absolute path to the barrel entry file (the
|
|
30
|
+
* caller owns entry resolution + its caching), or null when it could not be
|
|
31
|
+
* resolved.
|
|
27
32
|
*/
|
|
28
|
-
declare function buildBarrelExportMap(
|
|
33
|
+
declare function buildBarrelExportMap(entryPath: string | null, readFile: (filepath: string) => Promise<string | null>, cache?: Map<string, BarrelExportMap>): Promise<BarrelExportMap | null>;
|
|
29
34
|
/**
|
|
30
35
|
* Creates the vinext:optimize-imports Vite plugin.
|
|
31
36
|
*
|
|
@@ -34,4 +39,4 @@ declare function buildBarrelExportMap(packageName: string, resolveEntry: (pkg: s
|
|
|
34
39
|
*/
|
|
35
40
|
declare function createOptimizeImportsPlugin(getNextConfig: () => ResolvedNextConfig | undefined, getRoot: () => string): Plugin;
|
|
36
41
|
//#endregion
|
|
37
|
-
export { DEFAULT_OPTIMIZE_PACKAGES, buildBarrelExportMap, createOptimizeImportsPlugin };
|
|
42
|
+
export { DEFAULT_OPTIMIZE_PACKAGES, buildBarrelExportMap, createOptimizeImportsPlugin, createOptimizedImportSourceMatcher };
|