@nuxt/vite-builder-nightly 4.2.0-29344710.84b82c47 → 4.2.0-29345108.b399de2f

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/dist/index.d.mts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ViteConfig } from 'nuxt/schema';
2
+ import { EnvironmentOptions } from 'vite';
2
3
  import { NuxtBuilder } from '@nuxt/schema';
3
4
 
4
5
  declare const bundle: NuxtBuilder['bundle'];
5
6
 
6
7
  declare module 'nuxt/schema' {
7
8
  interface ViteOptions extends ViteConfig {
8
- $client?: ViteConfig;
9
- $server?: ViteConfig;
9
+ $client?: EnvironmentOptions;
10
+ $server?: EnvironmentOptions;
10
11
  viteNode?: {
11
12
  maxRetryAttempts?: number;
12
13
  /** in milliseconds */
package/dist/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ViteConfig } from 'nuxt/schema';
2
+ import { EnvironmentOptions } from 'vite';
2
3
  import { NuxtBuilder } from '@nuxt/schema';
3
4
 
4
5
  declare const bundle: NuxtBuilder['bundle'];
5
6
 
6
7
  declare module 'nuxt/schema' {
7
8
  interface ViteOptions extends ViteConfig {
8
- $client?: ViteConfig;
9
- $server?: ViteConfig;
9
+ $client?: EnvironmentOptions;
10
+ $server?: EnvironmentOptions;
10
11
  viteNode?: {
11
12
  maxRetryAttempts?: number;
12
13
  /** in milliseconds */
package/dist/index.mjs CHANGED
@@ -1,15 +1,14 @@
1
1
  import fs, { existsSync, readFileSync } from 'node:fs';
2
2
  import * as vite from 'vite';
3
- import { isCSSRequest, createLogger } from 'vite';
4
- import { dirname, normalize, resolve, join, relative, basename, isAbsolute } from 'pathe';
5
- import { useNitro, logger, useNuxt, resolvePath, getLayerDirectories, createIsIgnored } from '@nuxt/kit';
3
+ import { isCSSRequest, createLogger, mergeConfig, createBuilder, createServer } from 'vite';
4
+ import { dirname, normalize, join, resolve, relative, basename, isAbsolute } from 'pathe';
5
+ import { tryUseNuxt, useNitro, logger, useNuxt, resolvePath, getLayerDirectories, createIsIgnored } from '@nuxt/kit';
6
6
  import { findStaticImports, sanitizeFilePath } from 'mlly';
7
+ import viteJsxPlugin from '@vitejs/plugin-vue-jsx';
8
+ import vuePlugin from '@vitejs/plugin-vue';
7
9
  import { parseURL, parseQuery, joinURL, getQuery, withLeadingSlash, withTrailingSlash, withoutLeadingSlash, withoutBase } from 'ufo';
8
10
  import { filename as filename$1 } from 'pathe/utils';
9
11
  import { resolveModulePath } from 'exsolve';
10
- import vuePlugin from '@vitejs/plugin-vue';
11
- import viteJsxPlugin from '@vitejs/plugin-vue-jsx';
12
- import { defineEnv } from 'unenv';
13
12
  import { pathToFileURL, fileURLToPath } from 'node:url';
14
13
  import MagicString from 'magic-string';
15
14
  import { unlink, mkdir, writeFile, rm, readFile } from 'node:fs/promises';
@@ -31,6 +30,7 @@ import { isBuiltin } from 'node:module';
31
30
  import { createJiti } from 'jiti';
32
31
  import { genImport, genArrayFromRaw, genObjectFromRawEntries } from 'knitwork';
33
32
  import replacePlugin from '@rollup/plugin-replace';
33
+ import { defineEnv } from 'unenv';
34
34
 
35
35
  function isVue(id, opts = {}) {
36
36
  const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href));
@@ -209,8 +209,9 @@ if (/(?:chunks|shared)$/.test(_distDir)) {
209
209
  }
210
210
  const distDir = _distDir;
211
211
 
212
- function getManifest(nuxt, ssrServer, clientEntry) {
212
+ function getManifest(nuxt, viteServer, clientEntry) {
213
213
  const css = /* @__PURE__ */ new Set();
214
+ const ssrServer = nuxt.options.experimental.viteEnvironmentApi ? viteServer.environments.ssr : viteServer;
214
215
  for (const key of ssrServer.moduleGraph.urlToModuleMap.keys()) {
215
216
  if (isCSS(key)) {
216
217
  const query = getQuery(key);
@@ -292,9 +293,8 @@ function useInvalidates() {
292
293
  function ViteNodePlugin(nuxt) {
293
294
  let socketServer;
294
295
  const socketPath = generateSocketPath();
295
- let viteNodeServerOptions;
296
296
  const { invalidates, markInvalidate, markInvalidates } = useInvalidates();
297
- const cleanupSocket = async () => {
297
+ async function cleanupSocket() {
298
298
  if (socketServer && socketServer.listening) {
299
299
  await new Promise((resolveClose) => socketServer.close(() => resolveClose()));
300
300
  }
@@ -304,17 +304,16 @@ function ViteNodePlugin(nuxt) {
304
304
  } catch {
305
305
  }
306
306
  }
307
- };
307
+ }
308
308
  return {
309
309
  name: "nuxt:vite-node-server",
310
310
  enforce: "post",
311
- applyToEnvironment: (environment) => environment.name === "client",
312
311
  configureServer(clientServer) {
313
- nuxt.hook("vite:serverCreated", (ssrServer, ctx) => {
314
- if (!ctx.isServer) {
315
- return;
316
- }
317
- viteNodeServerOptions = {
312
+ if (!tryUseNuxt()) {
313
+ return;
314
+ }
315
+ function resolveServer(ssrServer) {
316
+ const viteNodeServerOptions = {
318
317
  socketPath,
319
318
  root: nuxt.options.srcDir,
320
319
  entryPath: resolveServerEntry(ssrServer.config),
@@ -328,11 +327,17 @@ function ViteNodePlugin(nuxt) {
328
327
  };
329
328
  process.env.NUXT_VITE_NODE_OPTIONS = JSON.stringify(viteNodeServerOptions);
330
329
  socketServer = createViteNodeSocketServer(nuxt, ssrServer, clientServer, invalidates, viteNodeServerOptions);
331
- });
330
+ }
331
+ if (nuxt.options.experimental.viteEnvironmentApi) {
332
+ resolveServer(clientServer);
333
+ } else {
334
+ nuxt.hook("vite:serverCreated", (ssrServer, ctx) => ctx.isServer ? resolveServer(ssrServer) : void 0);
335
+ }
332
336
  nuxt.hook("close", cleanupSocket);
337
+ const client = nuxt.options.experimental.viteEnvironmentApi ? clientServer.environments.client : clientServer;
333
338
  nuxt.hook("app:templatesGenerated", (_app, changedTemplates) => {
334
339
  for (const template of changedTemplates) {
335
- const mods = clientServer.moduleGraph.getModulesByFile(`virtual:nuxt:${encodeURIComponent(template.dst)}`);
340
+ const mods = client.moduleGraph.getModulesByFile(`virtual:nuxt:${encodeURIComponent(template.dst)}`);
336
341
  for (const mod of mods || []) {
337
342
  markInvalidate(mod);
338
343
  }
@@ -344,15 +349,7 @@ function ViteNodePlugin(nuxt) {
344
349
  });
345
350
  },
346
351
  async buildEnd() {
347
- if (socketServer && socketServer.listening) {
348
- await new Promise((resolveClose) => socketServer.close(() => resolveClose()));
349
- }
350
- if (socketPath && !socketPath.startsWith("\\\\.\\pipe\\")) {
351
- try {
352
- await unlink(socketPath);
353
- } catch {
354
- }
355
- }
352
+ await cleanupSocket();
356
353
  }
357
354
  };
358
355
  }
@@ -390,19 +387,20 @@ function createViteNodeSocketServer(nuxt, ssrServer, clientServer, invalidates,
390
387
  }
391
388
  case "resolve": {
392
389
  const { id: resolveId, importer } = request.payload;
393
- if (!resolveId || !ssrServer) {
390
+ if (!resolveId) {
394
391
  throw createError({ statusCode: 400, message: "Missing id for resolve" });
395
392
  }
396
- const resolvedResult = await getNode(ssrServer).resolveId(resolveId, importer).catch(() => null);
393
+ const ssrNode = nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.ssr.pluginContainer : getNode(ssrServer);
394
+ const resolvedResult = await ssrNode.resolveId(resolveId, importer).catch(() => null);
397
395
  sendResponse(socket, request.id, resolvedResult);
398
396
  return;
399
397
  }
400
398
  case "module": {
401
- if (request.payload.moduleId === "/" || !ssrServer) {
399
+ if (request.payload.moduleId === "/") {
402
400
  throw createError({ statusCode: 400, message: "Invalid moduleId" });
403
401
  }
404
- const node = getNode(ssrServer);
405
- const response = await node.fetchModule(request.payload.moduleId).catch(async (err) => {
402
+ const ssrNode = nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.ssr : getNode(ssrServer);
403
+ const response = await ssrNode.fetchModule(request.payload.moduleId).catch(async (err) => {
406
404
  const errorData = {
407
405
  code: "VITE_ERROR",
408
406
  id: request.payload.moduleId,
@@ -414,7 +412,8 @@ function createViteNodeSocketServer(nuxt, ssrServer, clientServer, invalidates,
414
412
  }
415
413
  if (!errorData.frame && err.code === "PARSE_ERROR") {
416
414
  try {
417
- errorData.frame = await node.transformRequest(request.payload.moduleId, "web").then((res) => `${err.message || ""}
415
+ const clientNode = nuxt.options.experimental.viteEnvironmentApi ? ssrServer.environments.client : getNode(ssrServer);
416
+ errorData.frame = await clientNode.transformRequest(request.payload.moduleId).then((res) => `${err.message || ""}
418
417
  ${res?.code}`).catch(() => void 0);
419
418
  } catch {
420
419
  }
@@ -941,6 +940,9 @@ function DevServerPlugin(nuxt) {
941
940
  }
942
941
  }));
943
942
  });
943
+ if (nuxt.options.experimental.viteEnvironmentApi) {
944
+ await nuxt.callHook("vite:serverCreated", viteServer, { isClient: true, isServer: true });
945
+ }
944
946
  const mw = {
945
947
  route: "",
946
948
  handle: (req, res, next) => {
@@ -1012,7 +1014,7 @@ async function VitePluginCheckerPlugin(nuxt, environment) {
1012
1014
  resolveTSConfig(nuxt.options.rootDir)
1013
1015
  ]);
1014
1016
  const supportsProjects = await readTSConfig(tsconfigPath).then((r) => !!r.references?.length);
1015
- const environments = ["client", nuxt.options.ssr ? "ssr" : void 0].filter((name) => name === environment);
1017
+ const environments = ["client", nuxt.options.ssr ? "ssr" : void 0].filter((name) => environment ? name === environment : !!name);
1016
1018
  return environments.map((envName) => ({
1017
1019
  applyToEnvironment: (environment2) => environment2.name === envName,
1018
1020
  ...checker({
@@ -1025,34 +1027,10 @@ async function VitePluginCheckerPlugin(nuxt, environment) {
1025
1027
  }
1026
1028
  }
1027
1029
 
1028
- async function buildClient(nuxt, ctx) {
1029
- const nodeCompat = nuxt.options.experimental.clientNodeCompat ? {
1030
- alias: defineEnv({ nodeCompat: true, resolve: true }).env.alias,
1031
- define: { global: "globalThis" }
1032
- } : { define: {} };
1033
- const clientConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({
1034
- configFile: false,
1035
- base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : "./",
1036
- css: {
1037
- devSourcemap: !!nuxt.options.sourcemap.client
1038
- },
1039
- define: {
1040
- "process.env.NODE_ENV": JSON.stringify(ctx.config.mode),
1041
- "process.server": false,
1042
- "process.client": true,
1043
- "process.browser": true,
1044
- "process.nitro": false,
1045
- "process.prerender": false,
1046
- "import.meta.server": false,
1047
- "import.meta.client": true,
1048
- "import.meta.browser": true,
1049
- "import.meta.nitro": false,
1050
- "import.meta.prerender": false,
1051
- "module.hot": false,
1052
- ...nodeCompat.define
1053
- },
1030
+ const clientEnvironment = (nuxt, entry) => {
1031
+ return {
1054
1032
  optimizeDeps: {
1055
- entries: [ctx.entry],
1033
+ entries: [entry],
1056
1034
  include: [],
1057
1035
  // We exclude Vue and Nuxt common dependencies from optimization
1058
1036
  // as they already ship ESM.
@@ -1096,15 +1074,40 @@ async function buildClient(nuxt, ctx) {
1096
1074
  "#app-manifest"
1097
1075
  ]
1098
1076
  },
1099
- cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "client"),
1077
+ define: {
1078
+ "process.env.NODE_ENV": JSON.stringify(nuxt.options.vite.mode),
1079
+ "process.server": false,
1080
+ "process.client": true,
1081
+ "process.browser": true,
1082
+ "process.nitro": false,
1083
+ "process.prerender": false,
1084
+ "import.meta.server": false,
1085
+ "import.meta.client": true,
1086
+ "import.meta.browser": true,
1087
+ "import.meta.nitro": false,
1088
+ "import.meta.prerender": false,
1089
+ "module.hot": false,
1090
+ ...nuxt.options.experimental.clientNodeCompat ? { global: "globalThis" } : {}
1091
+ },
1100
1092
  build: {
1101
- sourcemap: nuxt.options.sourcemap.client ? ctx.config.build?.sourcemap ?? nuxt.options.sourcemap.client : false,
1093
+ sourcemap: nuxt.options.sourcemap.client ? nuxt.options.vite.build?.sourcemap ?? nuxt.options.sourcemap.client : false,
1102
1094
  manifest: "manifest.json",
1103
1095
  outDir: resolve(nuxt.options.buildDir, "dist/client"),
1104
1096
  rollupOptions: {
1105
- input: { entry: ctx.entry }
1097
+ input: { entry }
1106
1098
  }
1099
+ }
1100
+ };
1101
+ };
1102
+
1103
+ async function buildClient(nuxt, ctx) {
1104
+ const clientConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({
1105
+ configFile: false,
1106
+ base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : "./",
1107
+ css: {
1108
+ devSourcemap: !!nuxt.options.sourcemap.client
1107
1109
  },
1110
+ cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "client"),
1108
1111
  plugins: [
1109
1112
  DevStyleSSRPlugin({
1110
1113
  srcDir: nuxt.options.srcDir,
@@ -1127,7 +1130,8 @@ async function buildClient(nuxt, ctx) {
1127
1130
  clientFiles: [ctx.entry]
1128
1131
  },
1129
1132
  middlewareMode: true
1130
- }
1133
+ },
1134
+ ...clientEnvironment(nuxt, ctx.entry)
1131
1135
  }, nuxt.options.vite.$client || {}));
1132
1136
  clientConfig.customLogger = createViteLogger(clientConfig);
1133
1137
  await nuxt.callHook("vite:extendConfig", clientConfig, { isClient: true, isServer: false });
@@ -1205,25 +1209,6 @@ async function writeManifest(ctx) {
1205
1209
  }
1206
1210
  }
1207
1211
 
1208
- function transpile(envs) {
1209
- const nuxt = useNuxt();
1210
- const transpile2 = [];
1211
- for (let pattern of nuxt.options.build.transpile) {
1212
- if (typeof pattern === "function") {
1213
- const result = pattern(envs);
1214
- if (result) {
1215
- pattern = result;
1216
- }
1217
- }
1218
- if (typeof pattern === "string") {
1219
- transpile2.push(new RegExp(escapeStringRegexp(normalize(pattern))));
1220
- } else if (pattern instanceof RegExp) {
1221
- transpile2.push(pattern);
1222
- }
1223
- }
1224
- return transpile2;
1225
- }
1226
-
1227
1212
  const SourcemapPreserverPlugin = (nuxt) => {
1228
1213
  let outputDir;
1229
1214
  const ids = /* @__PURE__ */ new Set();
@@ -1303,67 +1288,48 @@ function VueFeatureFlagsPlugin(nuxt) {
1303
1288
  };
1304
1289
  }
1305
1290
 
1306
- async function buildServer(nuxt, ctx) {
1307
- const serverEntry = nuxt.options.ssr ? ctx.entry : await resolvePath(resolve(nuxt.options.appDir, "entry-spa"));
1308
- const serverConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({
1309
- configFile: false,
1310
- base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : void 0,
1311
- css: {
1312
- devSourcemap: !!nuxt.options.sourcemap.server
1313
- },
1314
- plugins: [
1315
- VueFeatureFlagsPlugin(nuxt),
1316
- // tell rollup's nitro build about the original sources of the generated vite server build
1317
- SourcemapPreserverPlugin(nuxt),
1318
- VitePluginCheckerPlugin(nuxt, "ssr")
1319
- ],
1320
- define: {
1321
- "process.server": true,
1322
- "process.client": false,
1323
- "process.browser": false,
1324
- "import.meta.server": true,
1325
- "import.meta.client": false,
1326
- "import.meta.browser": false,
1327
- "window": "undefined",
1328
- "document": "undefined",
1329
- "navigator": "undefined",
1330
- "location": "undefined",
1331
- "XMLHttpRequest": "undefined"
1332
- },
1333
- optimizeDeps: {
1334
- noDiscovery: true,
1335
- include: void 0
1336
- },
1337
- environments: {
1338
- ssr: {
1339
- resolve: {
1340
- conditions: nuxt._nitro?.options.exportConditions
1341
- }
1291
+ function transpile(envs) {
1292
+ const nuxt = useNuxt();
1293
+ const transpile2 = [];
1294
+ for (let pattern of nuxt.options.build.transpile) {
1295
+ if (typeof pattern === "function") {
1296
+ const result = pattern(envs);
1297
+ if (result) {
1298
+ pattern = result;
1342
1299
  }
1343
- },
1344
- resolve: {
1345
- conditions: nuxt._nitro?.options.exportConditions
1346
- },
1347
- ssr: {
1348
- external: [
1349
- "nitro/runtime",
1350
- // TODO: remove in v5
1351
- "#internal/nitro",
1352
- "#internal/nitro/utils"
1353
- ],
1354
- noExternal: [
1355
- ...transpile({ isServer: true, isDev: nuxt.options.dev }),
1356
- "/__vue-jsx",
1357
- "#app",
1358
- /^nuxt(\/|$)/,
1359
- /(nuxt|nuxt3|nuxt-nightly)\/(dist|src|app)/
1360
- ]
1361
- },
1362
- cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "server"),
1300
+ }
1301
+ if (typeof pattern === "string") {
1302
+ transpile2.push(new RegExp(escapeStringRegexp(normalize(pattern))));
1303
+ } else if (pattern instanceof RegExp) {
1304
+ transpile2.push(pattern);
1305
+ }
1306
+ }
1307
+ return transpile2;
1308
+ }
1309
+
1310
+ function ssr(nuxt) {
1311
+ return {
1312
+ external: [
1313
+ "nitro/runtime",
1314
+ // TODO: remove in v5
1315
+ "#internal/nitro",
1316
+ "#internal/nitro/utils"
1317
+ ],
1318
+ noExternal: [
1319
+ ...transpile({ isServer: true, isDev: nuxt.options.dev }),
1320
+ "/__vue-jsx",
1321
+ "#app",
1322
+ /^nuxt(\/|$)/,
1323
+ /(nuxt|nuxt3|nuxt-nightly)\/(dist|src|app)/
1324
+ ]
1325
+ };
1326
+ }
1327
+ function ssrEnvironment(nuxt, serverEntry) {
1328
+ return {
1363
1329
  build: {
1364
1330
  // we'll display this in nitro build output
1365
1331
  reportCompressedSize: false,
1366
- sourcemap: nuxt.options.sourcemap.server ? ctx.config.build?.sourcemap ?? nuxt.options.sourcemap.server : false,
1332
+ sourcemap: nuxt.options.sourcemap.server ? nuxt.options.vite.build?.sourcemap ?? nuxt.options.sourcemap.server : false,
1367
1333
  outDir: resolve(nuxt.options.buildDir, "dist/server"),
1368
1334
  ssr: true,
1369
1335
  rollupOptions: {
@@ -1382,7 +1348,6 @@ async function buildServer(nuxt, ctx) {
1382
1348
  output: {
1383
1349
  entryFileNames: "[name].mjs",
1384
1350
  format: "module",
1385
- // @ts-expect-error non-public property
1386
1351
  ...vite.rolldownVersion ? {} : {
1387
1352
  generatedCode: {
1388
1353
  symbols: true,
@@ -1401,6 +1366,52 @@ async function buildServer(nuxt, ctx) {
1401
1366
  }
1402
1367
  }
1403
1368
  },
1369
+ define: {
1370
+ "process.server": true,
1371
+ "process.client": false,
1372
+ "process.browser": false,
1373
+ "import.meta.server": true,
1374
+ "import.meta.client": false,
1375
+ "import.meta.browser": false,
1376
+ "window": "undefined",
1377
+ "document": "undefined",
1378
+ "navigator": "undefined",
1379
+ "location": "undefined",
1380
+ "XMLHttpRequest": "undefined"
1381
+ },
1382
+ resolve: {
1383
+ conditions: useNitro().options.exportConditions
1384
+ }
1385
+ };
1386
+ }
1387
+
1388
+ async function buildServer(nuxt, ctx) {
1389
+ const serverEntry = nuxt.options.ssr ? ctx.entry : await resolvePath(resolve(nuxt.options.appDir, "entry-spa"));
1390
+ const serverConfig = vite.mergeConfig(ctx.config, vite.mergeConfig({
1391
+ configFile: false,
1392
+ base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : void 0,
1393
+ css: {
1394
+ devSourcemap: !!nuxt.options.sourcemap.server
1395
+ },
1396
+ plugins: [
1397
+ VueFeatureFlagsPlugin(nuxt),
1398
+ // tell rollup's nitro build about the original sources of the generated vite server build
1399
+ SourcemapPreserverPlugin(nuxt),
1400
+ VitePluginCheckerPlugin(nuxt, "ssr")
1401
+ ],
1402
+ optimizeDeps: {
1403
+ noDiscovery: true,
1404
+ include: void 0
1405
+ },
1406
+ environments: {
1407
+ ssr: {
1408
+ resolve: {
1409
+ conditions: nuxt._nitro?.options.exportConditions
1410
+ }
1411
+ }
1412
+ },
1413
+ ssr: ssr(nuxt),
1414
+ cacheDir: resolve(nuxt.options.rootDir, ctx.config.cacheDir ?? "node_modules/.cache/vite", "server"),
1404
1415
  server: {
1405
1416
  warmup: {
1406
1417
  ssrFiles: [serverEntry]
@@ -1408,7 +1419,8 @@ async function buildServer(nuxt, ctx) {
1408
1419
  // https://github.com/vitest-dev/vitest/issues/229#issuecomment-1002685027
1409
1420
  preTransformRequests: false,
1410
1421
  hmr: false
1411
- }
1422
+ },
1423
+ ...ssrEnvironment(nuxt, serverEntry)
1412
1424
  }, nuxt.options.vite.$server || {}));
1413
1425
  serverConfig.customLogger = createViteLogger(serverConfig, { hideOutput: !nuxt.options.dev });
1414
1426
  await nuxt.callHook("vite:extendConfig", serverConfig, { isClient: false, isServer: true });
@@ -1572,7 +1584,7 @@ function SSRStylesPlugin(nuxt) {
1572
1584
  return {
1573
1585
  name: "ssr-styles",
1574
1586
  configResolved(config) {
1575
- if (!config.build.ssr) {
1587
+ if (!config.build.ssr || nuxt.options.experimental.viteEnvironmentApi) {
1576
1588
  entry = resolveClientEntry(config);
1577
1589
  }
1578
1590
  },
@@ -1928,6 +1940,72 @@ function NodeCompatAliasPlugin() {
1928
1940
  };
1929
1941
  }
1930
1942
 
1943
+ function ClientManifestPlugin(nuxt) {
1944
+ let clientEntry;
1945
+ let key;
1946
+ let disableCssCodeSplit;
1947
+ return {
1948
+ name: "nuxt:client-manifest",
1949
+ // needs to run after server build (or after client build if there is no server build)
1950
+ applyToEnvironment: (environment) => environment.name === "ssr",
1951
+ configResolved(config) {
1952
+ clientEntry = resolveClientEntry(config);
1953
+ key = relative(config.root, clientEntry);
1954
+ disableCssCodeSplit = config.build?.cssCodeSplit === false;
1955
+ },
1956
+ async closeBundle() {
1957
+ const devClientManifest = {
1958
+ "@vite/client": {
1959
+ isEntry: true,
1960
+ file: "@vite/client",
1961
+ css: [],
1962
+ module: true,
1963
+ resourceType: "script"
1964
+ },
1965
+ ...nuxt.options.features.noScripts === "all" ? {} : {
1966
+ [clientEntry]: {
1967
+ isEntry: true,
1968
+ file: clientEntry,
1969
+ module: true,
1970
+ resourceType: "script"
1971
+ }
1972
+ }
1973
+ };
1974
+ const clientDist = resolve(nuxt.options.buildDir, "dist/client");
1975
+ const serverDist = resolve(nuxt.options.buildDir, "dist/server");
1976
+ const manifestFile = resolve(clientDist, "manifest.json");
1977
+ const clientManifest = nuxt.options.dev ? devClientManifest : JSON.parse(readFileSync(manifestFile, "utf-8"));
1978
+ const manifestEntries = Object.values(clientManifest);
1979
+ const buildAssetsDir = withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir));
1980
+ const BASE_RE = new RegExp(`^${escapeStringRegexp(buildAssetsDir)}`);
1981
+ for (const entry of manifestEntries) {
1982
+ entry.file &&= entry.file.replace(BASE_RE, "");
1983
+ for (const item of ["css", "assets"]) {
1984
+ entry[item] &&= entry[item].map((i) => i.replace(BASE_RE, ""));
1985
+ }
1986
+ }
1987
+ await mkdir(serverDist, { recursive: true });
1988
+ if (disableCssCodeSplit) {
1989
+ for (const entry of manifestEntries) {
1990
+ if (entry.file?.endsWith(".css")) {
1991
+ clientManifest[key].css ||= [];
1992
+ clientManifest[key].css.push(entry.file);
1993
+ break;
1994
+ }
1995
+ }
1996
+ }
1997
+ const manifest = normalizeViteManifest(clientManifest);
1998
+ await nuxt.callHook("build:manifest", manifest);
1999
+ const precomputed = precomputeDependencies(manifest);
2000
+ await writeFile(resolve(serverDist, "client.manifest.mjs"), "export default " + serialize(manifest), "utf8");
2001
+ await writeFile(resolve(serverDist, "client.precomputed.mjs"), "export default " + serialize(precomputed), "utf8");
2002
+ if (!nuxt.options.dev) {
2003
+ await rm(manifestFile, { force: true });
2004
+ }
2005
+ }
2006
+ };
2007
+ }
2008
+
1931
2009
  const bundle = async (nuxt) => {
1932
2010
  const useAsyncEntry = nuxt.options.experimental.asyncEntry || nuxt.options.dev;
1933
2011
  const entry = await resolvePath(resolve(nuxt.options.appDir, useAsyncEntry ? "entry.async" : "entry"));
@@ -1961,94 +2039,188 @@ const bundle = async (nuxt) => {
1961
2039
  const mockEmpty = resolveModulePath("mocked-exports/empty", { from: import.meta.url });
1962
2040
  const helper = nuxt.options.nitro.imports !== false ? "" : "globalThis.";
1963
2041
  const isIgnored = createIsIgnored(nuxt);
1964
- const ctx = {
1965
- nuxt,
1966
- entry,
1967
- config: vite.mergeConfig(
1968
- {
1969
- logLevel: logLevelMap[nuxt.options.logLevel] ?? logLevelMap.info,
1970
- experimental: {
1971
- renderBuiltUrl: (filename2, { type, hostType, ssr }) => {
1972
- if (hostType !== "js") {
2042
+ const serverEntry = nuxt.options.ssr ? entry : await resolvePath(resolve(nuxt.options.appDir, "entry-spa"));
2043
+ const config = mergeConfig(
2044
+ {
2045
+ base: nuxt.options.dev ? joinURL(nuxt.options.app.baseURL.replace(/^\.\//, "/") || "/", nuxt.options.app.buildAssetsDir) : void 0,
2046
+ logLevel: logLevelMap[nuxt.options.logLevel] ?? logLevelMap.info,
2047
+ experimental: {
2048
+ renderBuiltUrl: (filename2, { type, hostType, ssr: ssr2 }) => {
2049
+ if (hostType !== "js") {
2050
+ return { relative: true };
2051
+ }
2052
+ if (!ssr2) {
2053
+ if (type === "asset") {
1973
2054
  return { relative: true };
1974
2055
  }
1975
- if (!ssr) {
1976
- if (type === "asset") {
1977
- return { relative: true };
1978
- }
1979
- return { runtime: `globalThis.__publicAssetsURL(${JSON.stringify(filename2)})` };
1980
- }
1981
- if (type === "public") {
1982
- return { runtime: `${helper}__publicAssetsURL(${JSON.stringify(filename2)})` };
1983
- }
1984
- if (type === "asset") {
1985
- const relativeFilename = filename2.replace(withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir)), "");
1986
- return { runtime: `${helper}__buildAssetsURL(${JSON.stringify(relativeFilename)})` };
2056
+ return { runtime: `globalThis.__publicAssetsURL(${JSON.stringify(filename2)})` };
2057
+ }
2058
+ if (type === "public") {
2059
+ return { runtime: `${helper}__publicAssetsURL(${JSON.stringify(filename2)})` };
2060
+ }
2061
+ if (type === "asset") {
2062
+ const relativeFilename = filename2.replace(withTrailingSlash(withoutLeadingSlash(nuxt.options.app.buildAssetsDir)), "");
2063
+ return { runtime: `${helper}__buildAssetsURL(${JSON.stringify(relativeFilename)})` };
2064
+ }
2065
+ }
2066
+ },
2067
+ ...nuxt.options.experimental.viteEnvironmentApi ? {
2068
+ builder: {
2069
+ async buildApp(builder) {
2070
+ const environments = Object.values(builder.environments);
2071
+ for (const environment of environments) {
2072
+ logger.restoreAll();
2073
+ await builder.build(environment);
2074
+ logger.wrapAll();
2075
+ await nuxt.callHook("vite:compiled");
1987
2076
  }
1988
2077
  }
1989
2078
  },
1990
- resolve: {
1991
- alias: {
1992
- [basename(nuxt.options.dir.assets)]: resolve(nuxt.options.srcDir, nuxt.options.dir.assets),
1993
- ...nuxt.options.alias,
1994
- "#app": nuxt.options.appDir,
1995
- "web-streams-polyfill/ponyfill/es2018": mockEmpty,
1996
- // Cannot destructure property 'AbortController' of ..
1997
- "abort-controller": mockEmpty
2079
+ environments: {
2080
+ client: {
2081
+ consumer: "client",
2082
+ keepProcessEnv: false,
2083
+ dev: {
2084
+ warmup: [entry]
2085
+ },
2086
+ ...clientEnvironment(nuxt, entry)
1998
2087
  },
1999
- dedupe: [
2000
- "vue"
2001
- ]
2088
+ ssr: {
2089
+ consumer: "server",
2090
+ dev: {
2091
+ warmup: [serverEntry]
2092
+ },
2093
+ ...ssrEnvironment(nuxt, serverEntry)
2094
+ }
2002
2095
  },
2003
- css: await resolveCSSOptions(nuxt),
2004
- define: {
2005
- __NUXT_VERSION__: JSON.stringify(nuxt._version),
2006
- __NUXT_ASYNC_CONTEXT__: nuxt.options.experimental.asyncContext
2096
+ ssr: ssr(nuxt)
2097
+ } : {},
2098
+ resolve: {
2099
+ alias: {
2100
+ [basename(nuxt.options.dir.assets)]: resolve(nuxt.options.srcDir, nuxt.options.dir.assets),
2101
+ ...nuxt.options.alias,
2102
+ "#app": nuxt.options.appDir,
2103
+ "web-streams-polyfill/ponyfill/es2018": mockEmpty,
2104
+ // Cannot destructure property 'AbortController' of ..
2105
+ "abort-controller": mockEmpty
2007
2106
  },
2008
- build: {
2009
- copyPublicDir: false,
2010
- rollupOptions: {
2011
- output: {
2012
- sourcemapIgnoreList: (relativeSourcePath) => {
2013
- return relativeSourcePath.includes("node_modules") || relativeSourcePath.includes(nuxt.options.buildDir);
2014
- },
2015
- sanitizeFileName: sanitizeFilePath,
2016
- // https://github.com/vitejs/vite/tree/main/packages/vite/src/node/build.ts#L464-L478
2017
- assetFileNames: nuxt.options.dev ? void 0 : (chunk) => withoutLeadingSlash(join(nuxt.options.app.buildAssetsDir, `${sanitizeFilePath(filename$1(chunk.names[0]))}.[hash].[ext]`))
2018
- }
2019
- },
2020
- // @ts-expect-error non-public property
2021
- watch: vite.rolldownVersion ? { exclude: [...nuxt.options.ignore, /[\\/]node_modules[\\/]/] } : {
2022
- chokidar: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
2023
- exclude: nuxt.options.ignore
2107
+ dedupe: [
2108
+ "vue"
2109
+ ]
2110
+ },
2111
+ // TODO: devSourcemap
2112
+ css: await resolveCSSOptions(nuxt),
2113
+ define: {
2114
+ __NUXT_VERSION__: JSON.stringify(nuxt._version),
2115
+ __NUXT_ASYNC_CONTEXT__: nuxt.options.experimental.asyncContext
2116
+ },
2117
+ build: {
2118
+ copyPublicDir: false,
2119
+ rollupOptions: {
2120
+ output: {
2121
+ sourcemapIgnoreList: (relativeSourcePath) => {
2122
+ return relativeSourcePath.includes("node_modules") || relativeSourcePath.includes(nuxt.options.buildDir);
2123
+ },
2124
+ sanitizeFileName: sanitizeFilePath,
2125
+ // https://github.com/vitejs/vite/tree/main/packages/vite/src/node/build.ts#L464-L478
2126
+ assetFileNames: nuxt.options.dev ? void 0 : (chunk) => withoutLeadingSlash(join(nuxt.options.app.buildAssetsDir, `${sanitizeFilePath(filename$1(chunk.names[0]))}.[hash].[ext]`))
2024
2127
  }
2025
2128
  },
2026
- plugins: [
2027
- // add resolver for files in public assets directories
2028
- PublicDirsPlugin({
2029
- dev: nuxt.options.dev,
2030
- baseURL: nuxt.options.app.baseURL
2031
- }),
2032
- ReplacePlugin(),
2033
- LayerDepOptimizePlugin(nuxt),
2034
- SSRStylesPlugin(nuxt),
2035
- EnvironmentsPlugin(nuxt)
2036
- ],
2037
- server: {
2038
- watch: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
2039
- fs: {
2040
- allow: [...new Set(allowDirs)]
2041
- }
2129
+ // @ts-expect-error non-public property
2130
+ watch: vite.rolldownVersion ? { exclude: [...nuxt.options.ignore, /[\\/]node_modules[\\/]/] } : {
2131
+ chokidar: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
2132
+ exclude: nuxt.options.ignore
2042
2133
  }
2043
2134
  },
2044
- viteConfig
2045
- )
2046
- };
2135
+ plugins: [
2136
+ ...nuxt.options.experimental.viteEnvironmentApi ? [
2137
+ vuePlugin(viteConfig.vue),
2138
+ viteJsxPlugin(viteConfig.vueJsx),
2139
+ ViteNodePlugin(nuxt),
2140
+ ClientManifestPlugin(nuxt),
2141
+ DevServerPlugin(nuxt)
2142
+ ] : [],
2143
+ // add resolver for files in public assets directories
2144
+ PublicDirsPlugin({
2145
+ dev: nuxt.options.dev,
2146
+ baseURL: nuxt.options.app.baseURL
2147
+ }),
2148
+ ReplacePlugin(),
2149
+ LayerDepOptimizePlugin(nuxt),
2150
+ SSRStylesPlugin(nuxt),
2151
+ EnvironmentsPlugin(nuxt),
2152
+ ...nuxt.options.experimental.viteEnvironmentApi ? [
2153
+ // Add type-checking
2154
+ VitePluginCheckerPlugin(nuxt),
2155
+ // server-only plugins
2156
+ VueFeatureFlagsPlugin(nuxt),
2157
+ // tell rollup's nitro build about the original sources of the generated vite server build
2158
+ SourcemapPreserverPlugin(nuxt),
2159
+ // client-only plugins
2160
+ DevStyleSSRPlugin({
2161
+ srcDir: nuxt.options.srcDir,
2162
+ buildAssetsURL: joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir)
2163
+ }),
2164
+ RuntimePathsPlugin(),
2165
+ // Type checking client panel
2166
+ TypeCheckPlugin(nuxt),
2167
+ ModulePreloadPolyfillPlugin(),
2168
+ // ensure changes in chunks do not invalidate whole build
2169
+ StableEntryPlugin(nuxt),
2170
+ AnalyzePlugin(nuxt)
2171
+ ] : []
2172
+ ],
2173
+ appType: "custom",
2174
+ server: {
2175
+ middlewareMode: true,
2176
+ watch: { ...nuxt.options.watchers.chokidar, ignored: [isIgnored, /[\\/]node_modules[\\/]/] },
2177
+ fs: {
2178
+ allow: [...new Set(allowDirs)]
2179
+ }
2180
+ }
2181
+ },
2182
+ nuxt.options.experimental.viteEnvironmentApi ? {
2183
+ ...viteConfig,
2184
+ environments: {
2185
+ ssr: $server,
2186
+ client: $client
2187
+ }
2188
+ } : viteConfig
2189
+ );
2047
2190
  if (!nuxt.options.dev) {
2048
- ctx.config.server.watch = void 0;
2049
- ctx.config.build.watch = void 0;
2191
+ config.server.watch = void 0;
2192
+ config.build.watch = void 0;
2050
2193
  }
2194
+ const ctx = { nuxt, entry, config };
2051
2195
  await nuxt.callHook("vite:extend", ctx);
2196
+ if (nuxt.options.experimental.viteEnvironmentApi) {
2197
+ await handleEnvironments(nuxt, config);
2198
+ } else {
2199
+ await handleSerialBuilds(nuxt, ctx);
2200
+ }
2201
+ };
2202
+ async function handleEnvironments(nuxt, config) {
2203
+ config.customLogger = createViteLogger(config);
2204
+ config.configFile = false;
2205
+ for (const environment of ["client", "ssr"]) {
2206
+ const environments = { [environment]: config.environments[environment] };
2207
+ const strippedConfig = { ...config, environments };
2208
+ const ctx = { isServer: environment === "ssr", isClient: environment === "client" };
2209
+ await nuxt.hooks.callHook("vite:extendConfig", strippedConfig, ctx);
2210
+ await nuxt.hooks.callHook("vite:configResolved", strippedConfig, ctx);
2211
+ }
2212
+ if (!nuxt.options.dev) {
2213
+ const builder = await createBuilder(config);
2214
+ await builder.buildApp();
2215
+ return;
2216
+ }
2217
+ await withLogs(async () => {
2218
+ const server = await createServer(config);
2219
+ await server.environments.ssr.pluginContainer.buildStart({});
2220
+ }, "Vite dev server built");
2221
+ await writeDevServer(nuxt);
2222
+ }
2223
+ async function handleSerialBuilds(nuxt, ctx) {
2052
2224
  nuxt.hook("vite:serverCreated", (server, env) => {
2053
2225
  if (nuxt.options.vite.warmupEntry !== false) {
2054
2226
  useNitro().hooks.hookOnce("compiled", () => {
@@ -2059,7 +2231,7 @@ const bundle = async (nuxt) => {
2059
2231
  });
2060
2232
  await withLogs(() => buildClient(nuxt, ctx), "Vite client built", nuxt.options.dev);
2061
2233
  await withLogs(() => buildServer(nuxt, ctx), "Vite server built", nuxt.options.dev);
2062
- };
2234
+ }
2063
2235
  async function withLogs(fn, message, enabled = true) {
2064
2236
  if (!enabled) {
2065
2237
  return fn();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/vite-builder-nightly",
3
- "version": "4.2.0-29344710.84b82c47",
3
+ "version": "4.2.0-29345108.b399de2f",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",
@@ -21,7 +21,7 @@
21
21
  "dist"
22
22
  ],
23
23
  "devDependencies": {
24
- "@nuxt/schema": "npm:@nuxt/schema-nightly@4.2.0-29344710.84b82c47",
24
+ "@nuxt/schema": "npm:@nuxt/schema-nightly@4.2.0-29345108.b399de2f",
25
25
  "nitropack": "2.12.7",
26
26
  "rolldown": "1.0.0-beta.42",
27
27
  "rollup": "4.52.4",
@@ -29,7 +29,7 @@
29
29
  "vue": "3.5.22"
30
30
  },
31
31
  "dependencies": {
32
- "@nuxt/kit": "npm:@nuxt/kit-nightly@4.2.0-29344710.84b82c47",
32
+ "@nuxt/kit": "npm:@nuxt/kit-nightly@4.2.0-29345108.b399de2f",
33
33
  "@rollup/plugin-replace": "^6.0.2",
34
34
  "@vitejs/plugin-vue": "^6.0.1",
35
35
  "@vitejs/plugin-vue-jsx": "^5.1.1",
@@ -61,7 +61,7 @@
61
61
  "vue-bundle-renderer": "^2.2.0"
62
62
  },
63
63
  "peerDependencies": {
64
- "nuxt": "npm:nuxt-nightly@4.2.0-29344710.84b82c47",
64
+ "nuxt": "npm:nuxt-nightly@4.2.0-29345108.b399de2f",
65
65
  "rolldown": "^1.0.0-beta.38",
66
66
  "vue": "^3.3.4"
67
67
  },