vite 5.1.0-beta.2 → 5.1.0-beta.4

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.
@@ -1,6 +1,6 @@
1
1
  import fs$l, { promises as promises$1 } from 'node:fs';
2
2
  import fsp from 'node:fs/promises';
3
- import path$o, { posix as posix$1, isAbsolute as isAbsolute$2, join as join$2, extname as extname$1, dirname as dirname$2, relative as relative$2, basename as basename$2 } from 'node:path';
3
+ import path$o, { posix as posix$1, isAbsolute as isAbsolute$2, dirname as dirname$2, join as join$2, extname as extname$1, relative as relative$2, basename as basename$2 } from 'node:path';
4
4
  import { fileURLToPath, URL as URL$3, parse as parse$i, pathToFileURL } from 'node:url';
5
5
  import { promisify as promisify$4, format as format$2, inspect } from 'node:util';
6
6
  import { performance } from 'node:perf_hooks';
@@ -17,7 +17,7 @@ import { createServer as createServer$2, get as get$1 } from 'node:https';
17
17
  import require$$0$6 from 'util';
18
18
  import require$$4$1 from 'net';
19
19
  import require$$0$9 from 'url';
20
- import require$$1$1 from 'http';
20
+ import require$$1 from 'http';
21
21
  import require$$0$7 from 'stream';
22
22
  import require$$2 from 'os';
23
23
  import require$$2$1 from 'child_process';
@@ -25,23 +25,22 @@ import os$4 from 'node:os';
25
25
  import { exec } from 'node:child_process';
26
26
  import { createHash as createHash$2 } from 'node:crypto';
27
27
  import { promises } from 'node:dns';
28
- import { CLIENT_ENTRY, VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER, OPTIMIZABLE_ENTRY_RE, wildcardHosts, loopbackHosts, FS_PREFIX, CLIENT_PUBLIC_PATH, ENV_PUBLIC_PATH, DEFAULT_ASSETS_INLINE_LIMIT, CSS_LANGS_RE, ESBUILD_MODULES_TARGET, SPECIAL_QUERY_RE, ENV_ENTRY, DEP_VERSION_RE, DEFAULT_MAIN_FIELDS, DEFAULT_EXTENSIONS, KNOWN_ASSET_TYPES, JS_TYPES_RE, METADATA_FILENAME, VITE_PACKAGE_DIR, DEFAULT_DEV_PORT, CLIENT_DIR, VERSION as VERSION$1, DEFAULT_PREVIEW_PORT, DEFAULT_ASSETS_RE, DEFAULT_CONFIG_FILES } from '../constants.js';
28
+ import { CLIENT_ENTRY, VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER, OPTIMIZABLE_ENTRY_RE, wildcardHosts, loopbackHosts, FS_PREFIX, CLIENT_PUBLIC_PATH, ENV_PUBLIC_PATH, DEFAULT_ASSETS_INLINE_LIMIT, CSS_LANGS_RE, ESBUILD_MODULES_TARGET, SPECIAL_QUERY_RE, ENV_ENTRY, DEP_VERSION_RE, DEFAULT_MAIN_FIELDS, DEFAULT_EXTENSIONS, KNOWN_ASSET_TYPES, JS_TYPES_RE, METADATA_FILENAME, VITE_PACKAGE_DIR, DEFAULT_DEV_PORT, CLIENT_DIR, VERSION, DEFAULT_PREVIEW_PORT, DEFAULT_ASSETS_RE, DEFAULT_CONFIG_FILES } from '../constants.js';
29
29
  import require$$0$a from 'crypto';
30
30
  import require$$0$8, { createRequire as createRequire$2 } from 'module';
31
31
  import assert$1 from 'node:assert';
32
32
  import v8 from 'node:v8';
33
+ import { Worker as Worker$1 } from 'node:worker_threads';
33
34
  import { Buffer as Buffer$1 } from 'node:buffer';
34
- import { VERSION } from 'rollup';
35
35
  import { parseAst, parseAstAsync } from 'rollup/parseAst';
36
36
  import * as qs from 'querystring';
37
37
  import readline from 'node:readline';
38
38
  import { EventEmitter as EventEmitter$4 } from 'node:events';
39
39
  import require$$0$b from 'zlib';
40
40
  import require$$0$c from 'buffer';
41
- import require$$1$2 from 'https';
41
+ import require$$1$1 from 'https';
42
42
  import require$$4$2 from 'tls';
43
43
  import zlib$1, { gzip } from 'node:zlib';
44
- import require$$1 from 'worker_threads';
45
44
 
46
45
  import { fileURLToPath as __cjs_fileURLToPath } from 'node:url';
47
46
  import { dirname as __cjs_dirname } from 'node:path';
@@ -11837,7 +11836,7 @@ function loadPackageData(pkgPath) {
11837
11836
  });
11838
11837
  }
11839
11838
  else {
11840
- hasSideEffects = () => true;
11839
+ hasSideEffects = () => null;
11841
11840
  }
