vinext 1.1.0 → 1.2.1
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 +22 -10
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- 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 +6 -4
- package/dist/build/prerender.js +1 -1
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/check.js +12 -12
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +3 -2
- 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/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +90 -88
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +3 -0
- package/dist/entries/app-rsc-entry.d.ts +4 -0
- package/dist/entries/app-rsc-entry.js +20 -6
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +246 -136
- 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 +2 -1
- package/dist/init.js +153 -9
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/ast-utils.d.ts +53 -2
- package/dist/plugins/ast-utils.js +90 -2
- package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
- package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
- package/dist/plugins/commonjs-esm-facade.js +2 -2
- package/dist/plugins/css-module-imports.js +13 -20
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +11 -11
- package/dist/plugins/extensionless-dynamic-import.js +2 -3
- package/dist/plugins/fonts.d.ts +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +5 -7
- package/dist/plugins/import-meta-url.js +3 -4
- package/dist/plugins/instrumentation-client.js +3 -2
- package/dist/plugins/middleware-export-validation.js +2 -3
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +3 -4
- package/dist/plugins/remove-console.js +2 -18
- package/dist/plugins/require-condition-resolution.js +3 -3
- package/dist/plugins/require-context.js +2 -3
- 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 +265 -102
- package/dist/plugins/styled-jsx.js +2 -3
- 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.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +84 -35
- package/dist/plugins/worker-image-imports.js +30 -33
- 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 +153 -0
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +3 -2
- package/dist/server/app-action-forwarding.js +2 -2
- 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 +3 -3
- package/dist/server/app-browser-interception-context.js +1 -1
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-prefetch-response.js +2 -2
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +17 -2
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +3 -1
- package/dist/server/app-page-dispatch.js +5 -4
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-render-observation.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.js +53 -15
- package/dist/server/app-page-route-wiring.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +3 -4
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-render-abort-error.d.ts +19 -0
- package/dist/server/app-render-abort-error.js +31 -1
- package/dist/server/app-request-stage-dispatch.js +6 -2
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-stage-entry.js +11 -3
- 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 +5 -2
- 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 +46 -25
- package/dist/server/app-router-entry.js +29 -10
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +30 -13
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +89 -39
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +5 -3
- 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.js +7 -5
- package/dist/server/app-visited-response-cache.js +2 -2
- package/dist/server/app-worker-stages.d.ts +5 -0
- package/dist/server/app-worker-stages.js +1 -1
- package/dist/server/cacheability-request.js +2 -2
- 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 +1 -1
- package/dist/server/defer-until-stream-consumed.d.ts +2 -1
- package/dist/server/defer-until-stream-consumed.js +3 -1
- package/dist/server/dev-server.js +39 -28
- 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 +4 -1
- package/dist/server/headers.js +4 -1
- 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 +38 -0
- package/dist/server/image-optimization.js +94 -4
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +41 -6
- package/dist/server/metadata-route-response.js +11 -10
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +38 -25
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +11 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +6 -5
- 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 +21 -3
- 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 +51 -121
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +189 -127
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +42 -35
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +41 -22
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +75 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +3 -3
- package/dist/server/pages-router-entry.js +5 -4
- 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 +12 -0
- package/dist/server/prod-server.js +204 -74
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +4 -1
- package/dist/server/request-pipeline.js +3 -2
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +52 -5
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +5 -4
- 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 +9 -1
- package/dist/server/socket-error-backstop.js +46 -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 +99 -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-callable-runtime.d.ts +4 -2
- package/dist/shims/cache-callable-runtime.js +21 -12
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-runtime.d.ts +6 -1
- package/dist/shims/cache-runtime.js +2 -1
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +40 -13
- 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/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -67
- package/dist/shims/fetch-cache.js +160 -125
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +16 -14
- package/dist/shims/headers.js +2 -2
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +34 -9
- package/dist/shims/request-context.d.ts +2 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +21 -32
- package/dist/shims/server.d.ts +27 -4
- package/dist/shims/server.js +65 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/url-utils.d.ts +9 -0
- package/dist/shims/url-utils.js +15 -4
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -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 +6 -0
- package/dist/utils/plugin-rsc-version.js +41 -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 +10 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +11 -7
- package/dist/build/nitro-route-rules.d.ts +0 -47
- package/dist/build/nitro-route-rules.js +0 -79
- package/dist/plugins/cache-flight-codec.d.ts +0 -19
- package/dist/plugins/cache-flight-codec.js +0 -68
package/dist/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { detectPackageManager, detectPackageManagerName, detectProject, ensureESModule, findViteConfigPath, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
|
|
3
|
-
import { compactResourceName, cssModulesConfigSource, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
|
|
3
|
+
import { compactResourceName, cssModulesConfigSource, findConfigKeepingWorkerName, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
|
|
4
4
|
import { getReactUpgradeDeps } from "./utils/react-version.js";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -14,7 +14,8 @@ import { spawn, spawnSync } from "node:child_process";
|
|
|
14
14
|
* 2. Add "type": "module" to package.json
|
|
15
15
|
* 3. Rename CJS config files to .cjs
|
|
16
16
|
* 4. Add vinext scripts to package.json
|
|
17
|
-
* 5. Generate vite.config.ts and platform files
|
|
17
|
+
* 5. Generate vite.config.ts and platform files, plus a Tailwind PostCSS
|
|
18
|
+
* config when Tailwind is only set up as a Turbopack loader
|
|
18
19
|
* 6. Update .gitignore to include /dist/ and .vinext/
|
|
19
20
|
* 7. Install dependencies (vite, @vitejs/plugin-react, and App Router deps)
|
|
20
21
|
* 8. Print summary
|
|
@@ -94,6 +95,77 @@ function scanCssModuleFiles(root) {
|
|
|
94
95
|
exclude: (entry) => entry.isDirectory() && (CSS_MODULE_IGNORES.has(entry.name) || toSlash(entry.parentPath) === canonicalRoot && CSS_MODULE_ROOT_IGNORES.has(entry.name))
|
|
95
96
|
}).some((entry) => /\.module\.(css|scss|sass)$/.test(entry.name));
|
|
96
97
|
}
|
|
98
|
+
const NEXT_CONFIG_FILES = [
|
|
99
|
+
"next.config.ts",
|
|
100
|
+
"next.config.mts",
|
|
101
|
+
"next.config.mjs",
|
|
102
|
+
"next.config.js",
|
|
103
|
+
"next.config.cjs"
|
|
104
|
+
];
|
|
105
|
+
const TAILWIND_LOADERS = ["@tailwindcss/turbopack", "@tailwindcss/webpack"];
|
|
106
|
+
const TAILWIND_POSTCSS_CONFIG = `const config = {
|
|
107
|
+
plugins: {
|
|
108
|
+
"@tailwindcss/postcss": {},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export default config;
|
|
113
|
+
`;
|
|
114
|
+
/**
|
|
115
|
+
* Whether the project gets Tailwind from a Turbopack loader (as create-next-app
|
|
116
|
+
* 16.4+ sets up in `turbopack.rules`) rather than from PostCSS, which is the
|
|
117
|
+
* only way vinext compiles Tailwind. The config is not evaluated: a Next config
|
|
118
|
+
* that names the loader, or a declared loader package, is enough.
|
|
119
|
+
*/
|
|
120
|
+
function usesTailwindTurbopackLoader(root) {
|
|
121
|
+
for (const file of NEXT_CONFIG_FILES) {
|
|
122
|
+
const configPath = path.join(root, file);
|
|
123
|
+
if (!fs.existsSync(configPath)) continue;
|
|
124
|
+
const source = fs.readFileSync(configPath, "utf-8");
|
|
125
|
+
if (TAILWIND_LOADERS.some((loader) => source.includes(loader))) return true;
|
|
126
|
+
}
|
|
127
|
+
return TAILWIND_LOADERS.some((loader) => isDepInstalled(root, loader));
|
|
128
|
+
}
|
|
129
|
+
const POSTCSS_CONFIG_SEARCH_ORDER = [
|
|
130
|
+
".postcssrc",
|
|
131
|
+
".postcssrc.json",
|
|
132
|
+
".postcssrc.yaml",
|
|
133
|
+
".postcssrc.yml",
|
|
134
|
+
".postcssrc.ts",
|
|
135
|
+
".postcssrc.cts",
|
|
136
|
+
".postcssrc.mts",
|
|
137
|
+
".postcssrc.js",
|
|
138
|
+
".postcssrc.cjs",
|
|
139
|
+
".postcssrc.mjs",
|
|
140
|
+
"postcss.config.ts",
|
|
141
|
+
"postcss.config.cts",
|
|
142
|
+
"postcss.config.mts",
|
|
143
|
+
"postcss.config.js",
|
|
144
|
+
"postcss.config.cjs",
|
|
145
|
+
"postcss.config.mjs"
|
|
146
|
+
];
|
|
147
|
+
/** The source of the PostCSS config Vite would load, which init never replaces. */
|
|
148
|
+
function readPostcssConfig(root) {
|
|
149
|
+
try {
|
|
150
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
|
|
151
|
+
if (pkg.postcss) return JSON.stringify(pkg.postcss);
|
|
152
|
+
} catch {}
|
|
153
|
+
for (const file of POSTCSS_CONFIG_SEARCH_ORDER) {
|
|
154
|
+
const configPath = path.join(root, file);
|
|
155
|
+
if (!fs.existsSync(configPath)) continue;
|
|
156
|
+
const source = fs.readFileSync(configPath, "utf-8");
|
|
157
|
+
if (source.trim() !== "") return source;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function getTailwindPostcssSetup(root, viteConfigPath) {
|
|
161
|
+
if (!usesTailwindTurbopackLoader(root)) return "none";
|
|
162
|
+
const viteConfig = viteConfigPath ? fs.readFileSync(viteConfigPath, "utf-8") : "";
|
|
163
|
+
const config = /postcss|lightningcss|tailwindcss/.test(viteConfig) ? viteConfig : readPostcssConfig(root);
|
|
164
|
+
if (config === void 0) return "generate";
|
|
165
|
+
if (/lightningcss/.test(config) && !config.includes("@tailwindcss/vite")) return "manual";
|
|
166
|
+
if (config.includes("@tailwindcss/postcss")) return "install";
|
|
167
|
+
return config.includes("tailwindcss") ? "none" : "manual";
|
|
168
|
+
}
|
|
97
169
|
/**
|
|
98
170
|
* Add Vite scripts to package.json without overwriting custom scripts.
|
|
99
171
|
* Exact scripts generated by older vinext versions are migrated in place.
|
|
@@ -123,7 +195,7 @@ function addScripts(root, port, platform = "node", options = {}) {
|
|
|
123
195
|
if (platform === "cloudflare") {
|
|
124
196
|
addScript("deploy", !options.legacyWrangler ? options.warmCdnCache ? "vinext-cloudflare deploy --warm-cache" : "vinext-cloudflare deploy" : options.warmCdnCache ? "vinext-cloudflare deploy --config dist/server/wrangler.json --warm-cache" : "vinext-cloudflare deploy --config dist/server/wrangler.json");
|
|
125
197
|
if (options.deployResponseStore && !pkg.scripts["deploy:response-store"]) {
|
|
126
|
-
pkg.scripts["deploy:response-store"] = !options.legacyWrangler ? `cf deploy --prebuilt --mode production --worker ${compactResourceName(detectProject(root).projectName, "-response-store", 63)}` : "wrangler deploy --config wrangler.response-store.jsonc";
|
|
198
|
+
pkg.scripts["deploy:response-store"] = !options.legacyWrangler ? `cf deploy --prebuilt --mode production --worker ${compactResourceName(options.workerName ?? detectProject(root).projectName, "-response-store", 63)}` : "wrangler deploy --config wrangler.response-store.jsonc";
|
|
127
199
|
added.push("deploy:response-store");
|
|
128
200
|
}
|
|
129
201
|
}
|
|
@@ -133,7 +205,7 @@ function addScripts(root, port, platform = "node", options = {}) {
|
|
|
133
205
|
return [];
|
|
134
206
|
}
|
|
135
207
|
}
|
|
136
|
-
function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false) {
|
|
208
|
+
function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModules = false, tailwindPostcss = false) {
|
|
137
209
|
const dependencies = ["vinext"];
|
|
138
210
|
const devDependencies = ["vite", "@vitejs/plugin-react"];
|
|
139
211
|
if (isAppRouter) {
|
|
@@ -149,6 +221,7 @@ function getInitDependencyGroups(isAppRouter, platform, cloudflare, hasCssModule
|
|
|
149
221
|
} else devDependencies.push("@cloudflare/vite-plugin@1", "wrangler");
|
|
150
222
|
}
|
|
151
223
|
if (hasCssModules) devDependencies.push("vite-css-modules", "postcss");
|
|
224
|
+
if (tailwindPostcss) devDependencies.push("@tailwindcss/postcss");
|
|
152
225
|
return {
|
|
153
226
|
dependencies,
|
|
154
227
|
devDependencies
|
|
@@ -227,7 +300,7 @@ function addDependencyEntries(root, deps, { dev }) {
|
|
|
227
300
|
* Check if react/react-dom need upgrading for react-server-dom-webpack compatibility.
|
|
228
301
|
*
|
|
229
302
|
* react-server-dom-webpack versions are pinned to match their React version
|
|
230
|
-
* (e.g. rsdw@19.
|
|
303
|
+
* (e.g. rsdw@19.3.1 requires react@^19.3.1). When a project has an older
|
|
231
304
|
* React (e.g. create-next-app ships react@19.2.3), we need to upgrade
|
|
232
305
|
* react/react-dom BEFORE installing rsdw to avoid peer-dep conflicts.
|
|
233
306
|
*
|
|
@@ -302,6 +375,64 @@ function updateGitignore(root, platform = "node", legacyWrangler = false) {
|
|
|
302
375
|
fs.writeFileSync(gitignorePath, content + separator + missingEntries.join("\n") + "\n", "utf-8");
|
|
303
376
|
return true;
|
|
304
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Read `output` from the Next.js config as `vinext build` does: an inline
|
|
380
|
+
* `vinext({ nextConfig })` in the Vite config wins over next.config, and both
|
|
381
|
+
* are evaluated with NODE_ENV set to production and `.env.production` loaded as
|
|
382
|
+
* the build loads it. The Vite config is read as written, without running
|
|
383
|
+
* plugin `config` hooks, so a plugin that changes `root`, `envDir` or `mode` is
|
|
384
|
+
* not seen. A config that cannot load here keeps the Worker-first default.
|
|
385
|
+
* The loader is imported lazily because it needs Vite, which create-vinext-app
|
|
386
|
+
* runs without.
|
|
387
|
+
*/
|
|
388
|
+
async function resolvesToStaticExport(root, viteConfigPath) {
|
|
389
|
+
let configModule;
|
|
390
|
+
let dotenvModule;
|
|
391
|
+
try {
|
|
392
|
+
[configModule, dotenvModule] = await Promise.all([import("./config/next-config.js"), import("./config/dotenv.js")]);
|
|
393
|
+
} catch {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
const { findVinextNextConfigInPlugins, loadNextConfig, PHASE_PRODUCTION_BUILD, resolveNextConfigInput } = configModule;
|
|
397
|
+
const savedEnv = { ...process.env };
|
|
398
|
+
Reflect.set(process.env, "NODE_ENV", "production");
|
|
399
|
+
try {
|
|
400
|
+
dotenvModule.loadDotenv({
|
|
401
|
+
root,
|
|
402
|
+
mode: "production"
|
|
403
|
+
});
|
|
404
|
+
let mode = "production";
|
|
405
|
+
let inline = null;
|
|
406
|
+
let configRoot = root;
|
|
407
|
+
let envDir;
|
|
408
|
+
if (viteConfigPath) try {
|
|
409
|
+
const { loadConfigFromFile } = await import("vite");
|
|
410
|
+
const loaded = await loadConfigFromFile({
|
|
411
|
+
command: "build",
|
|
412
|
+
mode: "production",
|
|
413
|
+
isSsrBuild: false,
|
|
414
|
+
isPreview: false
|
|
415
|
+
}, viteConfigPath, root, "silent");
|
|
416
|
+
if (typeof loaded?.config.mode === "string") mode = loaded.config.mode;
|
|
417
|
+
if (typeof loaded?.config.root === "string") configRoot = path.resolve(root, loaded.config.root);
|
|
418
|
+
const configuredEnvDir = loaded?.config.envDir;
|
|
419
|
+
if (configuredEnvDir === false) envDir = false;
|
|
420
|
+
else if (typeof configuredEnvDir === "string") envDir = path.resolve(root, configuredEnvDir);
|
|
421
|
+
inline = await findVinextNextConfigInPlugins(loaded?.config.plugins);
|
|
422
|
+
} catch {}
|
|
423
|
+
if (envDir !== false) dotenvModule.loadDotenv({
|
|
424
|
+
root: envDir ?? configRoot,
|
|
425
|
+
mode
|
|
426
|
+
});
|
|
427
|
+
Reflect.set(process.env, "NODE_ENV", "production");
|
|
428
|
+
return (inline ? await resolveNextConfigInput(inline, PHASE_PRODUCTION_BUILD) : await loadNextConfig(configRoot, PHASE_PRODUCTION_BUILD))?.output === "export";
|
|
429
|
+
} catch {
|
|
430
|
+
return false;
|
|
431
|
+
} finally {
|
|
432
|
+
for (const key of Object.keys(process.env)) if (!Object.hasOwn(savedEnv, key)) delete process.env[key];
|
|
433
|
+
Object.assign(process.env, savedEnv);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
305
436
|
function setupNodePlatform(context) {
|
|
306
437
|
if (context.viteConfigExists && !context.force) {
|
|
307
438
|
if (context.hasCssModules && context.existingViteConfigPath) {
|
|
@@ -387,16 +518,20 @@ async function init(options) {
|
|
|
387
518
|
const viteConfigExists = hasViteConfig(root);
|
|
388
519
|
const isApp = detectProject(root).isAppRouter;
|
|
389
520
|
const hasCssModules = !options.skipCssModules && scanCssModuleFiles(root);
|
|
521
|
+
const tailwindPostcssSetup = getTailwindPostcssSetup(root, platform === "node" && options.force ? void 0 : existingViteConfigPath);
|
|
390
522
|
const pmName = detectPackageManagerName(root);
|
|
391
523
|
const shouldInstall = options.install ?? true;
|
|
524
|
+
const isStaticExport = platform === "cloudflare" && await resolvesToStaticExport(root, existingViteConfigPath);
|
|
392
525
|
if (platform === "cloudflare") validateCloudflarePlatformSetup({
|
|
393
526
|
root,
|
|
394
527
|
isAppRouter: isApp,
|
|
395
528
|
existingViteConfigPath,
|
|
396
529
|
hasCssModules,
|
|
530
|
+
isStaticExport,
|
|
397
531
|
today: options._today
|
|
398
532
|
}, cloudflareOptions);
|
|
399
533
|
else if (hasCssModules && existingViteConfigPath && !options.force) updateViteConfigForCssModules(existingViteConfigPath, fs.readFileSync(existingViteConfigPath, "utf-8"));
|
|
534
|
+
const configKeepingWorkerName = platform === "cloudflare" ? findConfigKeepingWorkerName(root, cloudflareOptions) : void 0;
|
|
400
535
|
if (!options.skipCheck) {
|
|
401
536
|
console.log(" Running compatibility check...\n");
|
|
402
537
|
const { runCheck, formatReport } = await import("./check.js");
|
|
@@ -417,7 +552,8 @@ async function init(options) {
|
|
|
417
552
|
deployResponseStore,
|
|
418
553
|
warmCdnCache: options.cloudflare?.warmCdnCache ?? false,
|
|
419
554
|
legacyWrangler: options.cloudflare?.legacyWrangler,
|
|
420
|
-
scriptNames: options.scriptNames
|
|
555
|
+
scriptNames: options.scriptNames,
|
|
556
|
+
workerName: configKeepingWorkerName ? void 0 : options.cloudflare?.name
|
|
421
557
|
});
|
|
422
558
|
const setupContext = {
|
|
423
559
|
root,
|
|
@@ -428,19 +564,24 @@ async function init(options) {
|
|
|
428
564
|
force: options.force ?? false,
|
|
429
565
|
prerender: options.prerender,
|
|
430
566
|
hasCssModules,
|
|
567
|
+
isStaticExport,
|
|
431
568
|
today: options._today
|
|
432
569
|
};
|
|
433
570
|
const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, cloudflareOptions) : setupNodePlatform(setupContext);
|
|
434
571
|
const { generatedViteConfig, skippedViteConfig, generatedPlatformFiles } = platformSetup;
|
|
572
|
+
if (tailwindPostcssSetup === "generate") fs.writeFileSync(path.join(root, "postcss.config.mjs"), TAILWIND_POSTCSS_CONFIG, "utf-8");
|
|
435
573
|
const updatedGitignore = updateGitignore(root, platform, options.cloudflare?.legacyWrangler);
|
|
436
|
-
const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules);
|
|
574
|
+
const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules, tailwindPostcssSetup === "generate" || tailwindPostcssSetup === "install");
|
|
437
575
|
const missingDependencies = neededDeps.dependencies.filter((dep) => !isDepInstalled(root, dep));
|
|
438
576
|
const missingDevDependencies = neededDeps.devDependencies.filter((dep) => !isDepInstalled(root, dep));
|
|
439
577
|
let dependencyInstallNeedsApproval = false;
|
|
440
578
|
const dependencyEntriesAdded = [];
|
|
441
579
|
const devDependencyEntriesAdded = [];
|
|
442
|
-
if (isApp
|
|
443
|
-
const reactUpgrade = getReactUpgradeDeps(root, {
|
|
580
|
+
if (isApp) {
|
|
581
|
+
const reactUpgrade = shouldInstall ? [.../* @__PURE__ */ new Set([...getReactUpgradeDeps(root), ...getReactUpgradeDeps(root, {
|
|
582
|
+
fromManifest: true,
|
|
583
|
+
installing: true
|
|
584
|
+
})])] : getReactUpgradeDeps(root, { fromManifest: true });
|
|
444
585
|
if (reactUpgrade.length > 0) {
|
|
445
586
|
console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
|
|
446
587
|
console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
|
|
@@ -513,6 +654,9 @@ async function init(options) {
|
|
|
513
654
|
if (skippedViteConfig) console.log(` ${terminalStyle.yellow("-")} Skipped vite.config.ts (already exists, use --force to overwrite)`);
|
|
514
655
|
if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
|
|
515
656
|
if (hasCssModules) console.log(` ${terminalStyle.green("✓")} Configured vite-css-modules for CSS Modules`);
|
|
657
|
+
if (tailwindPostcssSetup === "generate") console.log(` ${terminalStyle.green("✓")} Generated postcss.config.mjs for Tailwind CSS (vinext does not run turbopack.rules loaders)`);
|
|
658
|
+
else if (tailwindPostcssSetup === "manual") console.log(` ${terminalStyle.yellow("!")} Tailwind CSS is set up as a Turbopack loader, which vinext does not run; set up "@tailwindcss/postcss" or "@tailwindcss/vite" for vinext`);
|
|
659
|
+
if (configKeepingWorkerName) console.log(` ${terminalStyle.yellow("!")} Kept the Worker name in the existing ${configKeepingWorkerName}; --name was not applied, so update it there if it should be "${cloudflareOptions.name}"`);
|
|
516
660
|
if (platformSetup.preservedExistingGenerateScopedName) console.log(` ${terminalStyle.yellow("!")} Preserved existing css.modules.generateScopedName; verify it produces identical class names in SSR and client builds`);
|
|
517
661
|
const nextSteps = [...platformSetup.nextSteps];
|
|
518
662
|
if (dependencyInstallNeedsApproval) nextSteps.push("Dependency installation is incomplete because pnpm blocked dependency build scripts:", "1. Review and approve the required build scripts:", " pnpm approve-builds", "2. Finish installing dependencies:", " pnpm install");
|
|
@@ -11,4 +11,11 @@ export declare function collectDirectScopeBindings(node: ESTree.Node, scope: Ast
|
|
|
11
11
|
export declare function collectLoopScopeBindings(node: ESTree.ForStatement | ESTree.ForInStatement | ESTree.ForOfStatement, scope: AstScope, onVariableDeclarator?: (declaration: ESTree.VariableDeclaration, declarator: ESTree.VariableDeclarator) => void): void;
|
|
12
12
|
export declare function collectSwitchScopeBindings(node: ESTree.SwitchStatement, scope: AstScope, onVariableDeclarator?: (declaration: ESTree.VariableDeclaration, declarator: ESTree.VariableDeclarator) => void): void;
|
|
13
13
|
export declare function collectVarScopeBindings(node: ESTree.Node, scope: AstScope, root?: boolean): void;
|
|
14
|
+
/** The nearest scope declaring `name`, or `null` for an unbound (global) name. */
|
|
15
|
+
export declare function findAstBindingScope(scope: AstScope, name: string): AstScope | null;
|
|
16
|
+
/**
|
|
17
|
+
* Visit every node with the scope it is evaluated in. The root scope holds the
|
|
18
|
+
* program's own bindings, including every `var` outside a function.
|
|
19
|
+
*/
|
|
20
|
+
export declare function walkAstScopes(root: ESTree.Program, visitor: (node: ESTree.Node, scope: AstScope) => void): AstScope;
|
|
14
21
|
//#endregion
|
|
@@ -23,7 +23,7 @@ function collectDirectScopeBindings(node, scope, onVariableDeclarator) {
|
|
|
23
23
|
for (const specifier of declaration.specifiers) if (specifier.type !== "ImportSpecifier" || specifier.importKind !== "type") collectBindingNames(specifier.local, scope.bindings);
|
|
24
24
|
} else if (declaration.type === "TSImportEqualsDeclaration" && declaration.importKind !== "type") collectBindingNames(declaration.id, scope.bindings);
|
|
25
25
|
else if (declaration.type === "VariableDeclaration" && declaration.declare !== true) for (const declarator of declaration.declarations) {
|
|
26
|
-
collectBindingNames(declarator.id, scope.bindings);
|
|
26
|
+
if (declaration.kind !== "var") collectBindingNames(declarator.id, scope.bindings);
|
|
27
27
|
onVariableDeclarator?.(declaration, declarator);
|
|
28
28
|
}
|
|
29
29
|
else if ((declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") && declaration.declare !== true) collectBindingNames(declaration.id, scope.bindings);
|
|
@@ -34,7 +34,7 @@ function collectLoopScopeBindings(node, scope, onVariableDeclarator) {
|
|
|
34
34
|
const declarationValue = node.type === "ForStatement" ? node.init : node.left;
|
|
35
35
|
if (!declarationValue || declarationValue.type !== "VariableDeclaration" || declarationValue.declare === true) return;
|
|
36
36
|
for (const declarator of declarationValue.declarations) {
|
|
37
|
-
collectBindingNames(declarator.id, scope.bindings);
|
|
37
|
+
if (declarationValue.kind !== "var") collectBindingNames(declarator.id, scope.bindings);
|
|
38
38
|
onVariableDeclarator?.(declarationValue, declarator);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -46,5 +46,61 @@ function collectVarScopeBindings(node, scope, root = true) {
|
|
|
46
46
|
if (node.type === "VariableDeclaration" && node.kind === "var" && node.declare !== true) for (const declarator of node.declarations) collectBindingNames(declarator.id, scope.bindings);
|
|
47
47
|
forEachAstChild(node, (child) => collectVarScopeBindings(child, scope, false));
|
|
48
48
|
}
|
|
49
|
+
/** The nearest scope declaring `name`, or `null` for an unbound (global) name. */
|
|
50
|
+
function findAstBindingScope(scope, name) {
|
|
51
|
+
for (let current = scope; current; current = current.parent) if (current.bindings.has(name)) return current;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Visit every node with the scope it is evaluated in. The root scope holds the
|
|
56
|
+
* program's own bindings, including every `var` outside a function.
|
|
57
|
+
*/
|
|
58
|
+
function walkAstScopes(root, visitor) {
|
|
59
|
+
const rootScope = createAstScope(null);
|
|
60
|
+
collectDirectScopeBindings(root, rootScope);
|
|
61
|
+
collectVarScopeBindings(root, rootScope);
|
|
62
|
+
function visit(node, parentScope) {
|
|
63
|
+
visitor(node, parentScope);
|
|
64
|
+
let scope = parentScope;
|
|
65
|
+
if (isFunctionNode(node)) {
|
|
66
|
+
const parameterScope = createAstScope(parentScope);
|
|
67
|
+
if (node.type === "FunctionExpression") collectBindingNames(node.id, parameterScope.bindings);
|
|
68
|
+
for (const parameter of node.params) collectBindingNames(parameter, parameterScope.bindings);
|
|
69
|
+
if (node.id) visit(node.id, node.type === "FunctionExpression" ? parameterScope : parentScope);
|
|
70
|
+
for (const parameter of node.params) visit(parameter, parameterScope);
|
|
71
|
+
if (!node.body) return;
|
|
72
|
+
const bodyScope = createAstScope(parameterScope);
|
|
73
|
+
collectDirectScopeBindings(node.body, bodyScope);
|
|
74
|
+
collectVarScopeBindings(node.body, bodyScope);
|
|
75
|
+
if (node.body.type === "BlockStatement") for (const statement of node.body.body) visit(statement, bodyScope);
|
|
76
|
+
else visit(node.body, bodyScope);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (node.type === "SwitchStatement") {
|
|
80
|
+
visit(node.discriminant, parentScope);
|
|
81
|
+
const switchScope = createAstScope(parentScope);
|
|
82
|
+
collectSwitchScopeBindings(node, switchScope);
|
|
83
|
+
for (const switchCase of node.cases) visit(switchCase, switchScope);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (node.type === "BlockStatement" || node.type === "StaticBlock" || node.type === "TSModuleBlock") {
|
|
87
|
+
scope = createAstScope(parentScope);
|
|
88
|
+
collectDirectScopeBindings(node, scope);
|
|
89
|
+
if (node.type === "StaticBlock" || node.type === "TSModuleBlock") collectVarScopeBindings(node, scope);
|
|
90
|
+
} else if (node.type === "CatchClause") {
|
|
91
|
+
scope = createAstScope(parentScope);
|
|
92
|
+
collectBindingNames(node.param, scope.bindings);
|
|
93
|
+
} else if (node.type === "ForStatement" || node.type === "ForInStatement" || node.type === "ForOfStatement") {
|
|
94
|
+
scope = createAstScope(parentScope);
|
|
95
|
+
collectLoopScopeBindings(node, scope);
|
|
96
|
+
} else if (node.type === "ClassExpression" && node.id) {
|
|
97
|
+
scope = createAstScope(parentScope);
|
|
98
|
+
collectBindingNames(node.id, scope.bindings);
|
|
99
|
+
}
|
|
100
|
+
forEachAstChild(node, (child) => visit(child, scope));
|
|
101
|
+
}
|
|
102
|
+
for (const statement of root.body) visit(statement, rootScope);
|
|
103
|
+
return rootScope;
|
|
104
|
+
}
|
|
49
105
|
//#endregion
|
|
50
|
-
export { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, createAstScope, hasAstBinding, isFunctionNode };
|
|
106
|
+
export { collectDirectScopeBindings, collectLoopScopeBindings, collectSwitchScopeBindings, collectVarScopeBindings, createAstScope, findAstBindingScope, hasAstBinding, isFunctionNode, walkAstScopes };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ESTree } from "vite";
|
|
1
|
+
import { ESTree, ParseResult, ParserOptions } from "vite";
|
|
2
2
|
//#region src/plugins/ast-utils.d.ts
|
|
3
3
|
export type ScriptParserLanguage = "js" | "jsx" | "ts" | "tsx";
|
|
4
4
|
export declare const SCRIPT_MODULE_ID_RE: RegExp;
|
|
@@ -8,7 +8,7 @@ export declare const SCRIPT_MODULE_ID_RE: RegExp;
|
|
|
8
8
|
* Static imports — `import x from "..."`, `import { ... } from "..."`,
|
|
9
9
|
* `import "..."` — never place a `(` (nor a comment leading to one) immediately
|
|
10
10
|
* after the `import` keyword. Plugins that act only on dynamic `import(...)` use
|
|
11
|
-
* this to skip
|
|
11
|
+
* this to skip parsing for the overwhelming majority of modules in a large
|
|
12
12
|
* app: at ~5k routes, where almost every module is a static-import-only page,
|
|
13
13
|
* it removes most of the build's AST-parse/GC cost. This is a deliberate,
|
|
14
14
|
* measured performance filter — keep it a regex, never a parse.
|
|
@@ -36,6 +36,57 @@ export declare function mayContainDynamicImport(code: string): boolean;
|
|
|
36
36
|
* necessarily been lowered.
|
|
37
37
|
*/
|
|
38
38
|
export declare function scriptParserLanguage(id: string): ScriptParserLanguage | null;
|
|
39
|
+
/** The import/export record oxc builds alongside the AST. */
|
|
40
|
+
export type ModuleRecord = ParseResult["module"];
|
|
41
|
+
/**
|
|
42
|
+
* Parse `code` into an ESTree program, throwing on syntax errors.
|
|
43
|
+
*
|
|
44
|
+
* Replaces Vite's deprecated `parseAst` with the same defaults and contract.
|
|
45
|
+
* Callers that only need import/export declarations should use
|
|
46
|
+
* {@link parseModuleRecord}, which skips building the JS AST.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseProgram(code: string, options?: ParserOptions): ESTree.Program;
|
|
49
|
+
/** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
|
|
50
|
+
export declare function parseProgramAsync(code: string, options?: ParserOptions): Promise<ESTree.Program>;
|
|
51
|
+
/**
|
|
52
|
+
* Parse `code` and return only its static import/export and dynamic import
|
|
53
|
+
* record, or `null` when it has syntax errors.
|
|
54
|
+
*
|
|
55
|
+
* Reading the record never deserializes the JS AST, which is most of the cost
|
|
56
|
+
* of a parse (about 4x cheaper than {@link parseProgram} on large modules).
|
|
57
|
+
* The record omits import attributes; see {@link hasImportAttributes}.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseModuleRecord(code: string, lang: ParserOptions["lang"]): ModuleRecord | null;
|
|
60
|
+
/**
|
|
61
|
+
* One whitespace character or comment. Each alternative can only match one
|
|
62
|
+
* way (a block comment stops at the first `*\/`, a line comment runs to the
|
|
63
|
+
* line end), so repeating it cannot backtrack exponentially.
|
|
64
|
+
*/
|
|
65
|
+
export declare const TRIVIA_PATTERN: string;
|
|
66
|
+
/** Leading whitespace and comments. */
|
|
67
|
+
export declare const LEADING_TRIVIA_RE: RegExp;
|
|
68
|
+
/**
|
|
69
|
+
* Whether the static import/export statement ending at `statementEnd` has
|
|
70
|
+
* `with { ... }` (or legacy `assert { ... }`) attributes after its source
|
|
71
|
+
* string, which ends at `sourceEnd`. The module record does not report
|
|
72
|
+
* attributes.
|
|
73
|
+
*/
|
|
74
|
+
export declare function hasImportAttributes(code: string, sourceEnd: number, statementEnd: number): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Whether a static import is erased by TypeScript: every binding is
|
|
77
|
+
* type-only, or it is `import type {} from "x"`, which the module record
|
|
78
|
+
* reports with no entries (like a runtime `import {} from "x"`).
|
|
79
|
+
*/
|
|
80
|
+
export declare function isTypeOnlyImport(code: string, statement: ModuleRecord["staticImports"][number]): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* The value of the string literal or expression-free template literal spanning
|
|
83
|
+
* `span`, or `null` for any other expression. The module record gives only the
|
|
84
|
+
* span of a dynamic import's source.
|
|
85
|
+
*/
|
|
86
|
+
export declare function quotedStringAt(code: string, span: {
|
|
87
|
+
start: number;
|
|
88
|
+
end: number;
|
|
89
|
+
}): string | null;
|
|
39
90
|
export declare function isIdentifierNamed(value: ESTree.Node | null | undefined, name: string): boolean;
|
|
40
91
|
export declare function getAstName(node: ESTree.Node | null | undefined): string | null;
|
|
41
92
|
/** Remove syntax-only wrappers while preserving the underlying expression. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parse, parseSync } from "vite";
|
|
1
2
|
//#region src/plugins/ast-utils.ts
|
|
2
3
|
const SCRIPT_MODULE_EXTENSION_RE = /^\.(?:[cm]?[jt]s|[jt]sx)$/i;
|
|
3
4
|
const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
|
|
@@ -7,7 +8,7 @@ const SCRIPT_MODULE_ID_RE = /\.(?:[cm]?[jt]s|[jt]sx)(?:[?#].*)?$/i;
|
|
|
7
8
|
* Static imports — `import x from "..."`, `import { ... } from "..."`,
|
|
8
9
|
* `import "..."` — never place a `(` (nor a comment leading to one) immediately
|
|
9
10
|
* after the `import` keyword. Plugins that act only on dynamic `import(...)` use
|
|
10
|
-
* this to skip
|
|
11
|
+
* this to skip parsing for the overwhelming majority of modules in a large
|
|
11
12
|
* app: at ~5k routes, where almost every module is a static-import-only page,
|
|
12
13
|
* it removes most of the build's AST-parse/GC cost. This is a deliberate,
|
|
13
14
|
* measured performance filter — keep it a regex, never a parse.
|
|
@@ -46,6 +47,93 @@ function scriptParserLanguage(id) {
|
|
|
46
47
|
if (extension === ".tsx") return "tsx";
|
|
47
48
|
return "jsx";
|
|
48
49
|
}
|
|
50
|
+
const PROGRAM_PARSER_DEFAULTS = {
|
|
51
|
+
lang: "js",
|
|
52
|
+
preserveParens: false
|
|
53
|
+
};
|
|
54
|
+
const PARSE_FILENAME = "file.js";
|
|
55
|
+
function programOrThrow(result) {
|
|
56
|
+
if (result.errors.length > 0) {
|
|
57
|
+
const frames = result.errors.slice(0, 5).map((error) => error.codeframe ?? error.message);
|
|
58
|
+
throw new SyntaxError(`Parse failed with ${result.errors.length} error${result.errors.length === 1 ? "" : "s"}:\n${frames.join("\n")}`);
|
|
59
|
+
}
|
|
60
|
+
return result.program;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parse `code` into an ESTree program, throwing on syntax errors.
|
|
64
|
+
*
|
|
65
|
+
* Replaces Vite's deprecated `parseAst` with the same defaults and contract.
|
|
66
|
+
* Callers that only need import/export declarations should use
|
|
67
|
+
* {@link parseModuleRecord}, which skips building the JS AST.
|
|
68
|
+
*/
|
|
69
|
+
function parseProgram(code, options) {
|
|
70
|
+
return programOrThrow(parseSync(PARSE_FILENAME, code, {
|
|
71
|
+
...PROGRAM_PARSER_DEFAULTS,
|
|
72
|
+
...options
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
/** Async {@link parseProgram}; replaces Vite's deprecated `parseAstAsync`. */
|
|
76
|
+
async function parseProgramAsync(code, options) {
|
|
77
|
+
return programOrThrow(await parse(PARSE_FILENAME, code, {
|
|
78
|
+
...PROGRAM_PARSER_DEFAULTS,
|
|
79
|
+
...options
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse `code` and return only its static import/export and dynamic import
|
|
84
|
+
* record, or `null` when it has syntax errors.
|
|
85
|
+
*
|
|
86
|
+
* Reading the record never deserializes the JS AST, which is most of the cost
|
|
87
|
+
* of a parse (about 4x cheaper than {@link parseProgram} on large modules).
|
|
88
|
+
* The record omits import attributes; see {@link hasImportAttributes}.
|
|
89
|
+
*/
|
|
90
|
+
function parseModuleRecord(code, lang) {
|
|
91
|
+
const result = parseSync(PARSE_FILENAME, code, { lang });
|
|
92
|
+
return result.errors.length > 0 ? null : result.module;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* One whitespace character or comment. Each alternative can only match one
|
|
96
|
+
* way (a block comment stops at the first `*\/`, a line comment runs to the
|
|
97
|
+
* line end), so repeating it cannot backtrack exponentially.
|
|
98
|
+
*/
|
|
99
|
+
const TRIVIA_PATTERN = String.raw`(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/|\/\/[^\n\r\u2028\u2029]*(?![^\n\r\u2028\u2029]))`;
|
|
100
|
+
/** Leading whitespace and comments. */
|
|
101
|
+
const LEADING_TRIVIA_RE = new RegExp(`^${TRIVIA_PATTERN}*`);
|
|
102
|
+
/**
|
|
103
|
+
* Whether the static import/export statement ending at `statementEnd` has
|
|
104
|
+
* `with { ... }` (or legacy `assert { ... }`) attributes after its source
|
|
105
|
+
* string, which ends at `sourceEnd`. The module record does not report
|
|
106
|
+
* attributes.
|
|
107
|
+
*/
|
|
108
|
+
function hasImportAttributes(code, sourceEnd, statementEnd) {
|
|
109
|
+
const afterSource = code.slice(sourceEnd, statementEnd);
|
|
110
|
+
const triviaLength = LEADING_TRIVIA_RE.exec(afterSource)?.[0].length ?? 0;
|
|
111
|
+
return /^(?:with|assert)\b/.test(afterSource.slice(triviaLength));
|
|
112
|
+
}
|
|
113
|
+
const EMPTY_TYPE_IMPORT_RE = new RegExp(String.raw`^import${TRIVIA_PATTERN}*type${TRIVIA_PATTERN}*\{`);
|
|
114
|
+
/**
|
|
115
|
+
* Whether a static import is erased by TypeScript: every binding is
|
|
116
|
+
* type-only, or it is `import type {} from "x"`, which the module record
|
|
117
|
+
* reports with no entries (like a runtime `import {} from "x"`).
|
|
118
|
+
*/
|
|
119
|
+
function isTypeOnlyImport(code, statement) {
|
|
120
|
+
if (statement.entries.length > 0) return statement.entries.every((entry) => entry.isType);
|
|
121
|
+
return EMPTY_TYPE_IMPORT_RE.test(code.slice(statement.start, statement.moduleRequest.start));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The value of the string literal or expression-free template literal spanning
|
|
125
|
+
* `span`, or `null` for any other expression. The module record gives only the
|
|
126
|
+
* span of a dynamic import's source.
|
|
127
|
+
*/
|
|
128
|
+
function quotedStringAt(code, span) {
|
|
129
|
+
const text = code.slice(span.start, span.end);
|
|
130
|
+
const match = /^(?:"([^"\\\r\n]*)"|'([^'\\\r\n]*)'|`([^`\\$]*)`)$/.exec(text);
|
|
131
|
+
if (match) return match[1] ?? match[2] ?? match[3];
|
|
132
|
+
if (!/^["'`]/.test(text)) return null;
|
|
133
|
+
const result = parseSync(PARSE_FILENAME, `(${text})`, PROGRAM_PARSER_DEFAULTS);
|
|
134
|
+
const statement = result.errors.length > 0 ? void 0 : result.program.body[0];
|
|
135
|
+
return statement?.type === "ExpressionStatement" ? staticStringValue(statement.expression) : null;
|
|
136
|
+
}
|
|
49
137
|
const SKIP_CHILD_KEYS = /* @__PURE__ */ new Set([
|
|
50
138
|
"type",
|
|
51
139
|
"parent",
|
|
@@ -137,4 +225,4 @@ function collectBindingNames(node, target) {
|
|
|
137
225
|
}
|
|
138
226
|
}
|
|
139
227
|
//#endregion
|
|
140
|
-
export { DYNAMIC_IMPORT_PRESCAN, SCRIPT_MODULE_ID_RE, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, isIdentifierNamed, mayContainDynamicImport, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
|
|
228
|
+
export { DYNAMIC_IMPORT_PRESCAN, LEADING_TRIVIA_RE, SCRIPT_MODULE_ID_RE, TRIVIA_PATTERN, booleanLiteralValue, collectBindingNames, forEachAstChild, getAstName, hasImportAttributes, isIdentifierNamed, isTypeOnlyImport, mayContainDynamicImport, parseModuleRecord, parseProgram, parseProgramAsync, quotedStringAt, scriptParserLanguage, staticStringValue, stringLiteralValue, unwrapExpression, walkAst };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
//#region src/plugins/cloudflare-dev-module-urls.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Vite's internal middlewares that serve module requests (`/@vite/client`,
|
|
5
|
+
* `/@id/*`, JS and CSS source files) and `/@fs/*` paths, preceded by the one
|
|
6
|
+
* that strips a non-root `base` from the URL and the one that answers the HMR
|
|
7
|
+
* client's reconnect ping (`Accept: text/x-vite-ping`) with a 204 instead of
|
|
8
|
+
* the Worker rendering a page for it. If Vite renames them, none are found and
|
|
9
|
+
* every request falls through, which is the behavior without this plugin.
|
|
10
|
+
*
|
|
11
|
+
* `viteServePublicMiddleware` is deliberately excluded so that `public/` files
|
|
12
|
+
* reach the Worker and middleware, as they do in production. Without it, the
|
|
13
|
+
* transform middleware reports a public `.js` or `.css` file as an
|
|
14
|
+
* `ERR_LOAD_PUBLIC_URL` error, which is treated as a fall-through.
|
|
15
|
+
*/
|
|
16
|
+
export declare const VITE_MODULE_MIDDLEWARE_NAMES: Set<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Vite's internal middleware that serves files under the project root. Vite
|
|
19
|
+
* gives imported assets root-relative URLs (`import logo from "./logo.svg"`
|
|
20
|
+
* and CSS `url(./bg.png)` both resolve to paths like `/app/logo.svg`), and only
|
|
21
|
+
* this middleware serves them. It also serves every other project file, and a
|
|
22
|
+
* Worker route can share its path with one (e.g. an `api/` directory and an
|
|
23
|
+
* `/api/*` route handler), so it only runs for referenced assets. See
|
|
24
|
+
* `isReferencedAsset`. Navigations to a referenced asset
|
|
25
|
+
* are served too: in production its URL is under `/_next/static/`, which never
|
|
26
|
+
* reaches the Worker.
|
|
27
|
+
*/
|
|
28
|
+
export declare const VITE_STATIC_MIDDLEWARE_NAME = "viteServeStaticMiddleware";
|
|
29
|
+
type CloudflareDevModuleUrlsOptions = {
|
|
30
|
+
/** Whether the Cloudflare Vite plugin is present. Read when the dev server starts. */
|
|
31
|
+
isEnabled: () => boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Creates the plugin that lets Vite serve its module URLs before the Cloudflare
|
|
35
|
+
* plugin's `runWorkerFirst` routing in dev.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Plugin options
|
|
38
|
+
* @returns The Vite plugin
|
|
39
|
+
*/
|
|
40
|
+
export declare function createCloudflareDevModuleUrlsPlugin(options: CloudflareDevModuleUrlsOptions): Plugin;
|
|
41
|
+
//#endregion
|