@4399ywkf/core 5.0.32 → 5.1.2

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/cli/index.js CHANGED
@@ -380,8 +380,7 @@ var garfishPlugin = createPlugin((options = {}) => ({
380
380
  if (!master) {
381
381
  rspackConfig.output = {
382
382
  ...rspackConfig.output,
383
- library: finalAppName,
384
- libraryTarget: "umd",
383
+ library: { type: "umd", name: finalAppName },
385
384
  globalObject: "window",
386
385
  chunkLoadingGlobal: `garfish_${finalAppName}`
387
386
  };
@@ -880,7 +879,7 @@ function createMockMiddleware(mockPath, options) {
880
879
  scanMockFiles(mockPath);
881
880
  return async (_req, _res, next) => {
882
881
  if (delay > 0) {
883
- await new Promise((resolve4) => setTimeout(resolve4, delay));
882
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
884
883
  }
885
884
  next();
886
885
  };
@@ -1834,11 +1833,11 @@ var zustandPlugin = createPlugin((options = {}) => ({
1834
1833
  const hooks = {
1835
1834
  modifyRspackConfig(rspackConfig) {
1836
1835
  logger.info("Zustand \u5DF2\u542F\u7528");
1837
- const resolve4 = rspackConfig.resolve || {};
1838
- const alias = resolve4.alias || {};
1836
+ const resolve5 = rspackConfig.resolve || {};
1837
+ const alias = resolve5.alias || {};
1839
1838
  alias["@store"] = storePath;
1840
- resolve4.alias = alias;
1841
- rspackConfig.resolve = resolve4;
1839
+ resolve5.alias = alias;
1840
+ rspackConfig.resolve = resolve5;
1842
1841
  return rspackConfig;
1843
1842
  },
1844
1843
  generateFiles(_ctx) {
@@ -2192,32 +2191,39 @@ function findConfigFile(cwd) {
2192
2191
  }
2193
2192
  return null;
2194
2193
  }
2195
- async function loadTsConfig(configPath) {
2194
+ async function loadTsConfig(configPath, fresh = false) {
2196
2195
  const jiti = (await import("jiti")).default;
2197
2196
  const loader = jiti(configPath, {
2198
- interopDefault: true
2197
+ interopDefault: true,
2198
+ // fresh(热重启)时必须禁用缓存:jiti 的 moduleCache 默认与 Node 原生 require 缓存集成,
2199
+ // 即使新建 jiti 实例,loader(configPath) 仍会命中 Node 全局缓存读回旧配置;
2200
+ // fsCache 为转译产物缓存,一并关闭以确保读到最新源码。
2201
+ ...fresh ? { moduleCache: false, fsCache: false } : {}
2199
2202
  });
2200
2203
  const config = loader(configPath);
2201
2204
  return config.default || config;
2202
2205
  }
2203
- async function loadJsConfig(configPath) {
2204
- const fileUrl = pathToFileURL(configPath).href;
2206
+ async function loadJsConfig(configPath, fresh = false) {
2207
+ let fileUrl = pathToFileURL(configPath).href;
2208
+ if (fresh) {
2209
+ fileUrl += `?t=${Date.now()}`;
2210
+ }
2205
2211
  const module = await import(fileUrl);
2206
2212
  return module.default || module;
2207
2213
  }
2208
- async function loadConfigFile(configPath) {
2214
+ async function loadConfigFile(configPath, opts = {}) {
2209
2215
  const ext = extname(configPath);
2210
2216
  if (ext === ".ts" || ext === ".mts") {
2211
- return loadTsConfig(configPath);
2217
+ return loadTsConfig(configPath, opts.fresh);
2212
2218
  }
2213
- return loadJsConfig(configPath);
2219
+ return loadJsConfig(configPath, opts.fresh);
2214
2220
  }
2215
2221
  function mergeConfig(userConfig, baseConfig = defaultConfig) {
2216
2222
  return deepmerge(baseConfig, userConfig, {
2217
2223
  arrayMerge: (_, sourceArray) => sourceArray
2218
2224
  });
2219
2225
  }
2220
- async function resolveConfig(cwd) {
2226
+ async function resolveConfig(cwd, opts = {}) {
2221
2227
  const configPath = findConfigFile(cwd);
2222
2228
  if (!configPath) {
2223
2229
  console.warn("\u26A0\uFE0F \u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6 (ywkf.config.ts)\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");
@@ -2227,7 +2233,7 @@ async function resolveConfig(cwd) {
2227
2233
  };
2228
2234
  }
2229
2235
  try {
2230
- const userConfig = await loadConfigFile(configPath);
2236
+ const userConfig = await loadConfigFile(configPath, opts);
2231
2237
  const normalized = normalizeConfig(userConfig);
2232
2238
  const config = mergeConfig(normalized);
2233
2239
  return { config, configPath };
@@ -2475,7 +2481,7 @@ import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
2475
2481
 
2476
2482
  // src/rspack/dev.ts
2477
2483
  import { createRequire as createRequire2 } from "module";
2478
- import ReactRefreshPlugin from "@rspack/plugin-react-refresh";
2484
+ import { ReactRefreshRspackPlugin } from "@rspack/plugin-react-refresh";
2479
2485
  import { merge } from "webpack-merge";
2480
2486
 
2481
2487
  // src/rspack/base.ts
@@ -3375,16 +3381,6 @@ var YwkfGeneratorPlugin = class {
3375
3381
  );
3376
3382
  this.initialized = true;
3377
3383
  }
3378
- resetState() {
3379
- this.initialized = false;
3380
- this.pluginHooks = [];
3381
- this.generator = null;
3382
- }
3383
- async regenerate() {
3384
- if (this.generator) {
3385
- await this.generator.generate();
3386
- }
3387
- }
3388
3384
  apply(compiler) {
3389
3385
  const pluginName = "YwkfGeneratorPlugin";
3390
3386
  compiler.hooks.beforeCompile.tapAsync(pluginName, async (_params, callback) => {
@@ -3400,14 +3396,13 @@ var YwkfGeneratorPlugin = class {
3400
3396
  }
3401
3397
  });
3402
3398
  if (this.options.isDev && !this.isWatching) {
3403
- this.watchPages();
3404
- this.watchConfig();
3399
+ this.watchPages(compiler);
3405
3400
  }
3406
3401
  }
3407
3402
  /**
3408
3403
  * 监听页面目录变化
3409
3404
  */
3410
- watchPages() {
3405
+ watchPages(compiler) {
3411
3406
  const { config, cwd } = this.options;
3412
3407
  const pagesDir = join11(cwd, config.router.pagesDir || "src/pages");
3413
3408
  if (!existsSync11(pagesDir)) {
@@ -3429,47 +3424,11 @@ var YwkfGeneratorPlugin = class {
3429
3424
  }
3430
3425
  }, 500);
3431
3426
  });
3432
- process.on("exit", () => {
3433
- watcher.close();
3434
- });
3435
- }
3436
- /**
3437
- * 监听配置文件变化,重新加载配置并重新生成 .ywkf 文件
3438
- */
3439
- watchConfig() {
3440
- const { cwd } = this.options;
3441
- const configPath = findConfigFile(cwd);
3442
- if (!configPath) {
3443
- return;
3444
- }
3445
- let debounceTimer = null;
3446
- const watcher = watch(configPath, async () => {
3447
- if (debounceTimer) {
3448
- clearTimeout(debounceTimer);
3449
- }
3450
- debounceTimer = setTimeout(async () => {
3451
- try {
3452
- console.log(`
3453
- [ywkf] \u68C0\u6D4B\u5230\u914D\u7F6E\u6587\u4EF6\u53D8\u5316\uFF0C\u91CD\u65B0\u751F\u6210 .ywkf \u76EE\u5F55...
3454
- `);
3455
- const userConfig = await loadConfigFile(configPath);
3456
- const newConfig = mergeConfig(userConfig);
3457
- this.options.config = newConfig;
3458
- this.options.pluginConfigs = newConfig.plugins;
3459
- this.resetState();
3460
- await this.initialize();
3461
- await this.regenerate();
3462
- console.log(
3463
- ` [ywkf] .ywkf \u76EE\u5F55\u5DF2\u91CD\u65B0\u751F\u6210\u3002\u90E8\u5206\u914D\u7F6E\u53D8\u66F4\uFF08\u5982\u7AEF\u53E3\u3001\u4EE3\u7406\uFF09\u9700\u91CD\u542F dev server \u751F\u6548\u3002
3464
- `
3465
- );
3466
- } catch (error) {
3467
- console.error(` [ywkf] \u914D\u7F6E\u91CD\u8F7D\u5931\u8D25:`, error);
3468
- }
3469
- }, 500);
3470
- });
3471
- process.on("exit", () => {
3427
+ compiler.hooks.shutdown.tap("YwkfGeneratorPlugin", () => {
3428
+ if (debounceTimer) clearTimeout(debounceTimer);
3472
3429
  watcher.close();
3430
+ this.isWatching = false;
3431
+ this.hasGenerated = false;
3473
3432
  });
3474
3433
  }
3475
3434
  };
@@ -3638,9 +3597,8 @@ function createBaseConfig(config, cwd, options = {}) {
3638
3597
  ].filter(Boolean),
3639
3598
  output: {
3640
3599
  assetModuleFilename: "images/[hash][ext]",
3641
- library: microFrontend.enabled ? `${appCName}-[name]` : void 0,
3600
+ library: microFrontend.enabled ? { type: "umd", name: `${appCName}-[name]` } : void 0,
3642
3601
  chunkFilename: "[name].[contenthash].js",
3643
- libraryTarget: microFrontend.enabled ? "umd" : void 0,
3644
3602
  globalObject: microFrontend.enabled ? "window" : void 0,
3645
3603
  chunkLoadingGlobal: microFrontend.enabled ? `chunk_global_${appName}` : void 0,
3646
3604
  publicPath: output.publicPath ?? "/",
@@ -3861,7 +3819,7 @@ function createDevConfig(config, cwd) {
3861
3819
  clean: false
3862
3820
  },
3863
3821
  stats: "errors-only",
3864
- plugins: [new ReactRefreshPlugin()],
3822
+ plugins: [new ReactRefreshRspackPlugin()],
3865
3823
  devServer: {
3866
3824
  host: dev2.host,
3867
3825
  port: dev2.port,
@@ -4242,7 +4200,6 @@ var DevPrinter = class {
4242
4200
  */
4243
4201
  printBuildStart() {
4244
4202
  this.startTime = Date.now();
4245
- this.compileDone = false;
4246
4203
  const label = chalk.gray("start");
4247
4204
  console.log(` ${label} build started...`);
4248
4205
  }
@@ -4337,11 +4294,11 @@ var DevPrinter = class {
4337
4294
  }
4338
4295
  };
4339
4296
  function createProgressHandler(printer) {
4340
- return (percent, message, ..._details) => {
4297
+ return (percent, message) => {
4341
4298
  printer.updateProgress(percent, message);
4342
4299
  };
4343
4300
  }
4344
- function registerShortcuts(printer, opts) {
4301
+ function registerShortcuts(getPrinter, opts) {
4345
4302
  if (!process.stdin.isTTY) return;
4346
4303
  process.stdin.setEncoding("utf-8");
4347
4304
  process.stdin.setRawMode?.(false);
@@ -4353,10 +4310,10 @@ function registerShortcuts(printer, opts) {
4353
4310
  buffer = "";
4354
4311
  switch (cmd) {
4355
4312
  case "h":
4356
- printer.printShortcuts();
4313
+ getPrinter().printShortcuts();
4357
4314
  break;
4358
4315
  case "o": {
4359
- const url = `http://localhost:${opts.port}/`;
4316
+ const url = `http://localhost:${opts.getPort()}/`;
4360
4317
  import("child_process").then((cp) => {
4361
4318
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
4362
4319
  cp.exec(`${command} ${url}`);
@@ -4438,7 +4395,7 @@ async function build(options = {}) {
4438
4395
  rspackConfig.stats = "none";
4439
4396
  rspackConfig.infrastructureLogging = { level: "none" };
4440
4397
  const compiler = rspack4(rspackConfig);
4441
- const stats = await new Promise((resolve4, reject) => {
4398
+ const stats = await new Promise((resolve5, reject) => {
4442
4399
  compiler.run((err, stats2) => {
4443
4400
  if (err) {
4444
4401
  reject(err);
@@ -4448,13 +4405,13 @@ async function build(options = {}) {
4448
4405
  reject(new Error("Build failed: no stats available"));
4449
4406
  return;
4450
4407
  }
4451
- resolve4(stats2);
4408
+ resolve5(stats2);
4452
4409
  });
4453
4410
  });
4454
- await new Promise((resolve4, reject) => {
4411
+ await new Promise((resolve5, reject) => {
4455
4412
  compiler.close((err) => {
4456
4413
  if (err) reject(err);
4457
- else resolve4();
4414
+ else resolve5();
4458
4415
  });
4459
4416
  });
4460
4417
  const hasErrors = stats.hasErrors();
@@ -4485,17 +4442,17 @@ import chalk3 from "chalk";
4485
4442
  // src/cli/port.ts
4486
4443
  import net from "net";
4487
4444
  function isPortAvailable(port, host) {
4488
- return new Promise((resolve4) => {
4445
+ return new Promise((resolve5) => {
4489
4446
  const server = net.createServer();
4490
4447
  server.once("error", (err) => {
4491
4448
  if (err.code === "EADDRINUSE") {
4492
- resolve4(false);
4449
+ resolve5(false);
4493
4450
  } else {
4494
- resolve4(false);
4451
+ resolve5(false);
4495
4452
  }
4496
4453
  });
4497
4454
  server.once("listening", () => {
4498
- server.close(() => resolve4(true));
4455
+ server.close(() => resolve5(true));
4499
4456
  });
4500
4457
  server.listen(port, host);
4501
4458
  });
@@ -4512,88 +4469,211 @@ async function getAvailablePort(preferredPort, host) {
4512
4469
  );
4513
4470
  }
4514
4471
 
4472
+ // src/cli/restart-watcher.ts
4473
+ import { existsSync as existsSync13, watch as watch2 } from "fs";
4474
+ import { resolve as resolve4 } from "path";
4475
+ function isTriggerFile(filename, mode) {
4476
+ if (!filename) return false;
4477
+ if (CONFIG_FILES.includes(filename)) return true;
4478
+ if (filename === ".env" || filename === ".env.public" || filename === `.env.${mode}`) {
4479
+ return true;
4480
+ }
4481
+ return false;
4482
+ }
4483
+ function normalizeFilename(filename) {
4484
+ if (typeof filename === "string") return filename;
4485
+ if (Buffer.isBuffer(filename)) return filename.toString("utf8");
4486
+ return null;
4487
+ }
4488
+ function watchForRestart(opts) {
4489
+ const { cwd, mode, onChange, debounceMs = 300 } = opts;
4490
+ const watchers = [];
4491
+ let timer = null;
4492
+ const trigger = (filename) => {
4493
+ const name = normalizeFilename(filename);
4494
+ if (!isTriggerFile(name, mode)) return;
4495
+ if (timer) clearTimeout(timer);
4496
+ timer = setTimeout(() => {
4497
+ timer = null;
4498
+ Promise.resolve(onChange()).catch((err) => {
4499
+ console.error("[ywkf] \u81EA\u52A8\u91CD\u542F\u56DE\u8C03\u51FA\u9519:", err);
4500
+ });
4501
+ }, debounceMs);
4502
+ };
4503
+ watchers.push(watch2(cwd, { recursive: false }, (_event, filename) => trigger(filename)));
4504
+ const envDir = resolve4(cwd, "config/env");
4505
+ if (existsSync13(envDir)) {
4506
+ watchers.push(watch2(envDir, { recursive: false }, (_event, filename) => trigger(filename)));
4507
+ }
4508
+ return {
4509
+ close: () => {
4510
+ if (timer) clearTimeout(timer);
4511
+ for (const w of watchers) w.close();
4512
+ }
4513
+ };
4514
+ }
4515
+
4515
4516
  // src/cli/dev.ts
4516
- async function dev(options = {}) {
4517
- const cwd = options.cwd || process.cwd();
4518
- const mode = options.mode || "development";
4519
- try {
4520
- preloadEnv(cwd, mode, "development");
4521
- const { config } = await resolveConfig(cwd);
4522
- loadEnv(config, cwd, mode, "development");
4523
- const pluginManager = new PluginManager(config, cwd, true);
4524
- if (config.plugins && config.plugins.length > 0) {
4525
- await pluginManager.loadPlugins(config.plugins);
4517
+ function restoreEnv(snapshot) {
4518
+ for (const key of Object.keys(process.env)) {
4519
+ if (!(key in snapshot)) {
4520
+ delete process.env[key];
4526
4521
  }
4527
- await pluginManager.runBeforeDevServer();
4528
- let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
4529
- rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
4530
- const host = config.dev.host || "localhost";
4531
- const preferredPort = config.dev.port || 3e3;
4532
- const port = await getAvailablePort(preferredPort, host);
4533
- const pluginNames = pluginManager.getPluginNames();
4534
- if (port !== preferredPort) {
4535
- console.log(chalk3.yellow(` Port ${preferredPort} is in use, using ${port} instead.
4522
+ }
4523
+ for (const key of Object.keys(snapshot)) {
4524
+ process.env[key] = snapshot[key];
4525
+ }
4526
+ }
4527
+ async function loadFullConfig(cwd, mode, envSnapshot, opts = {}) {
4528
+ restoreEnv(envSnapshot);
4529
+ preloadEnv(cwd, mode, "development");
4530
+ const { config } = await resolveConfig(cwd, { fresh: opts.fresh });
4531
+ loadEnv(config, cwd, mode, "development");
4532
+ return config;
4533
+ }
4534
+ async function startDevServer(cwd, config) {
4535
+ const pluginManager = new PluginManager(config, cwd, true);
4536
+ if (config.plugins && config.plugins.length > 0) {
4537
+ await pluginManager.loadPlugins(config.plugins);
4538
+ }
4539
+ await pluginManager.runBeforeDevServer();
4540
+ let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
4541
+ rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
4542
+ const host = config.dev.host || "localhost";
4543
+ const preferredPort = config.dev.port || 3e3;
4544
+ const port = await getAvailablePort(preferredPort, host);
4545
+ const pluginNames = pluginManager.getPluginNames();
4546
+ if (port !== preferredPort) {
4547
+ console.log(chalk3.yellow(` Port ${preferredPort} is in use, using ${port} instead.
4536
4548
  `));
4537
- }
4538
- const printer = new DevPrinter(host, port, pluginNames);
4539
- printer.printBanner();
4540
- printer.printBuildStart();
4541
- printer.updateProgress(0, "preparing");
4542
- rspackConfig.plugins = rspackConfig.plugins || [];
4543
- rspackConfig.plugins.push(new rspack5.ProgressPlugin(createProgressHandler(printer)));
4544
- rspackConfig.stats = "none";
4545
- rspackConfig.infrastructureLogging = { level: "none" };
4546
- if (rspackConfig.devServer) {
4547
- const ds = rspackConfig.devServer;
4548
- const existingClient = ds.client ?? {};
4549
- ds.client = {
4550
- ...existingClient,
4551
- logging: "warn",
4552
- overlay: false,
4553
- progress: false
4554
- };
4555
- }
4556
- const compiler = rspack5(rspackConfig);
4557
- compiler.hooks.done.tap("ywkf-dev-printer", (stats) => {
4558
- const hasErrors = stats.hasErrors();
4559
- if (hasErrors) {
4560
- const info = stats.toJson({ errors: true });
4561
- console.log();
4562
- console.log(chalk3.red(" Compile error:"));
4563
- for (const err of info.errors || []) {
4564
- console.log(chalk3.red(` ${err.message}`));
4565
- }
4566
- console.log();
4549
+ }
4550
+ const printer = new DevPrinter(host, port, pluginNames);
4551
+ printer.printBanner();
4552
+ printer.printBuildStart();
4553
+ printer.updateProgress(0, "preparing");
4554
+ rspackConfig.plugins = rspackConfig.plugins || [];
4555
+ rspackConfig.plugins.push(new rspack5.ProgressPlugin(createProgressHandler(printer)));
4556
+ rspackConfig.stats = "none";
4557
+ rspackConfig.infrastructureLogging = { level: "none" };
4558
+ if (rspackConfig.devServer) {
4559
+ const ds = rspackConfig.devServer;
4560
+ const existingClient = ds.client ?? {};
4561
+ ds.client = {
4562
+ ...existingClient,
4563
+ logging: "warn",
4564
+ overlay: false,
4565
+ progress: false
4566
+ };
4567
+ }
4568
+ const compiler = rspack5(rspackConfig);
4569
+ compiler.hooks.done.tap("ywkf-dev-printer", (stats) => {
4570
+ const hasErrors = stats.hasErrors();
4571
+ if (hasErrors) {
4572
+ const info = stats.toJson({ errors: true });
4573
+ console.log();
4574
+ console.log(chalk3.red(" Compile error:"));
4575
+ for (const err of info.errors || []) {
4576
+ console.log(chalk3.red(` ${err.message}`));
4567
4577
  }
4568
- printer.printBuildDone(hasErrors);
4569
- });
4570
- compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
4571
- printer.markRebuildStart();
4572
- printer.updateProgress(0, "rebuilding");
4578
+ console.log();
4579
+ }
4580
+ printer.printBuildDone(hasErrors);
4581
+ });
4582
+ compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
4583
+ printer.markRebuildStart();
4584
+ printer.updateProgress(0, "rebuilding");
4585
+ });
4586
+ const devServerOptions = {
4587
+ ...rspackConfig.devServer || {},
4588
+ host,
4589
+ port,
4590
+ setupExitSignals: false
4591
+ };
4592
+ const server = new RspackDevServer(devServerOptions, compiler);
4593
+ await server.start();
4594
+ await pluginManager.runAfterDevServer({ host, port });
4595
+ let closed = false;
4596
+ const close = async () => {
4597
+ if (closed) return;
4598
+ closed = true;
4599
+ await server.stop();
4600
+ await new Promise((resolve5, reject) => {
4601
+ compiler.close((err) => {
4602
+ if (err) reject(err);
4603
+ else resolve5();
4604
+ });
4573
4605
  });
4574
- const devServerOptions = {
4575
- ...rspackConfig.devServer || {},
4576
- host,
4577
- port
4606
+ };
4607
+ return { printer, host, port, close };
4608
+ }
4609
+ async function dev(options = {}) {
4610
+ const cwd = options.cwd || process.cwd();
4611
+ const mode = options.mode || "development";
4612
+ const envSnapshot = { ...process.env };
4613
+ try {
4614
+ const config = await loadFullConfig(cwd, mode, envSnapshot);
4615
+ let current = await startDevServer(cwd, config);
4616
+ let shuttingDown = false;
4617
+ const shutdown = async () => {
4618
+ if (shuttingDown) return;
4619
+ shuttingDown = true;
4620
+ await current.close();
4621
+ process.exit(0);
4578
4622
  };
4579
- const server = new RspackDevServer(devServerOptions, compiler);
4580
- await server.start();
4581
- await pluginManager.runAfterDevServer({ host, port });
4582
- registerShortcuts(printer, {
4583
- port,
4623
+ registerShortcuts(() => current.printer, {
4624
+ getPort: () => current.port,
4584
4625
  onQuit: async () => {
4585
4626
  console.log(chalk3.gray("\n Shutting down...\n"));
4586
- await server.stop();
4587
- process.exit(0);
4627
+ await shutdown();
4588
4628
  }
4589
4629
  });
4590
4630
  const signals = ["SIGINT", "SIGTERM"];
4591
4631
  for (const signal of signals) {
4592
- process.on(signal, async () => {
4593
- await server.stop();
4594
- process.exit(0);
4632
+ process.on(signal, () => {
4633
+ void shutdown();
4595
4634
  });
4596
4635
  }
4636
+ let isRestarting = false;
4637
+ let pending = false;
4638
+ watchForRestart({
4639
+ cwd,
4640
+ mode,
4641
+ onChange: async () => {
4642
+ if (isRestarting) {
4643
+ pending = true;
4644
+ return;
4645
+ }
4646
+ isRestarting = true;
4647
+ try {
4648
+ do {
4649
+ pending = false;
4650
+ console.log(chalk3.cyan("\n \u27F3 \u68C0\u6D4B\u5230\u914D\u7F6E\u53D8\u66F4\uFF0C\u6B63\u5728\u91CD\u542F dev server...\n"));
4651
+ let nextConfig;
4652
+ try {
4653
+ nextConfig = await loadFullConfig(cwd, mode, envSnapshot, { fresh: true });
4654
+ } catch (error) {
4655
+ console.error(
4656
+ chalk3.red(" \u2716 \u914D\u7F6E\u52A0\u8F7D\u5931\u8D25\uFF0C\u4FDD\u6301\u5F53\u524D dev server \u8FD0\u884C\uFF08\u4FEE\u6B63\u540E\u4FDD\u5B58\u53EF\u91CD\u8BD5\uFF09:")
4657
+ );
4658
+ console.error(error);
4659
+ restoreEnv(envSnapshot);
4660
+ continue;
4661
+ }
4662
+ try {
4663
+ await current.close();
4664
+ current = await startDevServer(cwd, nextConfig);
4665
+ } catch (error) {
4666
+ console.error(
4667
+ chalk3.red(" \u2716 dev server \u91CD\u542F\u5931\u8D25\uFF0C\u5F53\u524D\u670D\u52A1\u4E0D\u53EF\u7528\uFF0C\u8BF7\u4FEE\u6B63\u540E\u4FDD\u5B58\u91CD\u8BD5:")
4668
+ );
4669
+ console.error(error);
4670
+ }
4671
+ } while (pending);
4672
+ } finally {
4673
+ isRestarting = false;
4674
+ }
4675
+ }
4676
+ });
4597
4677
  } catch (error) {
4598
4678
  console.error();
4599
4679
  console.error(chalk3.red(" \u2716 Dev server failed to start"));