11842
11841
  const pkg = {
11843
11842
  dir: pkgDir,
@@ -12047,7 +12046,12 @@ function isOptimizable(id, optimizeDeps) {
12047
12046
  const bareImportRE = /^(?![a-zA-Z]:)[\w@](?!.*:\/\/)/;
12048
12047
  const deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//;
12049
12048
  // TODO: use import()
12050
- const _require$2 = createRequire$1(import.meta.url);
12049
+ const _require$1 = createRequire$1(import.meta.url);
12050
+ function resolveDependencyVersion(dep, pkgRelativePath = '../../package.json') {
12051
+ const pkgPath = path$o.resolve(_require$1.resolve(dep), pkgRelativePath);
12052
+ return JSON.parse(fs$l.readFileSync(pkgPath, 'utf-8')).version;
12053
+ }
12054
+ const rollupVersion = resolveDependencyVersion('rollup');
12051
12055
  // set in bin/vite.js
12052
12056
  const filter = process.env.VITE_DEBUG_FILTER;
12053
12057
  const DEBUG = process.env.DEBUG;
@@ -12226,7 +12230,7 @@ function prettifyUrl(url, root) {
12226
12230
  url = removeTimestampQuery(url);
12227
12231
  const isAbsoluteFile = url.startsWith(root);
12228
12232
  if (isAbsoluteFile || url.startsWith(FS_PREFIX)) {
12229
- const file = path$o.relative(root, isAbsoluteFile ? url : fsPathFromId(url));
12233
+ const file = path$o.posix.relative(root, isAbsoluteFile ? url : fsPathFromId(url));
12230
12234
  return colors$1.dim(file);
12231
12235
  }
12232
12236
  else {
@@ -12770,7 +12774,7 @@ const requireResolveFromRootWithFallback = (root, id) => {
12770
12774
  }
12771
12775
  // actually resolve
12772
12776
  // Search in the root directory first, and fallback to the default require paths.
12773
- return _require$2.resolve(id, { paths: [root, _dirname] });
12777
+ return _require$1.resolve(id, { paths: [root, _dirname] });
12774
12778
  };
12775
12779
  function emptyCssComments(raw) {
12776
12780
  return raw.replace(multilineCommentsRE, blankReplacer);
@@ -14863,101 +14867,235 @@ async function reloadOnTsconfigChange(changedFile) {
14863
14867
  }
14864
14868
  }
14865
14869
 
14866
- var dist$1 = {};
14867
-
14868
- var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
14869
- return (mod && mod.__esModule) ? mod : { "default": mod };
14870
- };
14871
- Object.defineProperty(dist$1, "__esModule", { value: true });
14872
- var Worker_1 = dist$1.Worker = void 0;
14873
- const os_1 = __importDefault(require$$2);
14874
- const worker_threads_1 = require$$1;
14875
- class Worker {
14876
- constructor(fn, options = {}) {
14877
- this.code = genWorkerCode(fn);
14878
- this.max = options.max || Math.max(1, os_1.default.cpus().length - 1);
14879
- this.pool = [];
14880
- this.idlePool = [];
14881
- this.queue = [];
14882
- }
14883
- async run(...args) {
14884
- const worker = await this._getAvailableWorker();
14885
- return new Promise((resolve, reject) => {
14886
- worker.currentResolve = resolve;
14887
- worker.currentReject = reject;
14888
- worker.postMessage(args);
14889
- });
14890
- }
14891
- stop() {
14892
- this.pool.forEach((w) => w.unref());
14893
- this.queue.forEach(([_, reject]) => reject(new Error('Main worker pool stopped before a worker was available.')));
14894
- this.pool = [];
14895
- this.idlePool = [];
14896
- this.queue = [];
14897
- }
14898
- async _getAvailableWorker() {
14899
- // has idle one?
14900
- if (this.idlePool.length) {
14901
- return this.idlePool.shift();
14902
- }
14903
- // can spawn more?
14904
- if (this.pool.length < this.max) {
14905
- const worker = new worker_threads_1.Worker(this.code, { eval: true });
14906
- worker.on('message', (res) => {
14907
- worker.currentResolve && worker.currentResolve(res);
14908
- worker.currentResolve = null;
14909
- this._assignDoneWorker(worker);
14910
- });
14911
- worker.on('error', (err) => {
14912
- worker.currentReject && worker.currentReject(err);
14913
- worker.currentReject = null;
14914
- });
14915
- worker.on('exit', (code) => {
14916
- const i = this.pool.indexOf(worker);
14917
- if (i > -1)
14918
- this.pool.splice(i, 1);
14919
- if (code !== 0 && worker.currentReject) {
14920
- worker.currentReject(new Error(`Wroker stopped with non-0 exit code ${code}`));
14921
- worker.currentReject = null;
14922
- }
14870
+ // src/realWorker.ts
14871
+ var Worker = class {
14872
+ /** @internal */
14873
+ _code;
14874
+ /** @internal */
14875
+ _parentFunctions;
14876
+ /** @internal */
14877
+ _max;
14878
+ /** @internal */
14879
+ _pool;
14880
+ /** @internal */
14881
+ _idlePool;
14882
+ /** @internal */
14883
+ _queue;
14884
+ constructor(fn, options = {}) {
14885
+ this._code = genWorkerCode(fn, options.parentFunctions ?? {});
14886
+ this._parentFunctions = options.parentFunctions ?? {};
14887
+ const defaultMax = Math.max(
14888
+ 1,
14889
+ // os.availableParallelism is available from Node.js 18.14.0
14890
+ (os$4.availableParallelism?.() ?? os$4.cpus().length) - 1
14891
+ );
14892
+ this._max = options.max || defaultMax;
14893
+ this._pool = [];
14894
+ this._idlePool = [];
14895
+ this._queue = [];
14896
+ }
14897
+ async run(...args) {
14898
+ const worker = await this._getAvailableWorker();
14899
+ return new Promise((resolve, reject) => {
14900
+ worker.currentResolve = resolve;
14901
+ worker.currentReject = reject;
14902
+ worker.postMessage({ type: "run", args });
14903
+ });
14904
+ }
14905
+ stop() {
14906
+ this._pool.forEach((w) => w.unref());
14907
+ this._queue.forEach(
14908
+ ([, reject]) => reject(
14909
+ new Error("Main worker pool stopped before a worker was available.")
14910
+ )
14911
+ );
14912
+ this._pool = [];
14913
+ this._idlePool = [];
14914
+ this._queue = [];
14915
+ }
14916
+ /** @internal */
14917
+ async _getAvailableWorker() {
14918
+ if (this._idlePool.length) {
14919
+ return this._idlePool.shift();
14920
+ }
14921
+ if (this._pool.length < this._max) {
14922
+ const worker = new Worker$1(this._code, { eval: true });
14923
+ worker.on("message", async (args) => {
14924
+ if (args.type === "run") {
14925
+ if ("result" in args) {
14926
+ worker.currentResolve && worker.currentResolve(args.result);
14927
+ worker.currentResolve = null;
14928
+ } else {
14929
+ if (args.error instanceof ReferenceError) {
14930
+ args.error.message += ". Maybe you forgot to pass the function to parentFunction?";
14931
+ }
14932
+ worker.currentReject && worker.currentReject(args.error);
14933
+ worker.currentReject = null;
14934
+ }
14935
+ this._assignDoneWorker(worker);
14936
+ } else if (args.type === "parentFunction") {
14937
+ try {
14938
+ const result = await this._parentFunctions[args.name](...args.args);
14939
+ worker.postMessage({ type: "parentFunction", id: args.id, result });
14940
+ } catch (e) {
14941
+ worker.postMessage({
14942
+ type: "parentFunction",
14943
+ id: args.id,
14944
+ error: e
14923
14945
  });
14924
- this.pool.push(worker);
14925
- return worker;
14926
- }
14927
- // no one is available, we have to wait
14928
- let resolve;
14929
- let reject;
14930
- const onWorkerAvailablePromise = new Promise((r, rj) => {
14931
- resolve = r;
14932
- reject = rj;
14933
- });
14934
- this.queue.push([resolve, reject]);
14935
- return onWorkerAvailablePromise;
14936
- }
14937
- _assignDoneWorker(worker) {
14938
- // someone's waiting already?
14939
- if (this.queue.length) {
14940
- const [resolve] = this.queue.shift();
14941
- resolve(worker);
14942
- return;
14946
+ }
14943
14947
  }
14944
- // take a rest.
14945
- this.idlePool.push(worker);
14948
+ });
14949
+ worker.on("error", (err) => {
14950
+ worker.currentReject && worker.currentReject(err);
14951
+ worker.currentReject = null;
14952
+ });
14953
+ worker.on("exit", (code) => {
14954
+ const i = this._pool.indexOf(worker);
14955
+ if (i > -1)
14956
+ this._pool.splice(i, 1);
14957
+ if (code !== 0 && worker.currentReject) {
14958
+ worker.currentReject(
14959
+ new Error(`Worker stopped with non-0 exit code ${code}`)
14960
+ );
14961
+ worker.currentReject = null;
14962
+ }
14963
+ });
14964
+ this._pool.push(worker);
14965
+ return worker;
14946
14966
  }
14947
- }
14948
- Worker_1 = dist$1.Worker = Worker;
14949
- function genWorkerCode(fn) {
14950
- return `
14951
- const doWork = ${fn.toString()}
14952
-
14967
+ let resolve;
14968
+ let reject;
14969
+ const onWorkerAvailablePromise = new Promise((r, rj) => {
14970
+ resolve = r;
14971
+ reject = rj;
14972
+ });
14973
+ this._queue.push([resolve, reject]);
14974
+ return onWorkerAvailablePromise;
14975
+ }
14976
+ /** @internal */
14977
+ _assignDoneWorker(worker) {
14978
+ if (this._queue.length) {
14979
+ const [resolve] = this._queue.shift();
14980
+ resolve(worker);
14981
+ return;
14982
+ }
14983
+ this._idlePool.push(worker);
14984
+ }
14985
+ };
14986
+ function genWorkerCode(fn, parentFunctions) {
14987
+ const createParentFunctionCaller = (parentPort) => {
14988
+ let id = 0;
14989
+ const resolvers = /* @__PURE__ */ new Map();
14990
+ const call = (key) => async (...args) => {
14991
+ id++;
14992
+ let resolve, reject;
14993
+ const promise = new Promise((res, rej) => {
14994
+ resolve = res;
14995
+ reject = rej;
14996
+ });
14997
+ resolvers.set(id, { resolve, reject });
14998
+ parentPort.postMessage({ type: "parentFunction", id, name: key, args });
14999
+ return await promise;
15000
+ };
15001
+ const receive = (id2, args) => {
15002
+ if (resolvers.has(id2)) {
15003
+ const { resolve, reject } = resolvers.get(id2);
15004
+ resolvers.delete(id2);
15005
+ if ("result" in args) {
15006
+ resolve(args.result);
15007
+ } else {
15008
+ reject(args.error);
15009
+ }
15010
+ }
15011
+ };
15012
+ return { call, receive };
15013
+ };
15014
+ return `
14953
15015
  const { parentPort } = require('worker_threads')
15016
+ const parentFunctionCaller = (${createParentFunctionCaller.toString()})(parentPort)
15017
+
15018
+ const doWork = (() => {
15019
+ ${Object.keys(parentFunctions).map(
15020
+ (key) => `const ${key} = parentFunctionCaller.call(${JSON.stringify(key)});`
15021
+ ).join("\n")}
15022
+ return (${fn.toString()})()
15023
+ })()
14954
15024
 
14955
15025
  parentPort.on('message', async (args) => {
14956
- const res = await doWork(...args)
14957
- parentPort.postMessage(res)
15026
+ if (args.type === 'run') {
15027
+ try {
15028
+ const res = await doWork(...args.args)
15029
+ parentPort.postMessage({ type: 'run', result: res })
15030
+ } catch (e) {
15031
+ parentPort.postMessage({ type: 'run', error: e })
15032
+ }
15033
+ } else if (args.type === 'parentFunction') {
15034
+ parentFunctionCaller.receive(args.id, args)
15035
+ }
14958
15036
  })
14959
15037
  `;
14960
15038
  }
15039
+ var FakeWorker = class {
15040
+ /** @internal */
15041
+ _fn;
15042
+ constructor(fn, options = {}) {
15043
+ const argsAndCode = genFakeWorkerArgsAndCode(
15044
+ fn,
15045
+ options.parentFunctions ?? {}
15046
+ );
15047
+ const require2 = createRequire$1(import.meta.url);
15048
+ this._fn = new Function(...argsAndCode)(require2, options.parentFunctions);
15049
+ }
15050
+ async run(...args) {
15051
+ try {
15052
+ return await this._fn(...args);
15053
+ } catch (err) {
15054
+ if (err instanceof ReferenceError) {
15055
+ err.message += ". Maybe you forgot to pass the function to parentFunction?";
15056
+ }
15057
+ throw err;
15058
+ }
15059
+ }
15060
+ stop() {
15061
+ }
15062
+ };
15063
+ function genFakeWorkerArgsAndCode(fn, parentFunctions) {
15064
+ return [
15065
+ "require",
15066
+ "parentFunctions",
15067
+ `
15068
+ ${Object.keys(parentFunctions).map((key) => `const ${key} = parentFunctions[${JSON.stringify(key)}];`).join("\n")}
15069
+ return (${fn.toString()})()
15070
+ `
15071
+ ];
15072
+ }
15073
+
15074
+ // src/workerWithFallback.ts
15075
+ var WorkerWithFallback = class {
15076
+ /** @internal */
15077
+ _disableReal;
15078
+ /** @internal */
15079
+ _realWorker;
15080
+ /** @internal */
15081
+ _fakeWorker;
15082
+ /** @internal */
15083
+ _shouldUseFake;
15084
+ constructor(fn, options) {
15085
+ this._disableReal = options.max !== void 0 && options.max <= 0;
15086
+ this._realWorker = new Worker(fn, options);
15087
+ this._fakeWorker = new FakeWorker(fn, options);
15088
+ this._shouldUseFake = options.shouldUseFake;
15089
+ }
15090
+ async run(...args) {
15091
+ const useFake = this._disableReal || this._shouldUseFake(...args);
15092
+ return this[useFake ? "_fakeWorker" : "_realWorker"].run(...args);
15093
+ }
15094
+ stop() {
15095
+ this._realWorker.stop();
15096
+ this._fakeWorker.stop();
15097
+ }
15098
+ };
14961
15099
 
14962
15100
  let terserPath;
14963
15101
  const loadTerserPath = (root) => {
@@ -14980,7 +15118,7 @@ const loadTerserPath = (root) => {
14980
15118
  };
14981
15119
  function terserPlugin(config) {
14982
15120
  const { maxWorkers, ...terserOptions } = config.build.terserOptions;
14983
- const makeWorker = () => new Worker_1(async (terserPath, code, options) => {
15121
+ const makeWorker = () => new Worker(() => async (terserPath, code, options) => {
14984
15122
  // test fails when using `import`. maybe related: https://github.com/nodejs/node/issues/43205
14985
15123
  // eslint-disable-next-line no-restricted-globals -- this function runs inside cjs
14986
15124
  const terser = require(terserPath);
@@ -30813,28 +30951,33 @@ async function applyHtmlTransforms(html, hooks, ctx) {
30813
30951
  html = res.html || html;
30814
30952
  tags = res.tags;
30815
30953
  }
30816
- const headTags = [];
30817
- const headPrependTags = [];
30818
- const bodyTags = [];
30819
- const bodyPrependTags = [];
30954
+ let headTags;
30955
+ let headPrependTags;
30956
+ let bodyTags;
30957
+ let bodyPrependTags;
30820
30958
  for (const tag of tags) {
30821
- if (tag.injectTo === 'body') {
30822
- bodyTags.push(tag);
30823
- }
30824
- else if (tag.injectTo === 'body-prepend') {
30825
- bodyPrependTags.push(tag);
30826
- }
30827
- else if (tag.injectTo === 'head') {
30828
- headTags.push(tag);
30829
- }
30830
- else {
30831
- headPrependTags.push(tag);
30959
+ switch (tag.injectTo) {
30960
+ case 'body':
30961
+ (bodyTags ??= []).push(tag);
30962
+ break;
30963
+ case 'body-prepend':
30964
+ (bodyPrependTags ??= []).push(tag);
30965
+ break;
30966
+ case 'head':
30967
+ (headTags ??= []).push(tag);
30968
+ break;
30969
+ default:
30970
+ (headPrependTags ??= []).push(tag);
30832
30971
  }
30833
30972
  }
30834
- html = injectToHead(html, headPrependTags, true);
30835
- html = injectToHead(html, headTags);
30836
- html = injectToBody(html, bodyPrependTags, true);
30837
- html = injectToBody(html, bodyTags);
30973
+ if (headPrependTags)
30974
+ html = injectToHead(html, headPrependTags, true);
30975
+ if (headTags)
30976
+ html = injectToHead(html, headTags);
30977
+ if (bodyPrependTags)
30978
+ html = injectToBody(html, bodyPrependTags, true);
30979
+ if (bodyTags)
30980
+ html = injectToBody(html, bodyTags);
30838
30981
  }
30839
30982
  }
30840
30983
  return html;
@@ -31006,6 +31149,7 @@ function cssPlugin(config) {
31006
31149
  tryIndex: false,
31007
31150
  extensions: [],
31008
31151
  });
31152
+ let preprocessorWorkerController;
31009
31153
  // warm up cache for resolved postcss config
31010
31154
  if (config.css?.transformer !== 'lightningcss') {
31011
31155
  resolvePostcssConfig(config);
@@ -31017,6 +31161,11 @@ function cssPlugin(config) {
31017
31161
  moduleCache = new Map();
31018
31162
  cssModulesCache.set(config, moduleCache);
31019
31163
  removedPureCssFilesCache.set(config, new Map());
31164
+ preprocessorWorkerController = createPreprocessorWorkerController(normalizeMaxWorkers(config.css.preprocessorMaxWorkers));
31165
+ preprocessorWorkerControllerCache.set(config, preprocessorWorkerController);
31166
+ },
31167
+ buildEnd() {
31168
+ preprocessorWorkerController?.close();
31020
31169
  },
31021
31170
  async load(id) {
31022
31171
  if (!isCSSRequest(id))
@@ -31066,7 +31215,7 @@ function cssPlugin(config) {
31066
31215
  }
31067
31216
  return url;
31068
31217
  };
31069
- const { code: css, modules, deps, map, } = await compileCSS(id, raw, config, urlReplacer);
31218
+ const { code: css, modules, deps, map, } = await compileCSS(id, raw, config, preprocessorWorkerController, urlReplacer);
31070
31219
  if (modules) {
31071
31220
  moduleCache.set(id, modules);
31072
31221
  }
@@ -31592,10 +31741,10 @@ function createCSSResolvers(config) {
31592
31741
  function getCssResolversKeys(resolvers) {
31593
31742
  return Object.keys(resolvers);
31594
31743
  }
31595
- async function compileCSSPreprocessors(id, lang, code, config) {
31744
+ async function compileCSSPreprocessors(id, lang, code, config, workerController) {
31596
31745
  const { preprocessorOptions, devSourcemap } = config.css ?? {};
31597
31746
  const atImportResolvers = getAtImportResolvers(config);
31598
- const preProcessor = preProcessors[lang];
31747
+ const preProcessor = workerController[lang];
31599
31748
  let opts = (preprocessorOptions && preprocessorOptions[lang]) || {};
31600
31749
  // support @import from node dependencies by default
31601
31750
  switch (lang) {
@@ -31644,7 +31793,7 @@ function getAtImportResolvers(config) {
31644
31793
  }
31645
31794
  return atImportResolvers;
31646
31795
  }
31647
- async function compileCSS(id, code, config, urlReplacer) {
31796
+ async function compileCSS(id, code, config, workerController, urlReplacer) {
31648
31797
  if (config.css?.transformer === 'lightningcss') {
31649
31798
  return compileLightningCSS(id, code, config, urlReplacer);
31650
31799
  }
@@ -31669,7 +31818,7 @@ async function compileCSS(id, code, config, urlReplacer) {
31669
31818
  // 2. pre-processors: sass etc.
31670
31819
  let preprocessorMap;
31671
31820
  if (isPreProcessor(lang)) {
31672
- const preprocessorResult = await compileCSSPreprocessors(id, lang, code, config);
31821
+ const preprocessorResult = await compileCSSPreprocessors(id, lang, code, config, workerController);
31673
31822
  code = preprocessorResult.code;
31674
31823
  preprocessorMap = preprocessorResult.map;
31675
31824
  preprocessorResult.deps?.forEach((dep) => deps.add(dep));
@@ -31701,7 +31850,7 @@ async function compileCSS(id, code, config, urlReplacer) {
31701
31850
  const code = await fs$l.promises.readFile(id, 'utf-8');
31702
31851
  const lang = id.match(CSS_LANGS_RE)?.[1];
31703
31852
  if (isPreProcessor(lang)) {
31704
- const result = await compileCSSPreprocessors(id, lang, code, config);
31853
+ const result = await compileCSSPreprocessors(id, lang, code, config, workerController);
31705
31854
  result.deps?.forEach((dep) => deps.add(dep));
31706
31855
  // TODO: support source map
31707
31856
  return result.code;
@@ -31754,9 +31903,7 @@ async function compileCSS(id, code, config, urlReplacer) {
31754
31903
  // postcss is an unbundled dep and should be lazy imported
31755
31904
  postcssResult = await postcss.default(postcssPlugins).process(code, {
31756
31905
  ...postcssOptions,
31757
- parser: lang === 'sss'
31758
- ? loadPreprocessor("sugarss" /* PostCssDialectLang.sss */, config.root)
31759
- : postcssOptions.parser,
31906
+ parser: lang === 'sss' ? loadSss(config.root) : postcssOptions.parser,
31760
31907
  to: source,
31761
31908
  from: source,
31762
31909
  ...(devSourcemap
@@ -31851,14 +31998,24 @@ function createCachedImport(imp) {
31851
31998
  return cached;
31852
31999
  };
31853
32000
  }
31854
- const importPostcssImport = createCachedImport(() => import('./dep-AFY35plO.js').then(function (n) { return n.i; }));
31855
- const importPostcssModules = createCachedImport(() => import('./dep-7G7SPddr.js').then(function (n) { return n.i; }));
32001
+ const importPostcssImport = createCachedImport(() => import('./dep-y3MfcbcG.js').then(function (n) { return n.i; }));
32002
+ const importPostcssModules = createCachedImport(() => import('./dep-0RU5--AQ.js').then(function (n) { return n.i; }));
31856
32003
  const importPostcss = createCachedImport(() => import('postcss'));
32004
+ const preprocessorWorkerControllerCache = new WeakMap();
32005
+ let alwaysFakeWorkerWorkerControllerCache;
31857
32006
  /**
31858
32007
  * @experimental
31859
32008
  */
31860
32009
  async function preprocessCSS(code, filename, config) {
31861
- return await compileCSS(filename, code, config);
32010
+ let workerController = preprocessorWorkerControllerCache.get(config);
32011
+ if (!workerController) {
32012
+ // if workerController doesn't exist, create a workerController that always uses fake workers
32013
+ // because fake workers doesn't require calling `.close` unlike real workers
32014
+ alwaysFakeWorkerWorkerControllerCache ||=
32015
+ createPreprocessorWorkerController(0);
32016
+ workerController = alwaysFakeWorkerWorkerControllerCache;
32017
+ }
32018
+ return await compileCSS(filename, code, config, workerController);
31862
32019
  }
31863
32020
  async function formatPostcssSourceMap(rawMap, file) {
31864
32021
  const inputFileDir = path$o.dirname(file);
@@ -32160,16 +32317,15 @@ async function hoistAtRules(css) {
32160
32317
  }
32161
32318
  return s.toString();
32162
32319
  }
32163
- const loadedPreprocessors = {};
32164
- // TODO: use dynamic import
32165
- const _require$1 = createRequire$1(import.meta.url);
32166
- function loadPreprocessor(lang, root) {
32167
- if (lang in loadedPreprocessors) {
32168
- return loadedPreprocessors[lang];
32320
+ const loadedPreprocessorPath = {};
32321
+ function loadPreprocessorPath(lang, root) {
32322
+ const cached = loadedPreprocessorPath[lang];
32323
+ if (cached) {
32324
+ return cached;
32169
32325
  }
32170
32326
  try {
32171
32327
  const resolved = requireResolveFromRootWithFallback(root, lang);
32172
- return (loadedPreprocessors[lang] = _require$1(resolved));
32328
+ return (loadedPreprocessorPath[lang] = resolved);
32173
32329
  }
32174
32330
  catch (e) {
32175
32331
  if (e.code === 'MODULE_NOT_FOUND') {
@@ -32183,6 +32339,14 @@ function loadPreprocessor(lang, root) {
32183
32339
  }
32184
32340
  }
32185
32341
  }
32342
+ let cachedSss;
32343
+ function loadSss(root) {
32344
+ if (cachedSss)
32345
+ return cachedSss;
32346
+ const sssPath = loadPreprocessorPath("sugarss" /* PostCssDialectLang.sss */, root);
32347
+ cachedSss = createRequire$1(import.meta.url)(sssPath);
32348
+ return cachedSss;
32349
+ }
32186
32350
  // in unix, scss might append `location.href` in environments that shim `location`
32187
32351
  // see https://github.com/sass/dart-sass/issues/710
32188
32352
  function cleanScssBugUrl(url) {
@@ -32214,78 +32378,124 @@ function fixScssBugImportValue(data) {
32214
32378
  return data;
32215
32379
  }
32216
32380
  // .scss/.sass processor
32217
- const scss = async (source, root, options, resolvers) => {
32218
- const render = loadPreprocessor("sass" /* PreprocessLang.sass */, root).render;
32219
- // NOTE: `sass` always runs it's own importer first, and only falls back to
32220
- // the `importer` option when it can't resolve a path
32221
- const internalImporter = (url, importer, done) => {
32381
+ const makeScssWorker = (resolvers, alias, maxWorkers) => {
32382
+ const internalImporter = async (url, importer, filename) => {
32222
32383
  importer = cleanScssBugUrl(importer);
32223
- resolvers.sass(url, importer).then((resolved) => {
32224
- if (resolved) {
32225
- rebaseUrls(resolved, options.filename, options.alias, '$', resolvers.sass)
32226
- .then((data) => done?.(fixScssBugImportValue(data)))
32227
- .catch((data) => done?.(data));
32384
+ const resolved = await resolvers.sass(url, importer);
32385
+ if (resolved) {
32386
+ try {
32387
+ const data = await rebaseUrls(resolved, filename, alias, '$', resolvers.sass);
32388
+ return fixScssBugImportValue(data);
32228
32389
  }
32229
- else {
32230
- done?.(null);
32390
+ catch (data) {
32391
+ return data;
32231
32392
  }
32232
- });
32233
- };
32234
- const importer = [internalImporter];
32235
- if (options.importer) {
32236
- Array.isArray(options.importer)
32237
- ? importer.unshift(...options.importer)
32238
- : importer.unshift(options.importer);
32239
- }
32240
- const { content: data, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap);
32241
- const finalOptions = {
32242
- ...options,
32243
- data,
32244
- file: options.filename,
32245
- outFile: options.filename,
32246
- importer,
32247
- ...(options.enableSourcemap
32248
- ? {
32249
- sourceMap: true,
32250
- omitSourceMapUrl: true,
32251
- sourceMapRoot: path$o.dirname(options.filename),
32252
- }
32253
- : {}),
32393
+ }
32394
+ else {
32395
+ return null;
32396
+ }
32254
32397
  };
32255
- try {
32256
- const result = await new Promise((resolve, reject) => {
32257
- render(finalOptions, (err, res) => {
32398
+ const worker = new WorkerWithFallback(() => async (sassPath, data,
32399
+ // additionalData can a function that is not cloneable but it won't be used
32400
+ options) => {
32401
+ // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
32402
+ const sass = require(sassPath);
32403
+ // eslint-disable-next-line no-restricted-globals
32404
+ const path = require('node:path');
32405
+ // NOTE: `sass` always runs it's own importer first, and only falls back to
32406
+ // the `importer` option when it can't resolve a path
32407
+ const _internalImporter = (url, importer, done) => {
32408
+ internalImporter(url, importer, options.filename).then((data) => done?.(data));
32409
+ };
32410
+ const importer = [_internalImporter];
32411
+ if (options.importer) {
32412
+ Array.isArray(options.importer)
32413
+ ? importer.unshift(...options.importer)
32414
+ : importer.unshift(options.importer);
32415
+ }
32416
+ const finalOptions = {
32417
+ ...options,
32418
+ data,
32419
+ file: options.filename,
32420
+ outFile: options.filename,
32421
+ importer,
32422
+ ...(options.enableSourcemap
32423
+ ? {
32424
+ sourceMap: true,
32425
+ omitSourceMapUrl: true,
32426
+ sourceMapRoot: path.dirname(options.filename),
32427
+ }
32428
+ : {}),
32429
+ };
32430
+ return new Promise((resolve, reject) => {
32431
+ sass.render(finalOptions, (err, res) => {
32258
32432
  if (err) {
32259
32433
  reject(err);
32260
32434
  }
32261
32435
  else {
32262
- resolve(res);
32436
+ resolve({
32437
+ css: res.css.toString(),
32438
+ map: res.map?.toString(),
32439
+ stats: res.stats,
32440
+ });
32263
32441
  }
32264
32442
  });
32265
32443
  });
32266
- const deps = result.stats.includedFiles.map((f) => cleanScssBugUrl(f));
32267
- const map = result.map
32268
- ? JSON.parse(result.map.toString())
32269
- : undefined;
32270
- return {
32271
- code: result.css.toString(),
32272
- map,
32273
- additionalMap,
32274
- deps,
32275
- };
32276
- }
32277
- catch (e) {
32278
- // normalize SASS error
32279
- e.message = `[sass] ${e.message}`;
32280
- e.id = e.file;
32281
- e.frame = e.formatted;
32282
- return { code: '', error: e, deps: [] };
32283
- }
32444
+ }, {
32445
+ parentFunctions: { internalImporter },
32446
+ shouldUseFake(_sassPath, _data, options) {
32447
+ // functions and importer is a function and is not serializable
32448
+ // in that case, fallback to running in main thread
32449
+ return !!((options.functions && Object.keys(options.functions).length > 0) ||
32450
+ (options.importer &&
32451
+ (!Array.isArray(options.importer) || options.importer.length > 0)));
32452
+ },
32453
+ max: maxWorkers,
32454
+ });
32455
+ return worker;
32456
+ };
32457
+ const scssProcessor = (maxWorkers) => {
32458
+ const workerMap = new Map();
32459
+ return {
32460
+ close() {
32461
+ for (const worker of workerMap.values()) {
32462
+ worker.stop();
32463
+ }
32464
+ },
32465
+ async process(source, root, options, resolvers) {
32466
+ const sassPath = loadPreprocessorPath("sass" /* PreprocessLang.sass */, root);
32467
+ if (!workerMap.has(options.alias)) {
32468
+ workerMap.set(options.alias, makeScssWorker(resolvers, options.alias, maxWorkers));
32469
+ }
32470
+ const worker = workerMap.get(options.alias);
32471
+ const { content: data, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap);
32472
+ const optionsWithoutAdditionalData = {
32473
+ ...options,
32474
+ additionalData: undefined,
32475
+ };
32476
+ try {
32477
+ const result = await worker.run(sassPath, data, optionsWithoutAdditionalData);
32478
+ const deps = result.stats.includedFiles.map((f) => cleanScssBugUrl(f));
32479
+ const map = result.map
32480
+ ? JSON.parse(result.map.toString())
32481
+ : undefined;
32482
+ return {
32483
+ code: result.css.toString(),
32484
+ map,
32485
+ additionalMap,
32486
+ deps,
32487
+ };
32488
+ }
32489
+ catch (e) {
32490
+ // normalize SASS error
32491
+ e.message = `[sass] ${e.message}`;
32492
+ e.id = e.file;
32493
+ e.frame = e.formatted;
32494
+ return { code: '', error: e, deps: [] };
32495
+ }
32496
+ },
32497
+ };
32284
32498
  };
32285
- const sass = (source, root, options, aliasResolver) => scss(source, root, {
32286
- ...options,
32287
- indentedSyntax: true,
32288
- }, aliasResolver);
32289
32499
  /**
32290
32500
  * relative url() inside \@imported sass and less files must be rebased to use
32291
32501
  * root file as base.
@@ -32342,137 +32552,220 @@ async function rebaseUrls(file, rootFile, alias, variablePrefix, resolver) {
32342
32552
  };
32343
32553
  }
32344
32554
  // .less
32345
- const less = async (source, root, options, resolvers) => {
32346
- const nodeLess = loadPreprocessor("less" /* PreprocessLang.less */, root);
32347
- const viteResolverPlugin = createViteLessPlugin(nodeLess, options.filename, options.alias, resolvers);
32348
- const { content, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap);
32349
- let result;
32350
- try {
32351
- result = await nodeLess.render(content, {
32352
- ...options,
32353
- plugins: [viteResolverPlugin, ...(options.plugins || [])],
32354
- ...(options.enableSourcemap
32355
- ? {
32356
- sourceMap: {
32357
- outputSourceFiles: true,
32358
- sourceMapFileInline: false,
32359
- },
32360
- }
32361
- : {}),
32362
- });
32363
- }
32364
- catch (e) {
32365
- const error = e;
32366
- // normalize error info
32367
- const normalizedError = new Error(`[less] ${error.message || error.type}`);
32368
- normalizedError.loc = {
32369
- file: error.filename || options.filename,
32370
- line: error.line,
32371
- column: error.column,
32372
- };
32373
- return { code: '', error: normalizedError, deps: [] };
32374
- }
32375
- const map = result.map && JSON.parse(result.map);
32376
- if (map) {
32377
- delete map.sourcesContent;
32378
- }
32379
- return {
32380
- code: result.css.toString(),
32381
- map,
32382
- additionalMap,
32383
- deps: result.imports,
32555
+ const makeLessWorker = (resolvers, alias, maxWorkers) => {
32556
+ const viteLessResolve = async (filename, dir, rootFile) => {
32557
+ const resolved = await resolvers.less(filename, path$o.join(dir, '*'));
32558
+ if (!resolved)
32559
+ return undefined;
32560
+ const result = await rebaseUrls(resolved, rootFile, alias, '@', resolvers.less);
32561
+ if (result) {
32562
+ return {
32563
+ resolved,
32564
+ contents: 'contents' in result ? result.contents : undefined,
32565
+ };
32566
+ }
32567
+ return result;
32384
32568
  };
32385
- };
32386
- /**
32387
- * Less manager, lazy initialized
32388
- */
32389
- let ViteLessManager;
32390
- function createViteLessPlugin(less, rootFile, alias, resolvers) {
32391
- if (!ViteLessManager) {
32392
- ViteLessManager = class ViteManager extends less.FileManager {
32393
- resolvers;
32394
- rootFile;
32395
- alias;
32396
- constructor(rootFile, resolvers, alias) {
32397
- super();
32398
- this.rootFile = rootFile;
32399
- this.resolvers = resolvers;
32400
- this.alias = alias;
32401
- }
32402
- supports(filename) {
32403
- return !isExternalUrl(filename);
32404
- }
32405
- supportsSync() {
32406
- return false;
32407
- }
32408
- async loadFile(filename, dir, opts, env) {
32409
- const resolved = await this.resolvers.less(filename, path$o.join(dir, '*'));
32410
- if (resolved) {
32411
- const result = await rebaseUrls(resolved, this.rootFile, this.alias, '@', this.resolvers.less);
32412
- let contents;
32413
- if (result && 'contents' in result) {
32414
- contents = result.contents;
32569
+ const worker = new WorkerWithFallback(() => {
32570
+ // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
32571
+ const fsp = require('node:fs/promises');
32572
+ // eslint-disable-next-line no-restricted-globals
32573
+ const path = require('node:path');
32574
+ let ViteLessManager;
32575
+ const createViteLessPlugin = (less, rootFile) => {
32576
+ const { FileManager } = less;
32577
+ ViteLessManager ??= class ViteManager extends FileManager {
32578
+ rootFile;
32579
+ constructor(rootFile) {
32580
+ super();
32581
+ this.rootFile = rootFile;
32582
+ }
32583
+ supports(filename) {
32584
+ return !/^(?:https?:)?\/\//.test(filename);
32585
+ }
32586
+ supportsSync() {
32587
+ return false;
32588
+ }
32589
+ async loadFile(filename, dir, opts, env) {
32590
+ const result = await viteLessResolve(filename, dir, this.rootFile);
32591
+ if (result) {
32592
+ return {
32593
+ filename: path.resolve(result.resolved),
32594
+ contents: result.contents ??
32595
+ (await fsp.readFile(result.resolved, 'utf-8')),
32596
+ };
32415
32597
  }
32416
32598
  else {
32417
- contents = await fsp.readFile(resolved, 'utf-8');
32599
+ return super.loadFile(filename, dir, opts, env);
32418
32600
  }
32419
- return {
32420
- filename: path$o.resolve(resolved),
32421
- contents,
32422
- };
32423
32601
  }
32424
- else {
32425
- return super.loadFile(filename, dir, opts, env);
32426
- }
32427
- }
32602
+ };
32603
+ return {
32604
+ install(_, pluginManager) {
32605
+ pluginManager.addFileManager(new ViteLessManager(rootFile));
32606
+ },
32607
+ minVersion: [3, 0, 0],
32608
+ };
32428
32609
  };
32429
- }
32610
+ return async (lessPath, content,
32611
+ // additionalData can a function that is not cloneable but it won't be used
32612
+ options) => {
32613
+ // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
32614
+ const nodeLess = require(lessPath);
32615
+ const viteResolverPlugin = createViteLessPlugin(nodeLess, options.filename);
32616
+ const result = await nodeLess.render(content, {
32617
+ ...options,
32618
+ plugins: [viteResolverPlugin, ...(options.plugins || [])],
32619
+ ...(options.enableSourcemap
32620
+ ? {
32621
+ sourceMap: {
32622
+ outputSourceFiles: true,
32623
+ sourceMapFileInline: false,
32624
+ },
32625
+ }
32626
+ : {}),
32627
+ });
32628
+ return result;
32629
+ };
32630
+ }, {
32631
+ parentFunctions: { viteLessResolve },
32632
+ shouldUseFake(_lessPath, _content, options) {
32633
+ // plugins are a function and is not serializable
32634
+ // in that case, fallback to running in main thread
32635
+ return options.plugins?.length > 0;
32636
+ },
32637
+ max: maxWorkers,
32638
+ });
32639
+ return worker;
32640
+ };
32641
+ const lessProcessor = (maxWorkers) => {
32642
+ const workerMap = new Map();
32430
32643
  return {
32431
- install(_, pluginManager) {
32432
- pluginManager.addFileManager(new ViteLessManager(rootFile, resolvers, alias));
32644
+ close() {
32645
+ for (const worker of workerMap.values()) {
32646
+ worker.stop();
32647
+ }
32648
+ },
32649
+ async process(source, root, options, resolvers) {
32650
+ const lessPath = loadPreprocessorPath("less" /* PreprocessLang.less */, root);
32651
+ if (!workerMap.has(options.alias)) {
32652
+ workerMap.set(options.alias, makeLessWorker(resolvers, options.alias, maxWorkers));
32653
+ }
32654
+ const worker = workerMap.get(options.alias);
32655
+ const { content, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap);
32656
+ let result;
32657
+ const optionsWithoutAdditionalData = {
32658
+ ...options,
32659
+ additionalData: undefined,
32660
+ };
32661
+ try {
32662
+ result = await worker.run(lessPath, content, optionsWithoutAdditionalData);
32663
+ }
32664
+ catch (e) {
32665
+ const error = e;
32666
+ // normalize error info
32667
+ const normalizedError = new Error(`[less] ${error.message || error.type}`);
32668
+ normalizedError.loc = {
32669
+ file: error.filename || options.filename,
32670
+ line: error.line,
32671
+ column: error.column,
32672
+ };
32673
+ return { code: '', error: normalizedError, deps: [] };
32674
+ }
32675
+ const map = result.map && JSON.parse(result.map);
32676
+ if (map) {
32677
+ delete map.sourcesContent;
32678
+ }
32679
+ return {
32680
+ code: result.css.toString(),
32681
+ map,
32682
+ additionalMap,
32683
+ deps: result.imports,
32684
+ };
32433
32685
  },
32434
- minVersion: [3, 0, 0],
32435
32686
  };
32436
- }
32687
+ };
32437
32688
  // .styl
32438
- const styl = async (source, root, options) => {
32439
- const nodeStylus = loadPreprocessor("stylus" /* PreprocessLang.stylus */, root);
32440
- // Get source with preprocessor options.additionalData. Make sure a new line separator
32441
- // is added to avoid any render error, as added stylus content may not have semi-colon separators
32442
- const { content, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap, '\n');
32443
- // Get preprocessor options.imports dependencies as stylus
32444
- // does not return them with its builtin `.deps()` method
32445
- const importsDeps = (options.imports ?? []).map((dep) => path$o.resolve(dep));
32446
- try {
32447
- const ref = nodeStylus(content, options);
32448
- if (options.define) {
32449
- for (const key in options.define) {
32450
- ref.define(key, options.define[key]);
32689
+ const makeStylWorker = (maxWorkers) => {
32690
+ const worker = new WorkerWithFallback(() => {
32691
+ return async (stylusPath, content, root,
32692
+ // additionalData can a function that is not cloneable but it won't be used
32693
+ options) => {
32694
+ // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
32695
+ const nodeStylus = require(stylusPath);
32696
+ const ref = nodeStylus(content, options);
32697
+ if (options.define) {
32698
+ for (const key in options.define) {
32699
+ ref.define(key, options.define[key]);
32700
+ }
32451
32701
  }
32452
- }
32453
- if (options.enableSourcemap) {
32454
- ref.set('sourcemap', {
32455
- comment: false,
32456
- inline: false,
32457
- basePath: root,
32458
- });
32459
- }
32460
- const result = ref.render();
32461
- // Concat imports deps with computed deps
32462
- const deps = [...ref.deps(), ...importsDeps];
32463
- // @ts-expect-error sourcemap exists
32464
- const map = ref.sourcemap;
32465
- return {
32466
- code: result,
32467
- map: formatStylusSourceMap(map, root),
32468
- additionalMap,
32469
- deps,
32702
+ if (options.enableSourcemap) {
32703
+ ref.set('sourcemap', {
32704
+ comment: false,
32705
+ inline: false,
32706
+ basePath: root,
32707
+ });
32708
+ }
32709
+ return {
32710
+ code: ref.render(),
32711
+ // @ts-expect-error sourcemap exists
32712
+ map: ref.sourcemap,
32713
+ deps: ref.deps(),
32714
+ };
32470
32715
  };
32471
- }
32472
- catch (e) {
32473
- e.message = `[stylus] ${e.message}`;
32474
- return { code: '', error: e, deps: [] };
32475
- }
32716
+ }, {
32717
+ shouldUseFake(_stylusPath, _content, _root, options) {
32718
+ // define can include functions and those are not serializable
32719
+ // in that case, fallback to running in main thread
32720
+ return !!(options.define &&
32721
+ Object.values(options.define).some((d) => typeof d === 'function'));
32722
+ },
32723
+ max: maxWorkers,
32724
+ });
32725
+ return worker;
32726
+ };
32727
+ const stylProcessor = (maxWorkers) => {
32728
+ const workerMap = new Map();
32729
+ return {
32730
+ close() {
32731
+ for (const worker of workerMap.values()) {
32732
+ worker.stop();
32733
+ }
32734
+ },
32735
+ async process(source, root, options, resolvers) {
32736
+ const stylusPath = loadPreprocessorPath("stylus" /* PreprocessLang.stylus */, root);
32737
+ if (!workerMap.has(options.alias)) {
32738
+ workerMap.set(options.alias, makeStylWorker(maxWorkers));
32739
+ }
32740
+ const worker = workerMap.get(options.alias);
32741
+ // Get source with preprocessor options.additionalData. Make sure a new line separator
32742
+ // is added to avoid any render error, as added stylus content may not have semi-colon separators
32743
+ const { content, map: additionalMap } = await getSource(source, options.filename, options.additionalData, options.enableSourcemap, '\n');
32744
+ // Get preprocessor options.imports dependencies as stylus
32745
+ // does not return them with its builtin `.deps()` method
32746
+ const importsDeps = (options.imports ?? []).map((dep) => path$o.resolve(dep));
32747
+ const optionsWithoutAdditionalData = {
32748
+ ...options,
32749
+ additionalData: undefined,
32750
+ };
32751
+ try {
32752
+ const { code, map, deps } = await worker.run(stylusPath, content, root, optionsWithoutAdditionalData);
32753
+ return {
32754
+ code,
32755
+ map: formatStylusSourceMap(map, root),
32756
+ additionalMap,
32757
+ // Concat imports deps with computed deps
32758
+ deps: [...deps, ...importsDeps],
32759
+ };
32760
+ }
32761
+ catch (e) {
32762
+ const wrapped = new Error(`[stylus] ${e.message}`);
32763
+ wrapped.name = e.name;
32764
+ wrapped.stack = e.stack;
32765
+ return { code: '', error: wrapped, deps: [] };
32766
+ }
32767
+ },
32768
+ };
32476
32769
  };
32477
32770
  function formatStylusSourceMap(mapBefore, root) {
32478
32771
  if (!mapBefore)
@@ -32509,15 +32802,43 @@ async function getSource(source, filename, additionalData, enableSourcemap, sep
32509
32802
  map,
32510
32803
  };
32511
32804
  }
32512
- const preProcessors = Object.freeze({
32513
- ["less" /* PreprocessLang.less */]: less,
32514
- ["sass" /* PreprocessLang.sass */]: sass,
32515
- ["scss" /* PreprocessLang.scss */]: scss,
32516
- ["styl" /* PreprocessLang.styl */]: styl,
32517
- ["stylus" /* PreprocessLang.stylus */]: styl,
32518
- });
32805
+ const createPreprocessorWorkerController = (maxWorkers) => {
32806
+ const scss = scssProcessor(maxWorkers);
32807
+ const less = lessProcessor(maxWorkers);
32808
+ const styl = stylProcessor(maxWorkers);
32809
+ const sassProcess = (source, root, options, resolvers) => {
32810
+ return scss.process(source, root, { ...options, indentedSyntax: true }, resolvers);
32811
+ };
32812
+ const close = () => {
32813
+ less.close();
32814
+ scss.close();
32815
+ styl.close();
32816
+ };
32817
+ return {
32818
+ ["less" /* PreprocessLang.less */]: less.process,
32819
+ ["scss" /* PreprocessLang.scss */]: scss.process,
32820
+ ["sass" /* PreprocessLang.sass */]: sassProcess,
32821
+ ["styl" /* PreprocessLang.styl */]: styl.process,
32822
+ ["stylus" /* PreprocessLang.stylus */]: styl.process,
32823
+ close,
32824
+ };
32825
+ };
32826
+ const normalizeMaxWorkers = (maxWorker) => {
32827
+ if (maxWorker === undefined)
32828
+ return 0;
32829
+ if (maxWorker === true)
32830
+ return undefined;
32831
+ return maxWorker;
32832
+ };
32833
+ const preprocessorSet = new Set([
32834
+ "less" /* PreprocessLang.less */,
32835
+ "sass" /* PreprocessLang.sass */,
32836
+ "scss" /* PreprocessLang.scss */,
32837
+ "styl" /* PreprocessLang.styl */,
32838
+ "stylus" /* PreprocessLang.stylus */,
32839
+ ]);
32519
32840
  function isPreProcessor(lang) {
32520
- return lang && lang in preProcessors;
32841
+ return lang && preprocessorSet.has(lang);
32521
32842
  }
32522
32843
  const importLightningCSS = createCachedImport(() => import('lightningcss'));
32523
32844
  async function compileLightningCSS(id, src, config, urlReplacer) {
@@ -42028,7 +42349,7 @@ var utilsMergeExports = utilsMerge.exports;
42028
42349
  var debug$d = srcExports('connect:dispatcher');
42029
42350
  var EventEmitter$3 = require$$0$5.EventEmitter;
42030
42351
  var finalhandler = finalhandler_1;
42031
- var http$4 = require$$1$1;
42352
+ var http$4 = require$$1;
42032
42353
  var merge = utilsMergeExports;
42033
42354
  var parseUrl = parseurlExports;
42034
42355
 
@@ -46451,6 +46772,68 @@ function setClientErrorHandler(server, logger) {
46451
46772
  });
46452
46773
  }
46453
46774
 
46775
+ // https://github.com/vitejs/vite/issues/2820#issuecomment-812495079
46776
+ const ROOT_FILES = [
46777
+ // '.git',
46778
+ // https://pnpm.io/workspaces/
46779
+ 'pnpm-workspace.yaml',
46780
+ // https://rushjs.io/pages/advanced/config_files/
46781
+ // 'rush.json',
46782
+ // https://nx.dev/latest/react/getting-started/nx-setup
46783
+ // 'workspace.json',
46784
+ // 'nx.json',
46785
+ // https://github.com/lerna/lerna#lernajson
46786
+ 'lerna.json',
46787
+ ];
46788
+ // npm: https://docs.npmjs.com/cli/v7/using-npm/workspaces#installing-workspaces
46789
+ // yarn: https://classic.yarnpkg.com/en/docs/workspaces/#toc-how-to-use-it
46790
+ function hasWorkspacePackageJSON(root) {
46791
+ const path = join$2(root, 'package.json');
46792
+ if (!isFileReadable(path)) {
46793
+ return false;
46794
+ }
46795
+ try {
46796
+ const content = JSON.parse(fs$l.readFileSync(path, 'utf-8')) || {};
46797
+ return !!content.workspaces;
46798
+ }
46799
+ catch {
46800
+ return false;
46801
+ }
46802
+ }
46803
+ function hasRootFile(root) {
46804
+ return ROOT_FILES.some((file) => fs$l.existsSync(join$2(root, file)));
46805
+ }
46806
+ function hasPackageJSON(root) {
46807
+ const path = join$2(root, 'package.json');
46808
+ return fs$l.existsSync(path);
46809
+ }
46810
+ /**
46811
+ * Search up for the nearest `package.json`
46812
+ */
46813
+ function searchForPackageRoot(current, root = current) {
46814
+ if (hasPackageJSON(current))
46815
+ return current;
46816
+ const dir = dirname$2(current);
46817
+ // reach the fs root
46818
+ if (!dir || dir === current)
46819
+ return root;
46820
+ return searchForPackageRoot(dir, root);
46821
+ }
46822
+ /**
46823
+ * Search up for the nearest workspace root
46824
+ */
46825
+ function searchForWorkspaceRoot(current, root = searchForPackageRoot(current)) {
46826
+ if (hasRootFile(current))
46827
+ return current;
46828
+ if (hasWorkspacePackageJSON(current))
46829
+ return current;
46830
+ const dir = dirname$2(current);
46831
+ // reach the fs root
46832
+ if (!dir || dir === current)
46833
+ return root;
46834
+ return searchForWorkspaceRoot(dir, root);
46835
+ }
46836
+
46454
46837
  // An implementation of fsUtils without caching
46455
46838
  const commonFsUtils = {
46456
46839
  existsSync: fs$l.existsSync,
@@ -46467,20 +46850,9 @@ function getFsUtils(config) {
46467
46850
  // cached fsUtils is only used in the dev server for now, and only when the watcher isn't configured
46468
46851
  // we can support custom ignored patterns later
46469
46852
  fsUtils = commonFsUtils;
46470
- } /* TODO: Enabling for testing, we need to review if this guard is needed
46471
- else if (config.server.watch === null || config.server.watch?.ignored) {
46472
- config.logger.warn(
46473
- colors.yellow(
46474
- `${colors.bold(
46475
- `(!)`,
46476
- )} server.fs.cachedChecks isn't supported if server.watch is null or a custom server.watch.ignored is configured\n`,
46477
- ),
46478
- )
46479
- fsUtils = commonFsUtils
46480
- } */
46853
+ }
46481
46854
  else if (!config.resolve.preserveSymlinks &&
46482
46855
  config.root !== getRealPath(config.root)) {
46483
- config.logger.warn(colors$1.yellow(`${colors$1.bold(`(!)`)} server.fs.cachedChecks isn't supported when resolve.preserveSymlinks is false and root is symlinked\n`));
46484
46856
  fsUtils = commonFsUtils;
46485
46857
  }
46486
46858
  else {
@@ -46533,7 +46905,7 @@ function pathUntilPart(root, parts, i) {
46533
46905
  return p;
46534
46906
  }
46535
46907
  function createCachedFsUtils(config) {
46536
- const root = config.root; // root is resolved and normalized, so it doesn't have a trailing slash
46908
+ const root = normalizePath$3(searchForWorkspaceRoot(config.root));
46537
46909
  const rootDirPath = `${root}/`;
46538
46910
  const rootCache = { type: 'directory' }; // dirents will be computed lazily
46539
46911
  const getDirentCacheSync = (parts) => {
@@ -46604,7 +46976,7 @@ function createCachedFsUtils(config) {
46604
46976
  return direntCache;
46605
46977
  }
46606
46978
  function onPathAdd(file, type) {
46607
- const direntCache = getDirentCacheFromPath(path$o.dirname(file));
46979
+ const direntCache = getDirentCacheFromPath(normalizePath$3(path$o.dirname(file)));
46608
46980
  if (direntCache &&
46609
46981
  direntCache.type === 'directory' &&
46610
46982
  direntCache.dirents) {
@@ -46612,7 +46984,7 @@ function createCachedFsUtils(config) {
46612
46984
  }
46613
46985
  }
46614
46986
  function onPathUnlink(file) {
46615
- const direntCache = getDirentCacheFromPath(path$o.dirname(file));
46987
+ const direntCache = getDirentCacheFromPath(normalizePath$3(path$o.dirname(file)));
46616
46988
  if (direntCache &&
46617
46989
  direntCache.type === 'directory' &&
46618
46990
  direntCache.dirents) {
@@ -46918,7 +47290,7 @@ const debug$c = createDebugger('vite:resolve-details', {
46918
47290
  });
46919
47291
  function resolvePlugin(resolveOptions) {
46920
47292
  const { root, isProduction, asSrc, ssrConfig, preferRelative = false, } = resolveOptions;
46921
- const { target: ssrTarget, noExternal: ssrNoExternal } = ssrConfig ?? {};
47293
+ const { target: ssrTarget, noExternal: ssrNoExternal, external: ssrExternal, } = ssrConfig ?? {};
46922
47294
  // In unix systems, absolute paths inside root first needs to be checked as an
46923
47295
  // absolute URL (/root/root/path-to-file) resulting in failed checks before falling
46924
47296
  // back to checking the path as absolute. If /root/root isn't a valid path, we can
@@ -47092,7 +47464,10 @@ function resolvePlugin(resolveOptions) {
47092
47464
  // externalize if building for SSR, otherwise redirect to empty module
47093
47465
  if (isBuiltin(id)) {
47094
47466
  if (ssr) {
47095
- if (ssrNoExternal === true) {
47467
+ if (ssrNoExternal === true &&
47468
+ // if both noExternal and external are true, noExternal will take the higher priority and bundle it.
47469
+ // only if the id is explicitly listed in external, we will externalize it and skip this error.
47470
+ (ssrExternal === true || !ssrExternal?.includes(id))) {
47096
47471
  let message = `Cannot bundle Node.js built-in "${id}"`;
47097
47472
  if (importer) {
47098
47473
  message += ` imported from "${path$o.relative(process.cwd(), importer)}"`;
@@ -47100,7 +47475,9 @@ function resolvePlugin(resolveOptions) {
47100
47475
  message += `. Consider disabling ssr.noExternal or remove the built-in dependency.`;
47101
47476
  this.error(message);
47102
47477
  }
47103
- return options.idOnly ? id : { id, external: true };
47478
+ return options.idOnly
47479
+ ? id
47480
+ : { id, external: true, moduleSideEffects: false };
47104
47481
  }
47105
47482
  else {
47106
47483
  if (!asSrc) {
@@ -49867,7 +50244,7 @@ async function createPluginContainer(config, moduleGraph, watcher) {
49867
50244
  const moduleNodeToLoadAddedImports = new WeakMap();
49868
50245
  const minimalContext = {
49869
50246
  meta: {
49870
- rollupVersion: VERSION,
50247
+ rollupVersion,
49871
50248
  watchMode: true,
49872
50249
  },
49873
50250
  debug: noop$3,
@@ -51101,6 +51478,8 @@ async function createDepsOptimizer(config, server) {
51101
51478
  let debounceProcessingHandle;
51102
51479
  let closed = false;
51103
51480
  let metadata = cachedMetadata || initDepsOptimizerMetadata(config, ssr, sessionTimestamp);
51481
+ const options = getDepOptimizationConfig(config, ssr);
51482
+ const { noDiscovery, holdUntilCrawlEnd } = options;
51104
51483
  const depsOptimizer = {
51105
51484
  metadata,
51106
51485
  registerMissingImport,
@@ -51110,7 +51489,7 @@ async function createDepsOptimizer(config, server) {
51110
51489
  getOptimizedDepId: (depInfo) => `${depInfo.file}?v=${depInfo.browserHash}`,
51111
51490
  delayDepsOptimizerUntil,
51112
51491
  close,
51113
- options: getDepOptimizationConfig(config, ssr),
51492
+ options,
51114
51493
  };
51115
51494
  depsOptimizerMap.set(config, depsOptimizer);
51116
51495
  let newDepsDiscovered = false;
@@ -51124,6 +51503,15 @@ async function createDepsOptimizer(config, server) {
51124
51503
  newDepsToLog = [];
51125
51504
  }
51126
51505
  };
51506
+ let discoveredDepsWhileScanning = [];
51507
+ const logDiscoveredDepsWhileScanning = () => {
51508
+ if (discoveredDepsWhileScanning.length) {
51509
+ config.logger.info(colors$1.green(`✨ discovered while scanning: ${depsLogString(discoveredDepsWhileScanning)}`), {
51510
+ timestamp: true,
51511
+ });
51512
+ discoveredDepsWhileScanning = [];
51513
+ }
51514
+ };
51127
51515
  let depOptimizationProcessing = promiseWithResolvers();
51128
51516
  let depOptimizationProcessingQueue = [];
51129
51517
  const resolveEnqueuedProcessingPromises = () => {
@@ -51136,6 +51524,7 @@ async function createDepsOptimizer(config, server) {
51136
51524
  let enqueuedRerun;
51137
51525
  let currentlyProcessing = false;
51138
51526
  let firstRunCalled = !!cachedMetadata;
51527
+ let warnAboutMissedDependencies = false;
51139
51528
  // If this is a cold run, we wait for static imports discovered
51140
51529
  // from the first request before resolving to minimize full page reloads.
51141
51530
  // On warm start or after the first optimization is run, we use a simpler
@@ -51159,17 +51548,17 @@ async function createDepsOptimizer(config, server) {
51159
51548
  // Enter processing state until crawl of static imports ends
51160
51549
  currentlyProcessing = true;
51161
51550
  // Initialize discovered deps with manually added optimizeDeps.include info
51162
- const deps = {};
51163
- await addManuallyIncludedOptimizeDeps(deps, config, ssr);
51164
- const discovered = toDiscoveredDependencies(config, deps, ssr, sessionTimestamp);
51165
- for (const depInfo of Object.values(discovered)) {
51551
+ const manuallyIncludedDeps = {};
51552
+ await addManuallyIncludedOptimizeDeps(manuallyIncludedDeps, config, ssr);
51553
+ const manuallyIncludedDepsInfo = toDiscoveredDependencies(config, manuallyIncludedDeps, ssr, sessionTimestamp);
51554
+ for (const depInfo of Object.values(manuallyIncludedDepsInfo)) {
51166
51555
  addOptimizedDepInfo(metadata, 'discovered', {
51167
51556
  ...depInfo,
51168
51557
  processing: depOptimizationProcessing.promise,
51169
51558
  });
51170
51559
  newDepsDiscovered = true;
51171
51560
  }
51172
- if (config.optimizeDeps.noDiscovery) {
51561
+ if (noDiscovery) {
51173
51562
  // We don't need to scan for dependencies or wait for the static crawl to end
51174
51563
  // Run the first optimization run immediately
51175
51564
  runOptimizer();
@@ -51183,6 +51572,8 @@ async function createDepsOptimizer(config, server) {
51183
51572
  discover = discoverProjectDependencies(config);
51184
51573
  const deps = await discover.result;
51185
51574
  discover = undefined;
51575
+ const manuallyIncluded = Object.keys(manuallyIncludedDepsInfo);
51576
+ discoveredDepsWhileScanning.push(...Object.keys(metadata.discovered).filter((dep) => !deps[dep] && !manuallyIncluded.includes(dep)));
51186
51577
  // Add these dependencies to the discovered list, as these are currently
51187
51578
  // used by the preAliasPlugin to support aliased and optimized deps.
51188
51579
  // This is also used by the CJS externalization heuristics in legacy mode
@@ -51192,11 +51583,28 @@ async function createDepsOptimizer(config, server) {
51192
51583
  }
51193
51584
  }
51194
51585
  const knownDeps = prepareKnownDeps();
51586
+ startNextDiscoveredBatch();
51195
51587
  // For dev, we run the scanner and the first optimization
51196
- // run on the background, but we wait until crawling has ended
51197
- // to decide if we send this result to the browser or we need to
51198
- // do another optimize step
51588
+ // run on the background
51199
51589
  optimizationResult = runOptimizeDeps(config, knownDeps, ssr);
51590
+ // If the holdUntilCrawlEnd stratey is used, we wait until crawling has
51591
+ // ended to decide if we send this result to the browser or we need to
51592
+ // do another optimize step
51593
+ if (!holdUntilCrawlEnd) {
51594
+ // If not, we release the result to the browser as soon as the scanner
51595
+ // is done. If the scanner missed any dependency, and a new dependency
51596
+ // is discovered while crawling static imports, then there will be a
51597
+ // full-page reload if new common chunks are generated between the old
51598
+ // and new optimized deps.
51599
+ optimizationResult.result.then((result) => {
51600
+ // Check if the crawling of static imports has already finished. In that
51601
+ // case, the result is handled by the onCrawlEnd callback
51602
+ if (!crawlEndFinder)
51603
+ return;
51604
+ optimizationResult = undefined; // signal that we'll be using the result
51605
+ runOptimizer(result);
51606
+ });
51607
+ }
51200
51608
  }
51201
51609
  catch (e) {
51202
51610
  logger.error(e.stack || e.message);
@@ -51328,6 +51736,11 @@ async function createDepsOptimizer(config, server) {
51328
51736
  newDepsToLogHandle = setTimeout(() => {
51329
51737
  newDepsToLogHandle = undefined;
51330
51738
  logNewlyDiscoveredDeps();
51739
+ if (warnAboutMissedDependencies) {
51740
+ logDiscoveredDepsWhileScanning();
51741
+ config.logger.info(colors$1.magenta(`❗ add these dependencies to optimizeDeps.include to speed up cold start`), { timestamp: true });
51742
+ warnAboutMissedDependencies = false;
51743
+ }
51331
51744
  }, 2 * debounceMs);
51332
51745
  }
51333
51746
  else {
@@ -51352,6 +51765,11 @@ async function createDepsOptimizer(config, server) {
51352
51765
  clearTimeout(newDepsToLogHandle);
51353
51766
  newDepsToLogHandle = undefined;
51354
51767
  logNewlyDiscoveredDeps();
51768
+ if (warnAboutMissedDependencies) {
51769
+ logDiscoveredDepsWhileScanning();
51770
+ config.logger.info(colors$1.magenta(`❗ add these dependencies to optimizeDeps.include to avoid a full page reload during cold start`), { timestamp: true });
51771
+ warnAboutMissedDependencies = false;
51772
+ }
51355
51773
  }
51356
51774
  logger.info(colors$1.green(`✨ optimized dependencies changed. reloading`), {
51357
51775
  timestamp: true,
@@ -51447,7 +51865,7 @@ async function createDepsOptimizer(config, server) {
51447
51865
  }
51448
51866
  function debouncedProcessing(timeout = debounceMs) {
51449
51867
  // Debounced rerun, let other missing dependencies be discovered before
51450
- // the running next optimizeDeps
51868
+ // the next optimizeDeps run
51451
51869
  enqueuedRerun = undefined;
51452
51870
  if (debounceProcessingHandle)
51453
51871
  clearTimeout(debounceProcessingHandle);
@@ -51476,8 +51894,16 @@ async function createDepsOptimizer(config, server) {
51476
51894
  // It normally should be over by the time crawling of user code ended
51477
51895
  await depsOptimizer.scanProcessing;
51478
51896
  if (optimizationResult && !config.optimizeDeps.noDiscovery) {
51479
- const result = await optimizationResult.result;
51480
- optimizationResult = undefined;
51897
+ // In the holdUntilCrawlEnd strategy, we don't release the result of the
51898
+ // post-scanner optimize step to the browser until we reach this point
51899
+ // If there are new dependencies, we do another optimize run, if not, we
51900
+ // use the post-scanner optimize result
51901
+ // If holdUntilCrawlEnd is false and we reach here, it means that the
51902
+ // scan+optimize step finished after crawl end. We follow the same
51903
+ // process as in the holdUntilCrawlEnd in this case.
51904
+ const afterScanResult = optimizationResult.result;
51905
+ optimizationResult = undefined; // signal that we'll be using the result
51906
+ const result = await afterScanResult;
51481
51907
  currentlyProcessing = false;
51482
51908
  const crawlDeps = Object.keys(metadata.discovered);
51483
51909
  const scanDeps = Object.keys(result.metadata.optimized);
@@ -51513,6 +51939,17 @@ async function createDepsOptimizer(config, server) {
51513
51939
  runOptimizer(result);
51514
51940
  }
51515
51941
  }
51942
+ else if (!holdUntilCrawlEnd) {
51943
+ // The post-scanner optimize result has been released to the browser
51944
+ // If new deps have been discovered, issue a regular rerun of the
51945
+ // optimizer. A full page reload may still be avoided if the new
51946
+ // optimize result is compatible in this case
51947
+ if (newDepsDiscovered) {
51948
+ debug$8?.(colors$1.green(`✨ new dependencies were found while crawling static imports, re-running optimizer`));
51949
+ warnAboutMissedDependencies = true;
51950
+ debouncedProcessing(0);
51951
+ }
51952
+ }
51516
51953
  else {
51517
51954
  const crawlDeps = Object.keys(metadata.discovered);
51518
51955
  currentlyProcessing = false;
@@ -53103,12 +53540,8 @@ async function loadAndTransform(id, url, server, options, timestamp, mod, resolv
53103
53540
  });
53104
53541
  // Only cache the result if the module wasn't invalidated while it was
53105
53542
  // being processed, so it is re-processed next time if it is stale
53106
- if (timestamp > mod.lastInvalidationTimestamp) {
53107
- if (ssr)
53108
- mod.ssrTransformResult = result;
53109
- else
53110
- mod.transformResult = result;
53111
- }
53543
+ if (timestamp > mod.lastInvalidationTimestamp)
53544
+ moduleGraph.updateModuleTransformResult(mod, result, ssr);
53112
53545
  return result;
53113
53546
  }
53114
53547
  function createConvertSourceMapReadMap(originalFileName) {
@@ -53146,7 +53579,7 @@ async function handleModuleSoftInvalidation(mod, ssr, timestamp, server) {
53146
53579
  await init;
53147
53580
  const source = transformResult.code;
53148
53581
  const s = new MagicString(source);
53149
- const [imports] = parse$e(source);
53582
+ const [imports] = parse$e(source, mod.id || undefined);
53150
53583
  for (const imp of imports) {
53151
53584
  let rawUrl = source.slice(imp.s, imp.e);
53152
53585
  if (rawUrl === 'import.meta')
@@ -53185,12 +53618,8 @@ async function handleModuleSoftInvalidation(mod, ssr, timestamp, server) {
53185
53618
  }
53186
53619
  // Only cache the result if the module wasn't invalidated while it was
53187
53620
  // being processed, so it is re-processed next time if it is stale
53188
- if (timestamp > mod.lastInvalidationTimestamp) {
53189
- if (ssr)
53190
- mod.ssrTransformResult = result;
53191
- else
53192
- mod.transformResult = result;
53193
- }
53621
+ if (timestamp > mod.lastInvalidationTimestamp)
53622
+ server.moduleGraph.updateModuleTransformResult(mod, result, ssr);
53194
53623
  return result;
53195
53624
  }
53196
53625
 
@@ -58158,8 +58587,8 @@ var extension$1 = { format: format$1, parse: parse$2 };
58158
58587
  /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$" }] */
58159
58588
 
58160
58589
  const EventEmitter$1 = require$$0$5;
58161
- const https$2 = require$$1$2;
58162
- const http$3 = require$$1$1;
58590
+ const https$2 = require$$1$1;
58591
+ const http$3 = require$$1;
58163
58592
  const net = require$$4$1;
58164
58593
  const tls = require$$4$2;
58165
58594
  const { randomBytes, createHash: createHash$1 } = require$$0$a;
@@ -59553,7 +59982,7 @@ var subprotocol$1 = { parse };
59553
59982
  /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$" }] */
59554
59983
 
59555
59984
  const EventEmitter = require$$0$5;
59556
- const http$2 = require$$1$1;
59985
+ const http$2 = require$$1;
59557
59986
  const { createHash } = require$$0$a;
59558
59987
 
59559
59988
  const extension = extension$1;
@@ -61158,8 +61587,8 @@ var debug_1 = function () {
61158
61587
 
61159
61588
  var url = require$$0$9;
61160
61589
  var URL$1 = url.URL;
61161
- var http$1 = require$$1$1;
61162
- var https$1 = require$$1$2;
61590
+ var http$1 = require$$1;
61591
+ var https$1 = require$$1$1;
61163
61592
  var Writable = require$$0$7.Writable;
61164
61593
  var assert = require$$5;
61165
61594
  var debug$5 = debug_1;
@@ -61752,8 +62181,8 @@ followRedirects$1.exports.wrap = wrap;
61752
62181
 
61753
62182
  var followRedirectsExports = followRedirects$1.exports;
61754
62183
 
61755
- var httpNative = require$$1$1,
61756
- httpsNative = require$$1$2,
62184
+ var httpNative = require$$1,
62185
+ httpsNative = require$$1$1,
61757
62186
  web_o = webOutgoing,
61758
62187
  common$1 = common$3,
61759
62188
  followRedirects = followRedirectsExports;
@@ -61947,8 +62376,8 @@ var webIncoming = {
61947
62376
 
61948
62377
  };
61949
62378
 
61950
- var http = require$$1$1,
61951
- https = require$$1$2,
62379
+ var http = require$$1,
62380
+ https = require$$1$1,
61952
62381
  common = common$3;
61953
62382
 
61954
62383
  /*!
@@ -62115,8 +62544,8 @@ var wsIncoming = {
62115
62544
  extend = require$$0$6._extend,
62116
62545
  parse_url = require$$0$9.parse,
62117
62546
  EE3 = eventemitter3Exports,
62118
- http = require$$1$1,
62119
- https = require$$1$2,
62547
+ http = require$$1,
62548
+ https = require$$1$1,
62120
62549
  web = webIncoming,
62121
62550
  ws = wsIncoming;
62122
62551
 
@@ -62408,7 +62837,7 @@ function proxyMiddleware(httpServer, options, config) {
62408
62837
  });
62409
62838
  }
62410
62839
  else if ('req' in res) {
62411
- config.logger.error(`${colors$1.red(`http proxy error at ${originalRes.req.url}:`)}\n${err.stack}`, {
62840
+ config.logger.error(`${colors$1.red(`http proxy error: ${originalRes.req.url}`)}\n${err.stack}`, {
62412
62841
  timestamp: true,
62413
62842
  error: err,
62414
62843
  });
@@ -62619,6 +63048,32 @@ function send(req, res, content, type, options) {
62619
63048
 
62620
63049
  const debugCache = createDebugger('vite:cache');
62621
63050
  const knownIgnoreList = new Set(['/', '/favicon.ico']);
63051
+ /**
63052
+ * A middleware that short-circuits the middleware chain to serve cached transformed modules
63053
+ */
63054
+ function cachedTransformMiddleware(server) {
63055
+ // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
63056
+ return function viteCachedTransformMiddleware(req, res, next) {
63057
+ // check if we can return 304 early
63058
+ const ifNoneMatch = req.headers['if-none-match'];
63059
+ if (ifNoneMatch) {
63060
+ const moduleByEtag = server.moduleGraph.getModuleByEtag(ifNoneMatch);
63061
+ if (moduleByEtag?.transformResult?.etag === ifNoneMatch) {
63062
+ // For direct CSS requests, if the same CSS file is imported in a module,
63063
+ // the browser sends the request for the direct CSS request with the etag
63064
+ // from the imported CSS module. We ignore the etag in this case.
63065
+ const mixedEtag = !req.headers.accept?.includes('text/css') &&
63066
+ isDirectRequest(moduleByEtag.url);
63067
+ if (!mixedEtag) {
63068
+ debugCache?.(`[304] ${prettifyUrl(req.url, server.config.root)}`);
63069
+ res.statusCode = 304;
63070
+ return res.end();
63071
+ }
63072
+ }
63073
+ }
63074
+ next();
63075
+ };
63076
+ }
62622
63077
  function transformMiddleware(server) {
62623
63078
  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
62624
63079
  // check if public dir is inside root dir
@@ -62705,15 +63160,6 @@ function transformMiddleware(server) {
62705
63160
  req.headers.accept?.includes('text/css')) {
62706
63161
  url = injectQuery(url, 'direct');
62707
63162
  }
62708
- // check if we can return 304 early
62709
- const ifNoneMatch = req.headers['if-none-match'];
62710
- if (ifNoneMatch &&
62711
- (await server.moduleGraph.getModuleByUrl(url, false))?.transformResult
62712
- ?.etag === ifNoneMatch) {
62713
- debugCache?.(`[304] ${prettifyUrl(url, server.config.root)}`);
62714
- res.statusCode = 304;
62715
- return res.end();
62716
- }
62717
63163
  // resolve, load and transform using the plugin container
62718
63164
  const result = await transformRequest(url, server, {
62719
63165
  html: req.headers.accept?.includes('text/html'),
@@ -63176,6 +63622,7 @@ class ModuleGraph {
63176
63622
  resolveId;
63177
63623
  urlToModuleMap = new Map();
63178
63624
  idToModuleMap = new Map();
63625
+ etagToModuleMap = new Map();
63179
63626
  // a single file may corresponds to multiple modules with different queries
63180
63627
  fileToModulesMap = new Map();
63181
63628
  safeModulesPath = new Set();
@@ -63250,6 +63697,9 @@ class ModuleGraph {
63250
63697
  }
63251
63698
  // Don't invalidate mod.info and mod.meta, as they are part of the processing pipeline
63252
63699
  // Invalidating the transform result is enough to ensure this module is re-processed next time it is requested
63700
+ const etag = mod.transformResult?.etag;
63701
+ if (etag)
63702
+ this.etagToModuleMap.delete(etag);
63253
63703
  mod.transformResult = null;
63254
63704
  mod.ssrTransformResult = null;
63255
63705
  mod.ssrModule = null;
@@ -63428,6 +63878,22 @@ class ModuleGraph {
63428
63878
  }
63429
63879
  return this._resolveUrl(url, ssr);
63430
63880
  }
63881
+ updateModuleTransformResult(mod, result, ssr) {
63882
+ if (ssr) {
63883
+ mod.ssrTransformResult = result;
63884
+ }
63885
+ else {
63886
+ const prevEtag = mod.transformResult?.etag;
63887
+ if (prevEtag)
63888
+ this.etagToModuleMap.delete(prevEtag);
63889
+ mod.transformResult = result;
63890
+ if (result?.etag)
63891
+ this.etagToModuleMap.set(result.etag, mod);
63892
+ }
63893
+ }
63894
+ getModuleByEtag(etag) {
63895
+ return this.etagToModuleMap.get(etag);
63896
+ }
63431
63897
  /**
63432
63898
  * @internal
63433
63899
  */
@@ -63471,68 +63937,6 @@ function notFoundMiddleware() {
63471
63937
  };
63472
63938
  }
63473
63939
 
63474
- // https://github.com/vitejs/vite/issues/2820#issuecomment-812495079
63475
- const ROOT_FILES = [
63476
- // '.git',
63477
- // https://pnpm.io/workspaces/
63478
- 'pnpm-workspace.yaml',
63479
- // https://rushjs.io/pages/advanced/config_files/
63480
- // 'rush.json',
63481
- // https://nx.dev/latest/react/getting-started/nx-setup
63482
- // 'workspace.json',
63483
- // 'nx.json',
63484
- // https://github.com/lerna/lerna#lernajson
63485
- 'lerna.json',
63486
- ];
63487
- // npm: https://docs.npmjs.com/cli/v7/using-npm/workspaces#installing-workspaces
63488
- // yarn: https://classic.yarnpkg.com/en/docs/workspaces/#toc-how-to-use-it
63489
- function hasWorkspacePackageJSON(root) {
63490
- const path = join$2(root, 'package.json');
63491
- if (!isFileReadable(path)) {
63492
- return false;
63493
- }
63494
- try {
63495
- const content = JSON.parse(fs$l.readFileSync(path, 'utf-8')) || {};
63496
- return !!content.workspaces;
63497
- }
63498
- catch {
63499
- return false;
63500
- }
63501
- }
63502
- function hasRootFile(root) {
63503
- return ROOT_FILES.some((file) => fs$l.existsSync(join$2(root, file)));
63504
- }
63505
- function hasPackageJSON(root) {
63506
- const path = join$2(root, 'package.json');
63507
- return fs$l.existsSync(path);
63508
- }
63509
- /**
63510
- * Search up for the nearest `package.json`
63511
- */
63512
- function searchForPackageRoot(current, root = current) {
63513
- if (hasPackageJSON(current))
63514
- return current;
63515
- const dir = dirname$2(current);
63516
- // reach the fs root
63517
- if (!dir || dir === current)
63518
- return root;
63519
- return searchForPackageRoot(dir, root);
63520
- }
63521
- /**
63522
- * Search up for the nearest workspace root
63523
- */
63524
- function searchForWorkspaceRoot(current, root = searchForPackageRoot(current)) {
63525
- if (hasRootFile(current))
63526
- return current;
63527
- if (hasWorkspacePackageJSON(current))
63528
- return current;
63529
- const dir = dirname$2(current);
63530
- // reach the fs root
63531
- if (!dir || dir === current)
63532
- return root;
63533
- return searchForWorkspaceRoot(dir, root);
63534
- }
63535
-
63536
63940
  function warmupFiles(server) {
63537
63941
  const options = server.config.server.warmup;
63538
63942
  const root = server.config.root;
@@ -63844,7 +64248,17 @@ async function _createServer(inlineConfig = {}, options) {
63844
64248
  await container.watchChange(file, { event: isUnlink ? 'delete' : 'create' });
63845
64249
  if (publicDir && publicFiles) {
63846
64250
  if (file.startsWith(publicDir)) {
63847
- publicFiles[isUnlink ? 'delete' : 'add'](file.slice(publicDir.length));
64251
+ const path = file.slice(publicDir.length);
64252
+ publicFiles[isUnlink ? 'delete' : 'add'](path);
64253
+ if (!isUnlink) {
64254
+ const moduleWithSamePath = await moduleGraph.getModuleByUrl(path);
64255
+ const etag = moduleWithSamePath?.transformResult?.etag;
64256
+ if (etag) {
64257
+ // The public file should win on the next request over a module with the
64258
+ // same path. Prevent the transform etag fast path from serving the module
64259
+ moduleGraph.etagToModuleMap.delete(etag);
64260
+ }
64261
+ }
63848
64262
  }
63849
64263
  }
63850
64264
  await handleFileAddUnlink(file, server, isUnlink);
@@ -63895,6 +64309,7 @@ async function _createServer(inlineConfig = {}, options) {
63895
64309
  if (cors !== false) {
63896
64310
  middlewares.use(corsMiddleware(typeof cors === 'boolean' ? {} : cors));
63897
64311
  }
64312
+ middlewares.use(cachedTransformMiddleware(server));
63898
64313
  // proxy
63899
64314
  const { proxy } = serverConfig;
63900
64315
  if (proxy) {
@@ -64074,7 +64489,7 @@ function resolveServerOptions(root, raw, logger) {
64074
64489
  strict: server.fs?.strict ?? true,
64075
64490
  allow: allowDirs,
64076
64491
  deny,
64077
- cachedChecks: server.fs?.cachedChecks ?? !!process.env.VITE_SERVER_FS_CACHED_CHECKS,
64492
+ cachedChecks: server.fs?.cachedChecks ?? true,
64078
64493
  };
64079
64494
  if (server.origin?.endsWith('/')) {
64080
64495
  server.origin = server.origin.slice(0, -1);
@@ -65126,7 +65541,7 @@ function importAnalysisPlugin(config) {
65126
65541
  // `importedUrls` will be mixed with watched files for the module graph,
65127
65542
  // `staticImportedUrls` will only contain the static top-level imports and
65128
65543
  // dynamic imports
65129
- const staticImportedUrls = new Set(_orderedImportedUrls);
65544
+ const staticImportedUrls = new Set(_orderedImportedUrls.map((url) => removeTimestampQuery(url)));
65130
65545
  const acceptedUrls = mergeAcceptedUrls(orderedAcceptedUrls);
65131
65546
  const acceptedExports = mergeAcceptedUrls(orderedAcceptedExports);
65132
65547
  // While we always expect to work with ESM, a classic worker is the only
@@ -66045,7 +66460,7 @@ async function build(inlineConfig = {}) {
66045
66460
  const options = config.build;
66046
66461
  const ssr = !!options.ssr;
66047
66462
  const libOptions = options.lib;
66048
- config.logger.info(colors$1.cyan(`vite v${VERSION$1} ${colors$1.green(`building ${ssr ? `SSR bundle ` : ``}for ${config.mode}...`)}`));
66463
+ config.logger.info(colors$1.cyan(`vite v${VERSION} ${colors$1.green(`building ${ssr ? `SSR bundle ` : ``}for ${config.mode}...`)}`));
66049
66464
  const resolve = (p) => path$o.resolve(config.root, p);
66050
66465
  const input = libOptions
66051
66466
  ? options.rollupOptions?.input ||
@@ -66095,7 +66510,7 @@ async function build(inlineConfig = {}) {
66095
66510
  onRollupWarning(warning, warn, config);
66096
66511
  },
66097
66512
  };
66098
- const outputBuildError = (e) => {
66513
+ const mergeRollupError = (e) => {
66099
66514
  let msg = colors$1.red((e.plugin ? `[${e.plugin}] ` : '') + e.message);
66100
66515
  if (e.id) {
66101
66516
  msg += `\nfile: ${colors$1.cyan(e.id + (e.loc ? `:${e.loc.line}:${e.loc.column}` : ''))}`;
@@ -66103,6 +66518,10 @@ async function build(inlineConfig = {}) {
66103
66518
  if (e.frame) {
66104
66519
  msg += `\n` + colors$1.yellow(e.frame);
66105
66520
  }
66521
+ return msg;
66522
+ };
66523
+ const outputBuildError = (e) => {
66524
+ const msg = mergeRollupError(e);
66106
66525
  clearLine();
66107
66526
  config.logger.error(msg, { error: e });
66108
66527
  };
@@ -66215,7 +66634,8 @@ async function build(inlineConfig = {}) {
66215
66634
  return Array.isArray(outputs) ? res : res[0];
66216
66635
  }
66217
66636
  catch (e) {
66218
- outputBuildError(e);
66637
+ e.message = mergeRollupError(e);
66638
+ clearLine();
66219
66639
  throw e;
66220
66640
  }
66221
66641
  finally {
@@ -66719,7 +67139,7 @@ function resolvePreviewOptions(preview, server) {
66719
67139
  * Starts the Vite server in preview mode, to simulate a production deployment
66720
67140
  */
66721
67141
  async function preview(inlineConfig = {}) {
66722
- const config = await resolveConfig(inlineConfig, 'serve', 'production', 'production');
67142
+ const config = await resolveConfig(inlineConfig, 'serve', 'production', 'production', true);
66723
67143
  const distDir = path$o.resolve(config.root, config.build.outDir);
66724
67144
  if (!fs$l.existsSync(distDir) &&
66725
67145
  // error if no plugins implement `configurePreviewServer`
@@ -67119,6 +67539,7 @@ async function resolveConfig(inlineConfig, command, defaultMode = 'development',
67119
67539
  packageCache,
67120
67540
  createResolver,
67121
67541
  optimizeDeps: {
67542
+ holdUntilCrawlEnd: true,
67122
67543
  ...optimizeDeps,
67123
67544
  esbuildOptions: {
67124
67545
  preserveSymlinks: resolveOptions.preserveSymlinks,
@@ -67485,4 +67906,4 @@ function optimizeDepsDisabledBackwardCompatibility(resolved, optimizeDeps, optim
67485
67906
  }
67486
67907
  }
67487
67908
 
67488
- export { commonjsGlobal as A, index$1 as B, index as C, build$1 as D, preview$1 as E, arraify as a, build as b, createServer as c, defineConfig as d, preprocessCSS as e, formatPostcssSourceMap as f, buildErrorMessage as g, mergeAlias as h, isInNodeModules$1 as i, createFilter as j, send as k, loadConfigFromFile as l, mergeConfig as m, normalizePath$3 as n, optimizeDeps as o, preview as p, createLogger as q, resolveConfig as r, sortUserPlugins as s, transformWithEsbuild as t, searchForWorkspaceRoot as u, isFileServingAllowed as v, loadEnv as w, resolveEnvPrefix as x, colors$1 as y, getDefaultExportFromCjs as z };
67909
+ export { getDefaultExportFromCjs as A, commonjsGlobal as B, index$1 as C, index as D, build$1 as E, preview$1 as F, arraify as a, build as b, createServer as c, defineConfig as d, preprocessCSS as e, formatPostcssSourceMap as f, buildErrorMessage as g, mergeAlias as h, isInNodeModules$1 as i, createFilter as j, rollupVersion as k, loadConfigFromFile as l, mergeConfig as m, normalizePath$3 as n, optimizeDeps as o, preview as p, send as q, resolveConfig as r, sortUserPlugins as s, transformWithEsbuild as t, createLogger as u, searchForWorkspaceRoot as v, isFileServingAllowed as w, loadEnv as x, resolveEnvPrefix as y, colors$1 as z };