@4399ywkf/core 5.1.1 → 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/index.d.ts CHANGED
@@ -25,7 +25,6 @@ declare function build(options?: {
25
25
  * 启动开发服务器
26
26
  *
27
27
  * @param options.mode - env 文件模式,决定加载 .env.{mode},默认 "development"
28
- * 例如 --mode staging 会加载 .env.staging,但 NODE_ENV 仍为 "development"
29
28
  */
30
29
  declare function dev(options?: {
31
30
  cwd?: string;
@@ -129,17 +128,11 @@ declare class YwkfGeneratorPlugin {
129
128
  * 初始化插件钩子
130
129
  */
131
130
  private initialize;
132
- private resetState;
133
- private regenerate;
134
131
  apply(compiler: Compiler): void;
135
132
  /**
136
133
  * 监听页面目录变化
137
134
  */
138
135
  private watchPages;
139
- /**
140
- * 监听配置文件变化,重新加载配置并重新生成 .ywkf 文件
141
- */
142
- private watchConfig;
143
136
  }
144
137
 
145
138
  export { GeneratorContext, PluginConfig, PluginHooks, YwkfConfig, YwkfGenerator, YwkfGeneratorPlugin, type YwkfGeneratorPluginOptions, build, dev };
package/dist/index.js CHANGED
@@ -876,7 +876,7 @@ function createMockMiddleware(mockPath, options) {
876
876
  scanMockFiles(mockPath);
877
877
  return async (_req, _res, next) => {
878
878
  if (delay > 0) {
879
- await new Promise((resolve4) => setTimeout(resolve4, delay));
879
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
880
880
  }
881
881
  next();
882
882
  };
@@ -1830,11 +1830,11 @@ var zustandPlugin = createPlugin((options = {}) => ({
1830
1830
  const hooks = {
1831
1831
  modifyRspackConfig(rspackConfig) {
1832
1832
  logger.info("Zustand \u5DF2\u542F\u7528");
1833
- const resolve4 = rspackConfig.resolve || {};
1834
- const alias = resolve4.alias || {};
1833
+ const resolve5 = rspackConfig.resolve || {};
1834
+ const alias = resolve5.alias || {};
1835
1835
  alias["@store"] = storePath;
1836
- resolve4.alias = alias;
1837
- rspackConfig.resolve = resolve4;
1836
+ resolve5.alias = alias;
1837
+ rspackConfig.resolve = resolve5;
1838
1838
  return rspackConfig;
1839
1839
  },
1840
1840
  generateFiles(_ctx) {
@@ -2191,32 +2191,39 @@ function findConfigFile(cwd) {
2191
2191
  }
2192
2192
  return null;
2193
2193
  }
2194
- async function loadTsConfig(configPath) {
2194
+ async function loadTsConfig(configPath, fresh = false) {
2195
2195
  const jiti = (await import("jiti")).default;
2196
2196
  const loader = jiti(configPath, {
2197
- interopDefault: true
2197
+ interopDefault: true,
2198
+ // fresh(热重启)时必须禁用缓存:jiti 的 moduleCache 默认与 Node 原生 require 缓存集成,
2199
+ // 即使新建 jiti 实例,loader(configPath) 仍会命中 Node 全局缓存读回旧配置;
2200
+ // fsCache 为转译产物缓存,一并关闭以确保读到最新源码。
2201
+ ...fresh ? { moduleCache: false, fsCache: false } : {}
2198
2202
  });
2199
2203
  const config = loader(configPath);
2200
2204
  return config.default || config;
2201
2205
  }
2202
- async function loadJsConfig(configPath) {
2203
- 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
+ }
2204
2211
  const module = await import(fileUrl);
2205
2212
  return module.default || module;
2206
2213
  }
2207
- async function loadConfigFile(configPath) {
2214
+ async function loadConfigFile(configPath, opts = {}) {
2208
2215
  const ext = extname(configPath);
2209
2216
  if (ext === ".ts" || ext === ".mts") {
2210
- return loadTsConfig(configPath);
2217
+ return loadTsConfig(configPath, opts.fresh);
2211
2218
  }
2212
- return loadJsConfig(configPath);
2219
+ return loadJsConfig(configPath, opts.fresh);
2213
2220
  }
2214
2221
  function mergeConfig(userConfig, baseConfig = defaultConfig) {
2215
2222
  return deepmerge(baseConfig, userConfig, {
2216
2223
  arrayMerge: (_, sourceArray) => sourceArray
2217
2224
  });
2218
2225
  }
2219
- async function resolveConfig(cwd) {
2226
+ async function resolveConfig(cwd, opts = {}) {
2220
2227
  const configPath = findConfigFile(cwd);
2221
2228
  if (!configPath) {
2222
2229
  console.warn("\u26A0\uFE0F \u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6 (ywkf.config.ts)\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");
@@ -2226,7 +2233,7 @@ async function resolveConfig(cwd) {
2226
2233
  };
2227
2234
  }
2228
2235
  try {
2229
- const userConfig = await loadConfigFile(configPath);
2236
+ const userConfig = await loadConfigFile(configPath, opts);
2230
2237
  const normalized = normalizeConfig(userConfig);
2231
2238
  const config = mergeConfig(normalized);
2232
2239
  return { config, configPath };
@@ -3377,16 +3384,6 @@ var YwkfGeneratorPlugin = class {
3377
3384
  );
3378
3385
  this.initialized = true;
3379
3386
  }
3380
- resetState() {
3381
- this.initialized = false;
3382
- this.pluginHooks = [];
3383
- this.generator = null;
3384
- }
3385
- async regenerate() {
3386
- if (this.generator) {
3387
- await this.generator.generate();
3388
- }
3389
- }
3390
3387
  apply(compiler) {
3391
3388
  const pluginName = "YwkfGeneratorPlugin";
3392
3389
  compiler.hooks.beforeCompile.tapAsync(pluginName, async (_params, callback) => {
@@ -3402,14 +3399,13 @@ var YwkfGeneratorPlugin = class {
3402
3399
  }
3403
3400
  });
3404
3401
  if (this.options.isDev && !this.isWatching) {
3405
- this.watchPages();
3406
- this.watchConfig();
3402
+ this.watchPages(compiler);
3407
3403
  }
3408
3404
  }
3409
3405
  /**
3410
3406
  * 监听页面目录变化
3411
3407
  */
3412
- watchPages() {
3408
+ watchPages(compiler) {
3413
3409
  const { config, cwd } = this.options;
3414
3410
  const pagesDir = join11(cwd, config.router.pagesDir || "src/pages");
3415
3411
  if (!existsSync11(pagesDir)) {
@@ -3431,47 +3427,11 @@ var YwkfGeneratorPlugin = class {
3431
3427
  }
3432
3428
  }, 500);
3433
3429
  });
3434
- process.on("exit", () => {
3435
- watcher.close();
3436
- });
3437
- }
3438
- /**
3439
- * 监听配置文件变化,重新加载配置并重新生成 .ywkf 文件
3440
- */
3441
- watchConfig() {
3442
- const { cwd } = this.options;
3443
- const configPath = findConfigFile(cwd);
3444
- if (!configPath) {
3445
- return;
3446
- }
3447
- let debounceTimer = null;
3448
- const watcher = watch(configPath, async () => {
3449
- if (debounceTimer) {
3450
- clearTimeout(debounceTimer);
3451
- }
3452
- debounceTimer = setTimeout(async () => {
3453
- try {
3454
- console.log(`
3455
- [ywkf] \u68C0\u6D4B\u5230\u914D\u7F6E\u6587\u4EF6\u53D8\u5316\uFF0C\u91CD\u65B0\u751F\u6210 .ywkf \u76EE\u5F55...
3456
- `);
3457
- const userConfig = await loadConfigFile(configPath);
3458
- const newConfig = mergeConfig(userConfig);
3459
- this.options.config = newConfig;
3460
- this.options.pluginConfigs = newConfig.plugins;
3461
- this.resetState();
3462
- await this.initialize();
3463
- await this.regenerate();
3464
- console.log(
3465
- ` [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
3466
- `
3467
- );
3468
- } catch (error) {
3469
- console.error(` [ywkf] \u914D\u7F6E\u91CD\u8F7D\u5931\u8D25:`, error);
3470
- }
3471
- }, 500);
3472
- });
3473
- process.on("exit", () => {
3430
+ compiler.hooks.shutdown.tap("YwkfGeneratorPlugin", () => {
3431
+ if (debounceTimer) clearTimeout(debounceTimer);
3474
3432
  watcher.close();
3433
+ this.isWatching = false;
3434
+ this.hasGenerated = false;
3475
3435
  });
3476
3436
  }
3477
3437
  };
@@ -4341,7 +4301,7 @@ function createProgressHandler(printer) {
4341
4301
  printer.updateProgress(percent, message);
4342
4302
  };
4343
4303
  }
4344
- function registerShortcuts(printer, opts) {
4304
+ function registerShortcuts(getPrinter, opts) {
4345
4305
  if (!process.stdin.isTTY) return;
4346
4306
  process.stdin.setEncoding("utf-8");
4347
4307
  process.stdin.setRawMode?.(false);
@@ -4353,10 +4313,10 @@ function registerShortcuts(printer, opts) {
4353
4313
  buffer = "";
4354
4314
  switch (cmd) {
4355
4315
  case "h":
4356
- printer.printShortcuts();
4316
+ getPrinter().printShortcuts();
4357
4317
  break;
4358
4318
  case "o": {
4359
- const url = `http://localhost:${opts.port}/`;
4319
+ const url = `http://localhost:${opts.getPort()}/`;
4360
4320
  import("child_process").then((cp) => {
4361
4321
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
4362
4322
  cp.exec(`${command} ${url}`);
@@ -4438,7 +4398,7 @@ async function build(options = {}) {
4438
4398
  rspackConfig.stats = "none";
4439
4399
  rspackConfig.infrastructureLogging = { level: "none" };
4440
4400
  const compiler = rspack4(rspackConfig);
4441
- const stats = await new Promise((resolve4, reject) => {
4401
+ const stats = await new Promise((resolve5, reject) => {
4442
4402
  compiler.run((err, stats2) => {
4443
4403
  if (err) {
4444
4404
  reject(err);
@@ -4448,13 +4408,13 @@ async function build(options = {}) {
4448
4408
  reject(new Error("Build failed: no stats available"));
4449
4409
  return;
4450
4410
  }
4451
- resolve4(stats2);
4411
+ resolve5(stats2);
4452
4412
  });
4453
4413
  });
4454
- await new Promise((resolve4, reject) => {
4414
+ await new Promise((resolve5, reject) => {
4455
4415
  compiler.close((err) => {
4456
4416
  if (err) reject(err);
4457
- else resolve4();
4417
+ else resolve5();
4458
4418
  });
4459
4419
  });
4460
4420
  const hasErrors = stats.hasErrors();
@@ -4485,17 +4445,17 @@ import chalk3 from "chalk";
4485
4445
  // src/cli/port.ts
4486
4446
  import net from "net";
4487
4447
  function isPortAvailable(port, host) {
4488
- return new Promise((resolve4) => {
4448
+ return new Promise((resolve5) => {
4489
4449
  const server = net.createServer();
4490
4450
  server.once("error", (err) => {
4491
4451
  if (err.code === "EADDRINUSE") {
4492
- resolve4(false);
4452
+ resolve5(false);
4493
4453
  } else {
4494
- resolve4(false);
4454
+ resolve5(false);
4495
4455
  }
4496
4456
  });
4497
4457
  server.once("listening", () => {
4498
- server.close(() => resolve4(true));
4458
+ server.close(() => resolve5(true));
4499
4459
  });
4500
4460
  server.listen(port, host);
4501
4461
  });
@@ -4512,88 +4472,211 @@ async function getAvailablePort(preferredPort, host) {
4512
4472
  );
4513
4473
  }
4514
4474
 
4475
+ // src/cli/restart-watcher.ts
4476
+ import { existsSync as existsSync13, watch as watch2 } from "fs";
4477
+ import { resolve as resolve4 } from "path";
4478
+ function isTriggerFile(filename, mode) {
4479
+ if (!filename) return false;
4480
+ if (CONFIG_FILES.includes(filename)) return true;
4481
+ if (filename === ".env" || filename === ".env.public" || filename === `.env.${mode}`) {
4482
+ return true;
4483
+ }
4484
+ return false;
4485
+ }
4486
+ function normalizeFilename(filename) {
4487
+ if (typeof filename === "string") return filename;
4488
+ if (Buffer.isBuffer(filename)) return filename.toString("utf8");
4489
+ return null;
4490
+ }
4491
+ function watchForRestart(opts) {
4492
+ const { cwd, mode, onChange, debounceMs = 300 } = opts;
4493
+ const watchers = [];
4494
+ let timer = null;
4495
+ const trigger = (filename) => {
4496
+ const name = normalizeFilename(filename);
4497
+ if (!isTriggerFile(name, mode)) return;
4498
+ if (timer) clearTimeout(timer);
4499
+ timer = setTimeout(() => {
4500
+ timer = null;
4501
+ Promise.resolve(onChange()).catch((err) => {
4502
+ console.error("[ywkf] \u81EA\u52A8\u91CD\u542F\u56DE\u8C03\u51FA\u9519:", err);
4503
+ });
4504
+ }, debounceMs);
4505
+ };
4506
+ watchers.push(watch2(cwd, { recursive: false }, (_event, filename) => trigger(filename)));
4507
+ const envDir = resolve4(cwd, "config/env");
4508
+ if (existsSync13(envDir)) {
4509
+ watchers.push(watch2(envDir, { recursive: false }, (_event, filename) => trigger(filename)));
4510
+ }
4511
+ return {
4512
+ close: () => {
4513
+ if (timer) clearTimeout(timer);
4514
+ for (const w of watchers) w.close();
4515
+ }
4516
+ };
4517
+ }
4518
+
4515
4519
  // 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);
4520
+ function restoreEnv(snapshot) {
4521
+ for (const key of Object.keys(process.env)) {
4522
+ if (!(key in snapshot)) {
4523
+ delete process.env[key];
4526
4524
  }
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.
4525
+ }
4526
+ for (const key of Object.keys(snapshot)) {
4527
+ process.env[key] = snapshot[key];
4528
+ }
4529
+ }
4530
+ async function loadFullConfig(cwd, mode, envSnapshot, opts = {}) {
4531
+ restoreEnv(envSnapshot);
4532
+ preloadEnv(cwd, mode, "development");
4533
+ const { config } = await resolveConfig(cwd, { fresh: opts.fresh });
4534
+ loadEnv(config, cwd, mode, "development");
4535
+ return config;
4536
+ }
4537
+ async function startDevServer(cwd, config) {
4538
+ const pluginManager = new PluginManager(config, cwd, true);
4539
+ if (config.plugins && config.plugins.length > 0) {
4540
+ await pluginManager.loadPlugins(config.plugins);
4541
+ }
4542
+ await pluginManager.runBeforeDevServer();
4543
+ let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
4544
+ rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
4545
+ const host = config.dev.host || "localhost";
4546
+ const preferredPort = config.dev.port || 3e3;
4547
+ const port = await getAvailablePort(preferredPort, host);
4548
+ const pluginNames = pluginManager.getPluginNames();
4549
+ if (port !== preferredPort) {
4550
+ console.log(chalk3.yellow(` Port ${preferredPort} is in use, using ${port} instead.
4536
4551
  `));
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();
4552
+ }
4553
+ const printer = new DevPrinter(host, port, pluginNames);
4554
+ printer.printBanner();
4555
+ printer.printBuildStart();
4556
+ printer.updateProgress(0, "preparing");
4557
+ rspackConfig.plugins = rspackConfig.plugins || [];
4558
+ rspackConfig.plugins.push(new rspack5.ProgressPlugin(createProgressHandler(printer)));
4559
+ rspackConfig.stats = "none";
4560
+ rspackConfig.infrastructureLogging = { level: "none" };
4561
+ if (rspackConfig.devServer) {
4562
+ const ds = rspackConfig.devServer;
4563
+ const existingClient = ds.client ?? {};
4564
+ ds.client = {
4565
+ ...existingClient,
4566
+ logging: "warn",
4567
+ overlay: false,
4568
+ progress: false
4569
+ };
4570
+ }
4571
+ const compiler = rspack5(rspackConfig);
4572
+ compiler.hooks.done.tap("ywkf-dev-printer", (stats) => {
4573
+ const hasErrors = stats.hasErrors();
4574
+ if (hasErrors) {
4575
+ const info = stats.toJson({ errors: true });
4576
+ console.log();
4577
+ console.log(chalk3.red(" Compile error:"));
4578
+ for (const err of info.errors || []) {
4579
+ console.log(chalk3.red(` ${err.message}`));
4567
4580
  }
4568
- printer.printBuildDone(hasErrors);
4569
- });
4570
- compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
4571
- printer.markRebuildStart();
4572
- printer.updateProgress(0, "rebuilding");
4581
+ console.log();
4582
+ }
4583
+ printer.printBuildDone(hasErrors);
4584
+ });
4585
+ compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
4586
+ printer.markRebuildStart();
4587
+ printer.updateProgress(0, "rebuilding");
4588
+ });
4589
+ const devServerOptions = {
4590
+ ...rspackConfig.devServer || {},
4591
+ host,
4592
+ port,
4593
+ setupExitSignals: false
4594
+ };
4595
+ const server = new RspackDevServer(devServerOptions, compiler);
4596
+ await server.start();
4597
+ await pluginManager.runAfterDevServer({ host, port });
4598
+ let closed = false;
4599
+ const close = async () => {
4600
+ if (closed) return;
4601
+ closed = true;
4602
+ await server.stop();
4603
+ await new Promise((resolve5, reject) => {
4604
+ compiler.close((err) => {
4605
+ if (err) reject(err);
4606
+ else resolve5();
4607
+ });
4573
4608
  });
4574
- const devServerOptions = {
4575
- ...rspackConfig.devServer || {},
4576
- host,
4577
- port
4609
+ };
4610
+ return { printer, host, port, close };
4611
+ }
4612
+ async function dev(options = {}) {
4613
+ const cwd = options.cwd || process.cwd();
4614
+ const mode = options.mode || "development";
4615
+ const envSnapshot = { ...process.env };
4616
+ try {
4617
+ const config = await loadFullConfig(cwd, mode, envSnapshot);
4618
+ let current = await startDevServer(cwd, config);
4619
+ let shuttingDown = false;
4620
+ const shutdown = async () => {
4621
+ if (shuttingDown) return;
4622
+ shuttingDown = true;
4623
+ await current.close();
4624
+ process.exit(0);
4578
4625
  };
4579
- const server = new RspackDevServer(devServerOptions, compiler);
4580
- await server.start();
4581
- await pluginManager.runAfterDevServer({ host, port });
4582
- registerShortcuts(printer, {
4583
- port,
4626
+ registerShortcuts(() => current.printer, {
4627
+ getPort: () => current.port,
4584
4628
  onQuit: async () => {
4585
4629
  console.log(chalk3.gray("\n Shutting down...\n"));
4586
- await server.stop();
4587
- process.exit(0);
4630
+ await shutdown();
4588
4631
  }
4589
4632
  });
4590
4633
  const signals = ["SIGINT", "SIGTERM"];
4591
4634
  for (const signal of signals) {
4592
- process.on(signal, async () => {
4593
- await server.stop();
4594
- process.exit(0);
4635
+ process.on(signal, () => {
4636
+ void shutdown();
4595
4637
  });
4596
4638
  }
4639
+ let isRestarting = false;
4640
+ let pending = false;
4641
+ watchForRestart({
4642
+ cwd,
4643
+ mode,
4644
+ onChange: async () => {
4645
+ if (isRestarting) {
4646
+ pending = true;
4647
+ return;
4648
+ }
4649
+ isRestarting = true;
4650
+ try {
4651
+ do {
4652
+ pending = false;
4653
+ console.log(chalk3.cyan("\n \u27F3 \u68C0\u6D4B\u5230\u914D\u7F6E\u53D8\u66F4\uFF0C\u6B63\u5728\u91CD\u542F dev server...\n"));
4654
+ let nextConfig;
4655
+ try {
4656
+ nextConfig = await loadFullConfig(cwd, mode, envSnapshot, { fresh: true });
4657
+ } catch (error) {
4658
+ console.error(
4659
+ 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:")
4660
+ );
4661
+ console.error(error);
4662
+ restoreEnv(envSnapshot);
4663
+ continue;
4664
+ }
4665
+ try {
4666
+ await current.close();
4667
+ current = await startDevServer(cwd, nextConfig);
4668
+ } catch (error) {
4669
+ console.error(
4670
+ 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:")
4671
+ );
4672
+ console.error(error);
4673
+ }
4674
+ } while (pending);
4675
+ } finally {
4676
+ isRestarting = false;
4677
+ }
4678
+ }
4679
+ });
4597
4680
  } catch (error) {
4598
4681
  console.error();
4599
4682
  console.error(chalk3.red(" \u2716 Dev server failed to start"));
@@ -4603,7 +4686,7 @@ async function dev(options = {}) {
4603
4686
  }
4604
4687
 
4605
4688
  // src/router/plugin.ts
4606
- import { existsSync as existsSync13, watch as watch2 } from "fs";
4689
+ import { existsSync as existsSync14, watch as watch3 } from "fs";
4607
4690
  import { join as join14 } from "path";
4608
4691
  var ConventionalRoutePlugin = class {
4609
4692
  options;
@@ -4623,7 +4706,7 @@ var ConventionalRoutePlugin = class {
4623
4706
  callback();
4624
4707
  });
4625
4708
  if (this.options.watch && !this.isWatching) {
4626
- this.watchPages();
4709
+ this.watchPages(compiler);
4627
4710
  }
4628
4711
  }
4629
4712
  /**
@@ -4658,13 +4741,13 @@ var ConventionalRoutePlugin = class {
4658
4741
  /**
4659
4742
  * 监听页面目录变化
4660
4743
  */
4661
- watchPages() {
4662
- if (!existsSync13(this.options.pagesDir)) {
4744
+ watchPages(compiler) {
4745
+ if (!existsSync14(this.options.pagesDir)) {
4663
4746
  return;
4664
4747
  }
4665
4748
  this.isWatching = true;
4666
4749
  let debounceTimer = null;
4667
- const watcher = watch2(this.options.pagesDir, { recursive: true }, (_eventType, filename) => {
4750
+ const watcher = watch3(this.options.pagesDir, { recursive: true }, (_eventType, filename) => {
4668
4751
  if (!filename?.match(/\.(tsx?|jsx?)$/)) {
4669
4752
  return;
4670
4753
  }
@@ -4676,8 +4759,12 @@ var ConventionalRoutePlugin = class {
4676
4759
  this.generateRoutes();
4677
4760
  }, 500);
4678
4761
  });
4679
- process.on("exit", () => {
4762
+ compiler.hooks.shutdown.tap("ConventionalRoutePlugin", () => {
4763
+ if (debounceTimer) clearTimeout(debounceTimer);
4680
4764
  watcher.close();
4765
+ this.isWatching = false;
4766
+ this.hasGenerated = false;
4767
+ this.lastGeneratedContent = "";
4681
4768
  });
4682
4769
  }
4683
4770
  };