@4399ywkf/core 5.1.2 → 5.1.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.
package/dist/index.js CHANGED
@@ -2127,7 +2127,7 @@ var defaultConfig = {
2127
2127
  strictMode: true,
2128
2128
  dev: {
2129
2129
  port: 3e3,
2130
- host: "localhost",
2130
+ host: "127.0.0.1",
2131
2131
  proxy: {},
2132
2132
  https: false
2133
2133
  },
@@ -4172,6 +4172,10 @@ function getNetworkAddress(port) {
4172
4172
  }
4173
4173
  return null;
4174
4174
  }
4175
+ function displayHost(host) {
4176
+ if (host === "0.0.0.0" || host === "::") return "localhost";
4177
+ return host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
4178
+ }
4175
4179
  var BAR_WIDTH = 30;
4176
4180
  function renderBar(percent) {
4177
4181
  const filled = Math.round(BAR_WIDTH * percent);
@@ -4273,7 +4277,7 @@ var DevPrinter = class {
4273
4277
  * 打印服务器信息面板(dev 模式使用)
4274
4278
  */
4275
4279
  printServerInfo() {
4276
- const localUrl = `http://localhost:${this.port}/`;
4280
+ const localUrl = `http://${displayHost(this._host)}:${this.port}/`;
4277
4281
  const networkUrl = getNetworkAddress(this.port);
4278
4282
  console.log(` ${chalk.bold(">")} Local: ${chalk.cyan(localUrl)}`);
4279
4283
  if (networkUrl) {
@@ -4316,7 +4320,7 @@ function registerShortcuts(getPrinter, opts) {
4316
4320
  getPrinter().printShortcuts();
4317
4321
  break;
4318
4322
  case "o": {
4319
- const url = `http://localhost:${opts.getPort()}/`;
4323
+ const url = `http://${displayHost(opts.getHost())}:${opts.getPort()}/`;
4320
4324
  import("child_process").then((cp) => {
4321
4325
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
4322
4326
  cp.exec(`${command} ${url}`);
@@ -4389,7 +4393,7 @@ async function build(options = {}) {
4389
4393
  let rspackConfig = createRspackConfig(config, cwd, { isDev: false });
4390
4394
  rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
4391
4395
  const pluginNames = pluginManager.getPluginNames();
4392
- const printer = new DevPrinter("localhost", 0, pluginNames, true);
4396
+ const printer = new DevPrinter("127.0.0.1", 0, pluginNames, true);
4393
4397
  printer.printBanner();
4394
4398
  printer.printBuildStart();
4395
4399
  printer.updateProgress(0, "preparing");
@@ -4443,33 +4447,74 @@ import { RspackDevServer } from "@rspack/dev-server";
4443
4447
  import chalk3 from "chalk";
4444
4448
 
4445
4449
  // src/cli/port.ts
4450
+ import { execFile } from "child_process";
4446
4451
  import net from "net";
4447
- function isPortAvailable(port, host) {
4448
- return new Promise((resolve5) => {
4452
+ import { promisify } from "util";
4453
+ var execFileAsync = promisify(execFile);
4454
+ var PortInUseError = class extends Error {
4455
+ constructor(port, host) {
4456
+ super(`Port ${port} is already in use on ${host}`);
4457
+ this.port = port;
4458
+ this.host = host;
4459
+ this.name = "PortInUseError";
4460
+ }
4461
+ };
4462
+ function ensurePortAvailable(port, host) {
4463
+ return new Promise((resolve5, reject) => {
4449
4464
  const server = net.createServer();
4450
4465
  server.once("error", (err) => {
4451
4466
  if (err.code === "EADDRINUSE") {
4452
- resolve5(false);
4467
+ reject(new PortInUseError(port, host));
4453
4468
  } else {
4454
- resolve5(false);
4469
+ reject(err);
4455
4470
  }
4456
4471
  });
4457
4472
  server.once("listening", () => {
4458
- server.close(() => resolve5(true));
4473
+ server.close(() => resolve5());
4459
4474
  });
4460
4475
  server.listen(port, host);
4461
4476
  });
4462
4477
  }
4463
- async function getAvailablePort(preferredPort, host) {
4464
- const MAX_ATTEMPTS = 20;
4465
- for (let i = 0; i < MAX_ATTEMPTS; i++) {
4466
- const port = preferredPort + i;
4467
- const available = await isPortAvailable(port, host);
4468
- if (available) return port;
4478
+ async function findPortHolder(port) {
4479
+ try {
4480
+ if (process.platform === "win32") {
4481
+ const { stdout: stdout2 } = await execFileAsync("netstat", ["-ano", "-p", "tcp"], {
4482
+ timeout: 1500
4483
+ });
4484
+ const pid2 = parseWindowsNetstatPid(stdout2, port);
4485
+ return pid2 === null ? null : { pid: pid2 };
4486
+ }
4487
+ const { stdout } = await execFileAsync(
4488
+ "lsof",
4489
+ ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"],
4490
+ { timeout: 1500 }
4491
+ );
4492
+ const pid = Number.parseInt(stdout.trim().split(/\s+/)[0], 10);
4493
+ if (!Number.isInteger(pid)) return null;
4494
+ let name;
4495
+ try {
4496
+ const { stdout: comm } = await execFileAsync(
4497
+ "ps",
4498
+ ["-p", String(pid), "-o", "comm="],
4499
+ { timeout: 1500 }
4500
+ );
4501
+ name = comm.trim().split("/").pop() || void 0;
4502
+ } catch {
4503
+ }
4504
+ return { pid, name };
4505
+ } catch {
4506
+ return null;
4469
4507
  }
4470
- throw new Error(
4471
- `No available port found in range ${preferredPort}-${preferredPort + MAX_ATTEMPTS - 1}`
4472
- );
4508
+ }
4509
+ function parseWindowsNetstatPid(stdout, port) {
4510
+ for (const line of stdout.split(/\r?\n/)) {
4511
+ const parts = line.trim().split(/\s+/);
4512
+ if (parts.length >= 5 && parts[3] === "LISTENING" && parts[1]?.endsWith(`:${port}`)) {
4513
+ const pid = Number.parseInt(parts[4], 10);
4514
+ if (Number.isInteger(pid)) return pid;
4515
+ }
4516
+ }
4517
+ return null;
4473
4518
  }
4474
4519
 
4475
4520
  // src/cli/restart-watcher.ts
@@ -4534,6 +4579,22 @@ async function loadFullConfig(cwd, mode, envSnapshot, opts = {}) {
4534
4579
  loadEnv(config, cwd, mode, "development");
4535
4580
  return config;
4536
4581
  }
4582
+ async function renderPortInUseError(err) {
4583
+ const holder = await findPortHolder(err.port);
4584
+ console.error();
4585
+ console.error(chalk3.red(` \u2716 \u7AEF\u53E3 ${err.port} \u5DF2\u88AB\u5360\u7528\uFF0C\u65E0\u6CD5\u542F\u52A8 dev server`));
4586
+ if (holder) {
4587
+ const label = holder.name ? `${holder.name} ` : "";
4588
+ const killCmd = process.platform === "win32" ? `taskkill /PID ${holder.pid} /F` : `kill ${holder.pid}`;
4589
+ console.error(chalk3.gray(` \u5360\u7528\u8FDB\u7A0B\uFF1A${label}(PID ${holder.pid})`));
4590
+ console.error(chalk3.gray(` \xB7 \u7ED3\u675F\u5B83\uFF1A${killCmd}`));
4591
+ console.error(chalk3.gray(" \xB7 \u6216\u4FEE\u6539\u914D\u7F6E dev.port \u6362\u4E00\u4E2A\u7AEF\u53E3"));
4592
+ } else {
4593
+ console.error(chalk3.gray(" \xB7 \u4FEE\u6539\u914D\u7F6E dev.port \u6362\u4E00\u4E2A\u7AEF\u53E3"));
4594
+ console.error(chalk3.gray(" \xB7 \u6216\u5148\u91CA\u653E\u5360\u7528\u8BE5\u7AEF\u53E3\u7684\u8FDB\u7A0B"));
4595
+ }
4596
+ console.error();
4597
+ }
4537
4598
  async function startDevServer(cwd, config) {
4538
4599
  const pluginManager = new PluginManager(config, cwd, true);
4539
4600
  if (config.plugins && config.plugins.length > 0) {
@@ -4542,14 +4603,10 @@ async function startDevServer(cwd, config) {
4542
4603
  await pluginManager.runBeforeDevServer();
4543
4604
  let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
4544
4605
  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);
4606
+ const host = config.dev.host || "127.0.0.1";
4607
+ const port = config.dev.port || 3e3;
4608
+ await ensurePortAvailable(port, host);
4548
4609
  const pluginNames = pluginManager.getPluginNames();
4549
- if (port !== preferredPort) {
4550
- console.log(chalk3.yellow(` Port ${preferredPort} is in use, using ${port} instead.
4551
- `));
4552
- }
4553
4610
  const printer = new DevPrinter(host, port, pluginNames);
4554
4611
  printer.printBanner();
4555
4612
  printer.printBuildStart();
@@ -4625,6 +4682,7 @@ async function dev(options = {}) {
4625
4682
  };
4626
4683
  registerShortcuts(() => current.printer, {
4627
4684
  getPort: () => current.port,
4685
+ getHost: () => current.host,
4628
4686
  onQuit: async () => {
4629
4687
  console.log(chalk3.gray("\n Shutting down...\n"));
4630
4688
  await shutdown();
@@ -4666,10 +4724,17 @@ async function dev(options = {}) {
4666
4724
  await current.close();
4667
4725
  current = await startDevServer(cwd, nextConfig);
4668
4726
  } 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);
4727
+ if (error instanceof PortInUseError) {
4728
+ await renderPortInUseError(error);
4729
+ console.error(
4730
+ 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")
4731
+ );
4732
+ } else {
4733
+ console.error(
4734
+ 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:")
4735
+ );
4736
+ console.error(error);
4737
+ }
4673
4738
  }
4674
4739
  } while (pending);
4675
4740
  } finally {
@@ -4678,6 +4743,10 @@ async function dev(options = {}) {
4678
4743
  }
4679
4744
  });
4680
4745
  } catch (error) {
4746
+ if (error instanceof PortInUseError) {
4747
+ await renderPortInUseError(error);
4748
+ process.exit(1);
4749
+ }
4681
4750
  console.error();
4682
4751
  console.error(chalk3.red(" \u2716 Dev server failed to start"));
4683
4752
  console.error(error);