vinext 1.2.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 +1 -1
- package/dist/build/output-root-externals.d.ts +21 -0
- package/dist/build/output-root-externals.js +40 -0
- package/dist/build/prerender-paths.js +1 -1
- package/dist/build/prerender.js +1 -1
- package/dist/check.js +5 -6
- package/dist/cli-dev-config.js +3 -3
- package/dist/cli.js +1 -1
- package/dist/config/config-matchers.js +12 -7
- package/dist/index.js +113 -94
- package/dist/init.d.ts +1 -1
- package/dist/init.js +86 -6
- 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.js +2 -3
- 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.js +2 -3
- 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/og-harfbuzz.js +2 -3
- package/dist/plugins/optimize-imports.js +3 -4
- package/dist/plugins/pages-node-externals.js +2 -3
- 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/strip-server-exports.js +3 -4
- package/dist/plugins/styled-jsx.js +2 -3
- package/dist/plugins/use-cache-callable.d.ts +21 -2
- package/dist/plugins/use-cache-callable.js +76 -33
- package/dist/plugins/worker-image-imports.js +30 -33
- package/dist/plugins/worker-use-server.js +38 -14
- package/dist/server/api-handler.js +1 -1
- package/dist/server/app-action-forwarding.js +2 -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-prefetch-response.js +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-supplemental-refresh.js +1 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-dispatch.js +1 -1
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-pages-bridge.js +1 -1
- package/dist/server/app-prerender-endpoints.js +1 -1
- 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-independent-entry.js +5 -5
- package/dist/server/app-response-stage-entry.js +2 -2
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-router-entry.js +5 -5
- package/dist/server/app-rsc-cache-busting.d.ts +16 -0
- package/dist/server/app-rsc-cache-busting.js +29 -12
- package/dist/server/app-rsc-handler.js +5 -5
- package/dist/server/app-rsc-request-normalization.js +3 -3
- package/dist/server/app-rsc-response-stage.js +2 -2
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.js +5 -4
- package/dist/server/app-visited-response-cache.js +2 -2
- 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 +1 -1
- package/dist/server/image-optimization.js +1 -0
- package/dist/server/metadata-route-response.js +2 -2
- package/dist/server/middleware-path-to-regexp.js +1 -1
- package/dist/server/middleware-runtime.js +5 -5
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/open-redirect.d.ts +11 -4
- package/dist/server/open-redirect.js +11 -4
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-data-route.js +2 -1
- package/dist/server/pages-page-data.js +1 -1
- package/dist/server/pages-page-handler.js +1 -1
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-request-pipeline.js +5 -5
- package/dist/server/pages-request-stage-entry.js +4 -4
- package/dist/server/pages-revalidate.js +2 -2
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.js +5 -5
- package/dist/server/rsc-stream-hints.d.ts +1 -1
- package/dist/server/rsc-stream-hints.js +21 -3
- package/dist/server/worker-image-optimization.js +19 -6
- package/dist/shims/head.js +1 -1
- package/dist/shims/headers.js +2 -2
- 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/link-prefetch.js +5 -4
- package/dist/shims/link.js +2 -2
- package/dist/shims/navigation.js +4 -5
- package/dist/shims/router.js +9 -12
- package/dist/shims/server.d.ts +11 -4
- package/dist/shims/server.js +41 -5
- package/dist/shims/url-utils.d.ts +7 -0
- package/dist/shims/url-utils.js +12 -3
- package/dist/utils/domain-locale.js +1 -1
- package/dist/utils/plugin-rsc-version.d.ts +2 -0
- package/dist/utils/plugin-rsc-version.js +28 -2
- package/dist/utils/react-version.d.ts +7 -0
- package/dist/utils/react-version.js +39 -16
- package/package.json +6 -6
- 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/index.js
CHANGED
|
@@ -2,31 +2,32 @@ import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/
|
|
|
2
2
|
import { detectPackageManager, formatMissingCloudflarePluginError, hasWranglerConfig } from "./utils/project.js";
|
|
3
3
|
import { buildViteResolveExtensions, createValidFileMatcher, findFileWithExts, normalizeViteResolveExtensions } from "./routing/file-matcher.js";
|
|
4
4
|
import { resolvePostcssStringPlugins } from "./plugins/postcss.js";
|
|
5
|
+
import { TRIVIA_PATTERN, hasImportAttributes, isTypeOnlyImport, parseModuleRecord, parseProgram } from "./plugins/ast-utils.js";
|
|
5
6
|
import { claimViteCliBuildInvocation, getViteCliInvocation, isViteCliConfigFile } from "./utils/vite-cli-invocation.js";
|
|
6
7
|
import { VINEXT_DEV_CLI_LIFECYCLE, applyDevServerDefaults, claimViteCliDevInvocation, createDevServerLifecyclePlugin, reserveViteCliDevInvocation } from "./cli-dev-config.js";
|
|
7
8
|
import { isUnknownRecord } from "./utils/record.js";
|
|
8
|
-
import { getReactUpgradeDeps } from "./utils/react-version.js";
|
|
9
|
+
import { getReactUpgradeDeps, reactUpgradeRequiredMessage } from "./utils/react-version.js";
|
|
9
10
|
import { loadDotenv } from "./config/dotenv.js";
|
|
10
11
|
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
|
|
11
12
|
import { VINEXT_MW_CTX_HEADER } from "./utils/protocol-headers.js";
|
|
12
13
|
import { encodeMiddlewareRequestHeaders } from "./utils/middleware-request-headers.js";
|
|
14
|
+
import { hasBasePath, stripBasePath } from "./utils/base-path.js";
|
|
15
|
+
import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_TIMING_HEADER } from "./server/headers.js";
|
|
16
|
+
import { methodNotAllowedResponse, notFoundStaticAssetResponse } from "./server/http-error-responses.js";
|
|
17
|
+
import { isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./server/open-redirect.js";
|
|
18
|
+
import { canonicalizeRequestUrlPathname, filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
|
|
13
19
|
import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matchers.js";
|
|
14
20
|
import { omitUnusedBuildSourcemap } from "./plugins/transform-result.js";
|
|
15
21
|
import { assetPrefixPathname, isNextStaticPath, resolveAssetsDir } from "./utils/asset-prefix.js";
|
|
16
22
|
import { RESOLVED_VIRTUAL_GOOGLE_FONTS, VIRTUAL_GOOGLE_FONTS, createGoogleFontsPlugin, createLocalFontsPlugin, generateGoogleFontsVirtualModule, parseStaticObjectLiteral } from "./plugins/fonts.js";
|
|
17
23
|
import { VINEXT_NEXT_CONFIG_PLUGIN_PROPERTY, createRscCompatibilityId, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
|
|
18
24
|
import { normalizePathnameForRouteMatch, normalizePathnameForRouteMatchStrict } from "./routing/utils.js";
|
|
19
|
-
import { hasBasePath, stripBasePath } from "./utils/base-path.js";
|
|
20
25
|
import { appRouteGraph, appRouter, invalidateAppRouteCache, matchAppRoute } from "./routing/app-router.js";
|
|
21
26
|
import { generateRouteTypes } from "./typegen.js";
|
|
22
27
|
import { apiRouter, invalidateRouteCache, matchRoute, pagesRouter } from "./routing/pages-router.js";
|
|
23
28
|
import { resolveRuntimeEntryModule } from "./entries/runtime-entry-module.js";
|
|
24
|
-
import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_TIMING_HEADER } from "./server/headers.js";
|
|
25
29
|
import { normalizePath as normalizePath$1 } from "./server/normalize-path.js";
|
|
26
30
|
import { validateMiddlewareMatcherPatterns } from "./server/middleware-matcher-pattern.js";
|
|
27
|
-
import { methodNotAllowedResponse, notFoundStaticAssetResponse } from "./server/http-error-responses.js";
|
|
28
|
-
import { isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./server/open-redirect.js";
|
|
29
|
-
import { canonicalizeRequestUrlPathname, filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
|
|
30
31
|
import { resolvePagesI18nRequest, stripI18nLocaleForApiRoute } from "./server/pages-i18n.js";
|
|
31
32
|
import { encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./server/pages-data-route.js";
|
|
32
33
|
import { findInstrumentationClientFile, findInstrumentationFile, runInstrumentation } from "./server/instrumentation.js";
|
|
@@ -43,6 +44,7 @@ import { handleApiRoute } from "./server/api-handler.js";
|
|
|
43
44
|
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, resolveDevImageRedirect } from "./server/image-optimization.js";
|
|
44
45
|
import { CACHEABILITY_MANIFEST_MODULE, CACHEABILITY_REQUEST_PROJECTION_MODULE } from "./server/cacheability-manifest.js";
|
|
45
46
|
import { PREGENERATED_CONCRETE_PATHS_MODULE } from "./server/pregenerated-concrete-paths.js";
|
|
47
|
+
import { rewriteOutputRootExternals } from "./build/output-root-externals.js";
|
|
46
48
|
import { installSocketErrorBackstop } from "./server/socket-error-backstop.js";
|
|
47
49
|
import { invalidateMetadataFileCache, scanMetadataFiles } from "./server/metadata-routes.js";
|
|
48
50
|
import { shouldInvalidateAppRouteFile } from "./server/dev-route-files.js";
|
|
@@ -90,6 +92,7 @@ import { INSTRUMENTATION_CLIENT_EMPTY_MODULE, generateInstrumentationClientInjec
|
|
|
90
92
|
import { isServerEnvironment } from "./plugins/environment.js";
|
|
91
93
|
import { createMiddlewareServerOnlyPlugin } from "./plugins/middleware-server-only.js";
|
|
92
94
|
import { createPagesNodeExternalsPlugin } from "./plugins/pages-node-externals.js";
|
|
95
|
+
import { createCloudflareDevModuleUrlsPlugin } from "./plugins/cloudflare-dev-module-urls.js";
|
|
93
96
|
import { validateMiddlewareModuleExports } from "./plugins/middleware-export-validation.js";
|
|
94
97
|
import { createOptimizeImportsPlugin } from "./plugins/optimize-imports.js";
|
|
95
98
|
import { augmentSsrManifestFromBundle, relativeWithinRoot, tryRealpathSync } from "./build/ssr-manifest.js";
|
|
@@ -98,7 +101,6 @@ import { createTransformCache } from "./plugins/transform-cache.js";
|
|
|
98
101
|
import { createOgHarfbuzzPlugin } from "./plugins/og-harfbuzz.js";
|
|
99
102
|
import { createOgAssetsPlugin, createOgInlineFetchAssetsPlugin } from "./plugins/og-assets.js";
|
|
100
103
|
import { createUseCacheCallablePlugin } from "./plugins/use-cache-callable.js";
|
|
101
|
-
import { cacheFlightCodecPlugin } from "./plugins/cache-flight-codec.js";
|
|
102
104
|
import { SSR_EXTERNAL_REACT_ENTRIES, VINEXT_OPTIMIZE_DEPS_EXCLUDE, mergeOptimizeDepsExclude } from "./plugins/rsc-client-shim-excludes.js";
|
|
103
105
|
import { createServerExternalsManifestPlugin } from "./plugins/server-externals-manifest.js";
|
|
104
106
|
import { createTransitiveExternalsPlugin } from "./plugins/transitive-externals.js";
|
|
@@ -126,14 +128,13 @@ import { hasMdxFiles, loadMdxEsmReader, pageExtensionsIncludeMdx } from "./utils
|
|
|
126
128
|
import { publicFileRouteKey } from "./utils/public-file-path.js";
|
|
127
129
|
import { scanPublicFileRoutes } from "./utils/public-routes.js";
|
|
128
130
|
import { createIgnoreDynamicRequestsPlugin } from "./plugins/ignore-dynamic-requests.js";
|
|
129
|
-
import { assertPluginRscVersion } from "./utils/plugin-rsc-version.js";
|
|
131
|
+
import { assertPluginRscVersion, needsAppReactServerDom } from "./utils/plugin-rsc-version.js";
|
|
130
132
|
import { assertSupportedViteVersion, getDepOptimizeNodeEnvOptions, serializeViteDefine } from "./utils/vite-version.js";
|
|
131
133
|
import { staticExportApp, staticExportPages } from "./build/static-export.js";
|
|
132
134
|
import { createRequire } from "node:module";
|
|
133
135
|
import fs from "node:fs";
|
|
134
136
|
import { pathToFileURL } from "node:url";
|
|
135
|
-
import { createIdResolver, createLogger, isRunnableDevEnvironment,
|
|
136
|
-
import { execFileSync } from "node:child_process";
|
|
137
|
+
import { createIdResolver, createLogger, isRunnableDevEnvironment, transformWithOxc } from "vite";
|
|
137
138
|
import { createHash, randomBytes } from "node:crypto";
|
|
138
139
|
import MagicString from "magic-string";
|
|
139
140
|
import commonjs from "vite-plugin-commonjs";
|
|
@@ -146,6 +147,7 @@ const PAGES_CLOUDFLARE_WORKER_OPTIMIZE_DEPS_INCLUDE = Object.freeze([
|
|
|
146
147
|
"react/jsx-runtime",
|
|
147
148
|
"react/jsx-dev-runtime"
|
|
148
149
|
]);
|
|
150
|
+
const PAGES_CLOUDFLARE_WORKER_OPTIONAL_OPTIMIZE_DEPS_INCLUDE = Object.freeze(["use-sync-external-store/with-selector", "vinext > @vitejs/plugin-rsc/react/rsc"]);
|
|
149
151
|
const APP_CLIENT_OPTIONAL_OPTIMIZE_DEPS_INCLUDE = Object.freeze([
|
|
150
152
|
"use-sync-external-store/shim",
|
|
151
153
|
"use-sync-external-store/shim/index.js",
|
|
@@ -199,9 +201,13 @@ function createServerOnlyClientImportError(importer) {
|
|
|
199
201
|
}
|
|
200
202
|
function hasServerOnlyMarkerImport(code) {
|
|
201
203
|
if (!code.includes("server-only")) return false;
|
|
204
|
+
const record = parseModuleRecord(code, "js");
|
|
205
|
+
if (!record) return false;
|
|
206
|
+
if (record.staticImports.some((statement) => statement.moduleRequest.value === "server-only")) return true;
|
|
207
|
+
if (!code.includes("require")) return false;
|
|
202
208
|
let ast;
|
|
203
209
|
try {
|
|
204
|
-
ast =
|
|
210
|
+
ast = parseProgram(code);
|
|
205
211
|
} catch {
|
|
206
212
|
return false;
|
|
207
213
|
}
|
|
@@ -209,9 +215,6 @@ function hasServerOnlyMarkerImport(code) {
|
|
|
209
215
|
if (!node) return false;
|
|
210
216
|
if (Array.isArray(node)) return node.some((child) => walk(child));
|
|
211
217
|
if (typeof node !== "object") return false;
|
|
212
|
-
if (node.type === "ImportDeclaration") {
|
|
213
|
-
if (node.source?.value === "server-only") return true;
|
|
214
|
-
}
|
|
215
218
|
if (node.type === "CallExpression") {
|
|
216
219
|
const call = node;
|
|
217
220
|
if (call.callee?.type === "Identifier" && call.callee.name === "require" && call.arguments?.[0]?.type === "Literal" && call.arguments[0].value === "server-only") return true;
|
|
@@ -300,24 +303,16 @@ function isolateMdxStylesheetImports(code) {
|
|
|
300
303
|
}
|
|
301
304
|
function isolateGlobalNotFoundStylesheetImports(code, id) {
|
|
302
305
|
if (isMdxModuleId(id)) return isolateMdxStylesheetImports(code);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
ast = parseAst(code, { lang: parserLanguageForScript(id) });
|
|
306
|
-
} catch {
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
306
|
+
const record = parseModuleRecord(code, parserLanguageForScript(id));
|
|
307
|
+
if (!record) return null;
|
|
309
308
|
let output = null;
|
|
310
|
-
for (const statement of
|
|
311
|
-
if (statement.
|
|
312
|
-
|
|
313
|
-
if (
|
|
314
|
-
|
|
315
|
-
const specifier = source?.value;
|
|
316
|
-
if (typeof specifier !== "string" || !isStylesheetSpecifier(specifier)) continue;
|
|
317
|
-
const range = source;
|
|
318
|
-
if (typeof range.start !== "number" || typeof range.end !== "number") continue;
|
|
309
|
+
for (const statement of record.staticImports) {
|
|
310
|
+
if (statement.entries.length > 0 || isTypeOnlyImport(code, statement)) continue;
|
|
311
|
+
const source = statement.moduleRequest;
|
|
312
|
+
if (hasImportAttributes(code, source.end, statement.end)) continue;
|
|
313
|
+
if (!isStylesheetSpecifier(source.value)) continue;
|
|
319
314
|
output ??= new MagicString(code);
|
|
320
|
-
output.overwrite(
|
|
315
|
+
output.overwrite(source.start, source.end, JSON.stringify(source.value + GLOBAL_NOT_FOUND_CSS_QUERY));
|
|
321
316
|
}
|
|
322
317
|
return output ? toMagicStringTransformResult(output) : null;
|
|
323
318
|
}
|
|
@@ -330,8 +325,46 @@ function commonjsTransformFilter(id, transformProjectLocalCommonJs = false, tran
|
|
|
330
325
|
if (transformBundledDependencies && isBundledCommonJsDependency(cleanId)) return true;
|
|
331
326
|
if (/\.c[jt]s$/i.test(cleanId) && !cleanId.includes("node_modules")) return transformProjectLocalCommonJs;
|
|
332
327
|
}
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
const EMPTY_EXPORT_PRESCAN = new RegExp(String.raw`\bexport${TRIVIA_PATTERN}*\{${TRIVIA_PATTERN}*\}`);
|
|
329
|
+
/**
|
|
330
|
+
* Sources of a module's static imports and re-exports, in source order.
|
|
331
|
+
* Type-only declarations and declarations with import attributes are skipped.
|
|
332
|
+
*/
|
|
333
|
+
function runtimeStaticDependencySpecifiers(code, record, lang) {
|
|
334
|
+
const dependencies = [];
|
|
335
|
+
for (const statement of record.staticImports) {
|
|
336
|
+
if (isTypeOnlyImport(code, statement)) continue;
|
|
337
|
+
if (hasImportAttributes(code, statement.moduleRequest.end, statement.end)) continue;
|
|
338
|
+
dependencies.push({
|
|
339
|
+
start: statement.start,
|
|
340
|
+
specifier: statement.moduleRequest.value
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
for (const statement of record.staticExports) {
|
|
344
|
+
const source = statement.entries[0]?.moduleRequest;
|
|
345
|
+
if (!source || statement.entries.every((entry) => entry.isType)) continue;
|
|
346
|
+
if (hasImportAttributes(code, source.end, statement.end)) continue;
|
|
347
|
+
dependencies.push({
|
|
348
|
+
start: statement.start,
|
|
349
|
+
specifier: source.value
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (EMPTY_EXPORT_PRESCAN.test(code)) {
|
|
353
|
+
let program = null;
|
|
354
|
+
try {
|
|
355
|
+
program = parseProgram(code, { lang });
|
|
356
|
+
} catch {}
|
|
357
|
+
for (const statement of program?.body ?? []) {
|
|
358
|
+
if (statement.type !== "ExportNamedDeclaration" || !statement.source) continue;
|
|
359
|
+
if (statement.specifiers.length > 0 || statement.exportKind === "type") continue;
|
|
360
|
+
if (statement.attributes.length > 0) continue;
|
|
361
|
+
dependencies.push({
|
|
362
|
+
start: statement.start,
|
|
363
|
+
specifier: statement.source.value
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return dependencies.sort((a, b) => a.start - b.start).map(({ specifier }) => specifier);
|
|
335
368
|
}
|
|
336
369
|
function resolvedStylesheetToDevManifestAsset(root, resolvedId) {
|
|
337
370
|
const cleanId = stripViteModuleQuery(resolvedId);
|
|
@@ -363,22 +396,17 @@ function createDevPagesModuleDependencyReader(root, resolve) {
|
|
|
363
396
|
async function collectModuleDependencies(modulePath) {
|
|
364
397
|
const cleanModulePath = stripViteModuleQuery(modulePath);
|
|
365
398
|
if (!path.isAbsolute(cleanModulePath) || !fs.existsSync(cleanModulePath)) return [];
|
|
366
|
-
let
|
|
399
|
+
let code;
|
|
367
400
|
try {
|
|
368
|
-
|
|
401
|
+
code = fs.readFileSync(cleanModulePath, "utf-8");
|
|
369
402
|
} catch {
|
|
370
403
|
return [];
|
|
371
404
|
}
|
|
405
|
+
const record = parseModuleRecord(code, parserLanguageForScript(cleanModulePath));
|
|
406
|
+
if (!record) return [];
|
|
372
407
|
const dependencies = [];
|
|
373
|
-
for (const
|
|
374
|
-
|
|
375
|
-
if (statement.importKind === "type") continue;
|
|
376
|
-
if (statement.exportKind === "type") continue;
|
|
377
|
-
if (hasOnlyTypeSpecifiers(statement)) continue;
|
|
378
|
-
if (statement.attributes && statement.attributes.length > 0) continue;
|
|
379
|
-
const specifier = statement.source?.value;
|
|
380
|
-
if (typeof specifier !== "string") continue;
|
|
381
|
-
const resolved = await resolve(specifier, cleanModulePath, { skipSelf: true });
|
|
408
|
+
for (const specifier of runtimeStaticDependencySpecifiers(code, record, parserLanguageForScript(cleanModulePath))) {
|
|
409
|
+
const resolved = await resolve(specifier, cleanModulePath, { skipSelf: false });
|
|
382
410
|
if (!resolved?.id) continue;
|
|
383
411
|
if (isStylesheetSpecifier(specifier) || isStylesheetSpecifier(resolved.id)) {
|
|
384
412
|
const asset = resolvedStylesheetToDevManifestAsset(root, resolved.id);
|
|
@@ -721,6 +749,11 @@ const VIRTUAL_CACHEABILITY_REQUEST_PROJECTION = "virtual:vinext-cacheability-req
|
|
|
721
749
|
const RESOLVED_CACHEABILITY_REQUEST_PROJECTION = "\0" + VIRTUAL_CACHEABILITY_REQUEST_PROJECTION;
|
|
722
750
|
const VIRTUAL_PREGENERATED_CONCRETE_PATHS = "virtual:vinext-pregenerated-concrete-paths";
|
|
723
751
|
const RESOLVED_PREGENERATED_CONCRETE_PATHS = "\0" + VIRTUAL_PREGENERATED_CONCRETE_PATHS;
|
|
752
|
+
const OUTPUT_ROOT_SERVER_EXTERNALS = /* @__PURE__ */ new Map([
|
|
753
|
+
[VIRTUAL_CACHEABILITY_MANIFEST, CACHEABILITY_MANIFEST_MODULE],
|
|
754
|
+
[VIRTUAL_CACHEABILITY_REQUEST_PROJECTION, CACHEABILITY_REQUEST_PROJECTION_MODULE],
|
|
755
|
+
[VIRTUAL_PREGENERATED_CONCRETE_PATHS, PREGENERATED_CONCRETE_PATHS_MODULE]
|
|
756
|
+
]);
|
|
724
757
|
const VIRTUAL_APP_REQUEST_ENTRY = "virtual:vinext-app-request-entry";
|
|
725
758
|
const RESOLVED_APP_REQUEST_ENTRY = "\0" + VIRTUAL_APP_REQUEST_ENTRY;
|
|
726
759
|
const VIRTUAL_APP_RESPONSE_ENTRY = "virtual:vinext-app-response-entry";
|
|
@@ -912,7 +945,7 @@ function vinext(options = {}) {
|
|
|
912
945
|
let hasPlainPagesBuildEnvironments = false;
|
|
913
946
|
let originalPlainPagesEnvironments;
|
|
914
947
|
let buildLifecycleInvocation;
|
|
915
|
-
let
|
|
948
|
+
let reactVersionChecked = false;
|
|
916
949
|
let pagesOptimizeEntries = [];
|
|
917
950
|
const importMetaUrlCapability = createImportMetaUrlPlugin({
|
|
918
951
|
getRoot: () => root,
|
|
@@ -922,6 +955,7 @@ function vinext(options = {}) {
|
|
|
922
955
|
}
|
|
923
956
|
});
|
|
924
957
|
const pagesClientAssetsOutputDirs = /* @__PURE__ */ new Set();
|
|
958
|
+
const pagesClientAssetsExternalTargets = /* @__PURE__ */ new Map();
|
|
925
959
|
const resolvePagesClientAssetsOutputDir = (environmentName, outputDir) => !selectedMultiStageOutput && !hasAppDir && !hasCloudflarePlugin && environmentName === "ssr" ? path.dirname(outputDir) : outputDir;
|
|
926
960
|
let pagesClientAssetsModule = internalOptions.__pagesClientAssetsModule ?? null;
|
|
927
961
|
let clientBuildFiles = [];
|
|
@@ -1042,7 +1076,7 @@ function vinext(options = {}) {
|
|
|
1042
1076
|
});
|
|
1043
1077
|
const useServerIndex = plugins.findIndex((plugin) => plugin.name === "rsc:use-server");
|
|
1044
1078
|
if (useServerIndex === -1) throw new Error("vinext: Failed to locate @vitejs/plugin-rsc use-server plugin.");
|
|
1045
|
-
plugins.splice(useServerIndex, 0,
|
|
1079
|
+
plugins.splice(useServerIndex, 0, useCachePlugin);
|
|
1046
1080
|
return plugins.map(scopeRscPlugin);
|
|
1047
1081
|
}).catch((cause) => {
|
|
1048
1082
|
throw new Error("vinext: Failed to load @vitejs/plugin-rsc.", { cause });
|
|
@@ -1214,17 +1248,13 @@ function vinext(options = {}) {
|
|
|
1214
1248
|
shouldDeferPostBuild: () => buildLifecycleInvocation !== void 0,
|
|
1215
1249
|
shouldPrepare: (config) => buildLifecycleEnabled && config.build?.write !== false && !config.build?.lib && (buildLifecycleInvocation !== void 0 || !config.build?.watch && !config.build?.ssr && getBuildBundlerOptions(config.build)?.input === void 0),
|
|
1216
1250
|
onPrepare: () => {
|
|
1217
|
-
if (!hasAppDir ||
|
|
1218
|
-
|
|
1251
|
+
if (!hasAppDir || reactVersionChecked) return;
|
|
1252
|
+
reactVersionChecked = true;
|
|
1219
1253
|
const reactUpgrade = getReactUpgradeDeps(root);
|
|
1254
|
+
const needsAppRsdw = rscVersion !== null && needsAppReactServerDom(process.cwd(), rscVersion);
|
|
1255
|
+
if (needsAppRsdw && !reactUpgrade.includes("react-server-dom-webpack@latest")) reactUpgrade.push("react-server-dom-webpack@latest");
|
|
1220
1256
|
if (reactUpgrade.length === 0) return;
|
|
1221
|
-
|
|
1222
|
-
console.log(" Upgrading React for RSC compatibility...");
|
|
1223
|
-
execFileSync(packageManager, [...packageManagerArgs, ...reactUpgrade], {
|
|
1224
|
-
cwd: root,
|
|
1225
|
-
stdio: "inherit",
|
|
1226
|
-
shell: process.platform === "win32"
|
|
1227
|
-
});
|
|
1257
|
+
throw new Error(reactUpgradeRequiredMessage(detectPackageManager(root).replace(/ -D$/, ""), reactUpgrade, needsAppRsdw ? rscVersion : void 0));
|
|
1228
1258
|
},
|
|
1229
1259
|
shouldBuildPlainPages: () => !hasAppDir && !hasCloudflarePlugin && !hasNitroPlugin,
|
|
1230
1260
|
createContext: () => ({
|
|
@@ -1990,9 +2020,10 @@ function vinext(options = {}) {
|
|
|
1990
2020
|
const optionalWarnings = /* @__PURE__ */ new Set();
|
|
1991
2021
|
for (const [name, environment] of Object.entries(config.environments)) {
|
|
1992
2022
|
const optimizer = environment.optimizeDeps;
|
|
1993
|
-
const optionalIncludes = hasAppDir ? name === "client" && !optimizer.noDiscovery ? APP_CLIENT_OPTIONAL_OPTIMIZE_DEPS_INCLUDE : [] : name !== "client" ?
|
|
2023
|
+
const optionalIncludes = hasAppDir ? name === "client" && !optimizer.noDiscovery ? APP_CLIENT_OPTIONAL_OPTIMIZE_DEPS_INCLUDE : [] : name !== "client" ? PAGES_CLOUDFLARE_WORKER_OPTIONAL_OPTIMIZE_DEPS_INCLUDE : [];
|
|
1994
2024
|
for (const id of optionalIncludes) {
|
|
1995
|
-
|
|
2025
|
+
const depId = id.slice(id.lastIndexOf(">") + 1).trim();
|
|
2026
|
+
if (optimizer.include?.includes(id) || optimizer.include?.includes(depId) || optimizer.exclude?.some((excluded) => depId === excluded || depId.startsWith(`${excluded}/`))) continue;
|
|
1996
2027
|
(optimizer.include ??= []).push(id);
|
|
1997
2028
|
optionalWarnings.add(`Failed to resolve dependency: ${id}, present in ${name} 'optimizeDeps.include'`);
|
|
1998
2029
|
}
|
|
@@ -2120,21 +2151,21 @@ function vinext(options = {}) {
|
|
|
2120
2151
|
if (cleanId === VIRTUAL_RSC_ENTRY) return RESOLVED_RSC_ENTRY;
|
|
2121
2152
|
if (cleanId === VIRTUAL_CACHEABILITY_MANIFEST) {
|
|
2122
2153
|
if ((hasAppDir ? this.environment?.name === "rsc" : this.environment !== void 0 && isServerEnvironment(this.environment)) && this.environment.config?.command === "build") return {
|
|
2123
|
-
id:
|
|
2154
|
+
id: VIRTUAL_CACHEABILITY_MANIFEST,
|
|
2124
2155
|
external: true
|
|
2125
2156
|
};
|
|
2126
2157
|
return RESOLVED_CACHEABILITY_MANIFEST;
|
|
2127
2158
|
}
|
|
2128
2159
|
if (cleanId === VIRTUAL_CACHEABILITY_REQUEST_PROJECTION) {
|
|
2129
2160
|
if (hasAppDir && this.environment?.name === "rsc" && this.environment.config?.command === "build") return {
|
|
2130
|
-
id:
|
|
2161
|
+
id: VIRTUAL_CACHEABILITY_REQUEST_PROJECTION,
|
|
2131
2162
|
external: true
|
|
2132
2163
|
};
|
|
2133
2164
|
return RESOLVED_CACHEABILITY_REQUEST_PROJECTION;
|
|
2134
2165
|
}
|
|
2135
2166
|
if (cleanId === VIRTUAL_PREGENERATED_CONCRETE_PATHS) {
|
|
2136
2167
|
if ((hasAppDir ? this.environment?.name === "rsc" : this.environment !== void 0 && isServerEnvironment(this.environment)) && this.environment.config?.command === "build") return {
|
|
2137
|
-
id:
|
|
2168
|
+
id: VIRTUAL_PREGENERATED_CONCRETE_PATHS,
|
|
2138
2169
|
external: true
|
|
2139
2170
|
};
|
|
2140
2171
|
return RESOLVED_PREGENERATED_CONCRETE_PATHS;
|
|
@@ -2370,15 +2401,19 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
2370
2401
|
const buildRoot = this.environment.config.root ?? process.cwd();
|
|
2371
2402
|
const environmentOutDir = path.resolve(buildRoot, this.environment.config.build.outDir);
|
|
2372
2403
|
const sidecarDir = resolvePagesClientAssetsOutputDir(this.environment.name, environmentOutDir);
|
|
2373
|
-
|
|
2374
|
-
if (!externalId.startsWith(".")) externalId = `./${externalId}`;
|
|
2404
|
+
pagesClientAssetsExternalTargets.set(this.environment.name, /* @__PURE__ */ new Map([[VIRTUAL_PAGES_CLIENT_ASSETS, path.relative(environmentOutDir, path.join(sidecarDir, PAGES_CLIENT_ASSETS_MODULE))]]));
|
|
2375
2405
|
pagesClientAssetsOutputDirs.add(sidecarDir);
|
|
2376
2406
|
return {
|
|
2377
|
-
id:
|
|
2407
|
+
id: VIRTUAL_PAGES_CLIENT_ASSETS,
|
|
2378
2408
|
external: true
|
|
2379
2409
|
};
|
|
2380
2410
|
}
|
|
2381
2411
|
},
|
|
2412
|
+
renderChunk(code, chunk) {
|
|
2413
|
+
const targets = pagesClientAssetsExternalTargets.get(this.environment.name);
|
|
2414
|
+
if (!targets) return null;
|
|
2415
|
+
return rewriteOutputRootExternals(code, chunk.fileName, targets);
|
|
2416
|
+
},
|
|
2382
2417
|
outputOptions(output) {
|
|
2383
2418
|
const environment = this.environment;
|
|
2384
2419
|
if (!selectedMultiStageOutput || !environment || !isMultiStageServerEnvironment(environment)) return;
|
|
@@ -2484,6 +2519,9 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
2484
2519
|
{
|
|
2485
2520
|
name: "vinext:cacheability-manifest-asset",
|
|
2486
2521
|
apply: "build",
|
|
2522
|
+
renderChunk(code, chunk) {
|
|
2523
|
+
return rewriteOutputRootExternals(code, chunk.fileName, OUTPUT_ROOT_SERVER_EXTERNALS);
|
|
2524
|
+
},
|
|
2487
2525
|
generateBundle() {
|
|
2488
2526
|
if (!(hasAppDir ? this.environment?.name === "rsc" : this.environment !== void 0 && isServerEnvironment(this.environment))) return;
|
|
2489
2527
|
this.emitFile({
|
|
@@ -2648,7 +2686,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
2648
2686
|
return new URL(resolved).origin;
|
|
2649
2687
|
} catch {}
|
|
2650
2688
|
const address = server.httpServer?.address();
|
|
2651
|
-
return `http://localhost:${typeof address === "object" && address ? address.port : server.config.server.port
|
|
2689
|
+
return `http://localhost:${typeof address === "object" && address ? address.port : server.config.server.port}`;
|
|
2652
2690
|
};
|
|
2653
2691
|
let cachedSSRHandler = null;
|
|
2654
2692
|
const devPageRouteDataKinds = /* @__PURE__ */ new Map();
|
|
@@ -3724,27 +3762,18 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3724
3762
|
},
|
|
3725
3763
|
async handler(code, id) {
|
|
3726
3764
|
const lang = id.endsWith(".ts") ? "ts" : "tsx";
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
ast = parseAst(code, { lang });
|
|
3730
|
-
} catch {
|
|
3731
|
-
return null;
|
|
3732
|
-
}
|
|
3765
|
+
const record = parseModuleRecord(code, lang);
|
|
3766
|
+
if (!record) return null;
|
|
3733
3767
|
const s = new MagicString(code);
|
|
3734
3768
|
let hasChanges = false;
|
|
3735
3769
|
const imageImports = /* @__PURE__ */ new Set();
|
|
3736
|
-
for (const
|
|
3737
|
-
|
|
3738
|
-
const importNode = node;
|
|
3739
|
-
const importPath = importNode.source?.value;
|
|
3740
|
-
if (typeof importPath !== "string") continue;
|
|
3770
|
+
for (const importNode of record.staticImports) {
|
|
3771
|
+
const importPath = importNode.moduleRequest.value;
|
|
3741
3772
|
if (!IMAGE_EXT_RE.test(importPath)) continue;
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
const varName = specifier.local?.name;
|
|
3747
|
-
if (!varName) continue;
|
|
3773
|
+
if (importNode.entries.length !== 1) continue;
|
|
3774
|
+
const [entry] = importNode.entries;
|
|
3775
|
+
if (entry.importName.kind !== "Default") continue;
|
|
3776
|
+
const varName = entry.localName.value;
|
|
3748
3777
|
const dir = path.dirname(id);
|
|
3749
3778
|
const resolvedImage = importPath.startsWith(".") ? path.resolve(dir, importPath) : (await this.resolve(importPath, id, { skipSelf: true }))?.id;
|
|
3750
3779
|
if (!resolvedImage) continue;
|
|
@@ -3866,24 +3895,13 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3866
3895
|
}
|
|
3867
3896
|
},
|
|
3868
3897
|
{
|
|
3869
|
-
name: "vinext:nitro-
|
|
3870
|
-
nitro: { setup:
|
|
3898
|
+
name: "vinext:nitro-setup",
|
|
3899
|
+
nitro: { setup: (nitro) => {
|
|
3871
3900
|
nitroBuildDir = nitro.options.buildDir ? path.resolve(root, nitro.options.buildDir) : void 0;
|
|
3872
3901
|
nitroHostRuntime = nitro.options.exportConditions?.includes("workerd") ? "worker" : "node";
|
|
3873
3902
|
if (!nextConfig) return;
|
|
3874
3903
|
if (!hasAppDir && !hasPagesDir) return;
|
|
3875
3904
|
if (resolvedServerExternalPackages.length > 0) nitro.options.traceDeps = [.../* @__PURE__ */ new Set([...nitro.options.traceDeps ?? [], ...resolvedServerExternalPackages])];
|
|
3876
|
-
if (nitro.options.dev) return;
|
|
3877
|
-
const { collectNitroRouteRules, mergeNitroRouteRules } = await import("./build/nitro-route-rules.js");
|
|
3878
|
-
const generatedRouteRules = await collectNitroRouteRules({
|
|
3879
|
-
appDir: hasAppDir ? appDir : null,
|
|
3880
|
-
pagesDir: hasPagesDir ? pagesDir : null,
|
|
3881
|
-
pageExtensions: nextConfig.pageExtensions
|
|
3882
|
-
});
|
|
3883
|
-
if (Object.keys(generatedRouteRules).length === 0) return;
|
|
3884
|
-
const { routeRules, skippedRoutes } = mergeNitroRouteRules(nitro.options.routeRules, generatedRouteRules);
|
|
3885
|
-
nitro.options.routeRules = routeRules;
|
|
3886
|
-
if (skippedRoutes.length > 0) (nitro.logger?.warn ?? console.warn)(`[vinext] Skipping generated Nitro routeRules for routes with existing exact cache config: ${skippedRoutes.join(", ")}`);
|
|
3887
3905
|
} }
|
|
3888
3906
|
},
|
|
3889
3907
|
{
|
|
@@ -4236,7 +4254,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
4236
4254
|
if (rscPluginPromise) {
|
|
4237
4255
|
plugins.push(createRscReferenceValidationNormalizerPlugin());
|
|
4238
4256
|
plugins.push(createRscClientReferenceLoadersPlugin());
|
|
4239
|
-
} else if (manualUseCachePluginPromise) plugins.push(
|
|
4257
|
+
} else if (manualUseCachePluginPromise) plugins.push(manualUseCachePluginPromise);
|
|
4240
4258
|
plugins.push({
|
|
4241
4259
|
name: "vinext:plain-pages-build-config",
|
|
4242
4260
|
apply: "build",
|
|
@@ -4257,6 +4275,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
4257
4275
|
}
|
|
4258
4276
|
}
|
|
4259
4277
|
});
|
|
4278
|
+
plugins.push(createCloudflareDevModuleUrlsPlugin({ isEnabled: () => hasCloudflarePlugin }));
|
|
4260
4279
|
plugins.push(buildLifecyclePlugins[1]);
|
|
4261
4280
|
return plugins;
|
|
4262
4281
|
}
|
package/dist/init.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export type InitDependencyGroups = {
|
|
|
70
70
|
dependencies: string[];
|
|
71
71
|
devDependencies: string[];
|
|
72
72
|
};
|
|
73
|
-
export declare function getInitDependencyGroups(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean): InitDependencyGroups;
|
|
73
|
+
export declare function getInitDependencyGroups(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean, tailwindPostcss?: boolean): InitDependencyGroups;
|
|
74
74
|
export declare function getInitDeps(isAppRouter: boolean, platform: InitPlatform, cloudflare?: CloudflareInitOptions, hasCssModules?: boolean): string[];
|
|
75
75
|
export declare function isDepInstalled(root: string, dep: string): boolean;
|
|
76
76
|
/**
|
package/dist/init.js
CHANGED
|
@@ -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.
|
|
@@ -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
|
*
|
|
@@ -445,6 +518,7 @@ async function init(options) {
|
|
|
445
518
|
const viteConfigExists = hasViteConfig(root);
|
|
446
519
|
const isApp = detectProject(root).isAppRouter;
|
|
447
520
|
const hasCssModules = !options.skipCssModules && scanCssModuleFiles(root);
|
|
521
|
+
const tailwindPostcssSetup = getTailwindPostcssSetup(root, platform === "node" && options.force ? void 0 : existingViteConfigPath);
|
|
448
522
|
const pmName = detectPackageManagerName(root);
|
|
449
523
|
const shouldInstall = options.install ?? true;
|
|
450
524
|
const isStaticExport = platform === "cloudflare" && await resolvesToStaticExport(root, existingViteConfigPath);
|
|
@@ -495,15 +569,19 @@ async function init(options) {
|
|
|
495
569
|
};
|
|
496
570
|
const platformSetup = platform === "cloudflare" ? setupCloudflarePlatform(setupContext, cloudflareOptions) : setupNodePlatform(setupContext);
|
|
497
571
|
const { generatedViteConfig, skippedViteConfig, generatedPlatformFiles } = platformSetup;
|
|
572
|
+
if (tailwindPostcssSetup === "generate") fs.writeFileSync(path.join(root, "postcss.config.mjs"), TAILWIND_POSTCSS_CONFIG, "utf-8");
|
|
498
573
|
const updatedGitignore = updateGitignore(root, platform, options.cloudflare?.legacyWrangler);
|
|
499
|
-
const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules);
|
|
574
|
+
const neededDeps = getInitDependencyGroups(isApp, platform, options.cloudflare, hasCssModules, tailwindPostcssSetup === "generate" || tailwindPostcssSetup === "install");
|
|
500
575
|
const missingDependencies = neededDeps.dependencies.filter((dep) => !isDepInstalled(root, dep));
|
|
501
576
|
const missingDevDependencies = neededDeps.devDependencies.filter((dep) => !isDepInstalled(root, dep));
|
|
502
577
|
let dependencyInstallNeedsApproval = false;
|
|
503
578
|
const dependencyEntriesAdded = [];
|
|
504
579
|
const devDependencyEntriesAdded = [];
|
|
505
|
-
if (isApp
|
|
506
|
-
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 });
|
|
507
585
|
if (reactUpgrade.length > 0) {
|
|
508
586
|
console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
|
|
509
587
|
console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
|
|
@@ -576,6 +654,8 @@ async function init(options) {
|
|
|
576
654
|
if (skippedViteConfig) console.log(` ${terminalStyle.yellow("-")} Skipped vite.config.ts (already exists, use --force to overwrite)`);
|
|
577
655
|
if (updatedGitignore) console.log(` ${terminalStyle.green("✓")} Added vinext output directories to .gitignore`);
|
|
578
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`);
|
|
579
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}"`);
|
|
580
660
|
if (platformSetup.preservedExistingGenerateScopedName) console.log(` ${terminalStyle.yellow("!")} Preserved existing css.modules.generateScopedName; verify it produces identical class names in SSR and client builds`);
|
|
581
661
|
const nextSteps = [...platformSetup.nextSteps];
|