@4399ywkf/core 5.0.2 → 5.0.5

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
@@ -2,13 +2,15 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { Command } from "commander";
5
- import chalk3 from "chalk";
5
+ import chalk4 from "chalk";
6
+ import { createRequire as createRequire4 } from "module";
7
+ import { fileURLToPath as fileURLToPath3 } from "url";
8
+ import { dirname as dirname3, join as join7 } from "path";
6
9
 
7
10
  // src/cli/dev.ts
8
11
  import { rspack as rspack3 } from "@rspack/core";
9
12
  import { RspackDevServer } from "@rspack/dev-server";
10
- import chalk from "chalk";
11
- import ora from "ora";
13
+ import chalk2 from "chalk";
12
14
 
13
15
  // src/config/loader.ts
14
16
  import { existsSync } from "fs";
@@ -147,6 +149,7 @@ function createPathResolver(cwd) {
147
149
  import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
148
150
 
149
151
  // src/rspack/dev.ts
152
+ import ReactRefreshPlugin from "@rspack/plugin-react-refresh";
150
153
  import { merge } from "webpack-merge";
151
154
  import { createRequire as createRequire2 } from "module";
152
155
 
@@ -458,7 +461,7 @@ export default routes;
458
461
  mkdirSync(outputDir, { recursive: true });
459
462
  }
460
463
  writeFileSync(join(outputDir, "routes.tsx"), code, "utf-8");
461
- console.log(`[ywkf] \u7EA6\u5B9A\u5F0F\u8DEF\u7531\u5DF2\u751F\u6210`);
464
+ if (process.env.DEBUG) console.log(`[ywkf] \u7EA6\u5B9A\u5F0F\u8DEF\u7531\u5DF2\u751F\u6210`);
462
465
  }
463
466
  };
464
467
 
@@ -472,17 +475,33 @@ function generateEntry(config, injections = {}) {
472
475
  const topLevel = injections.topLevel || [];
473
476
  const exports = injections.exports || [];
474
477
  const hasPluginExports = exports.length > 0;
475
- const startupCode = hasPluginExports ? `// \u72EC\u7ACB\u8FD0\u884C\u6A21\u5F0F
476
- if (shouldRunIndependently !== false) {
477
- runApp();
478
- }` : `// \u542F\u52A8\u5E94\u7528
479
- runApp();`;
478
+ const hasAsyncTopLevel = topLevel.some((line) => line.includes("await "));
479
+ let startupBody;
480
+ if (hasPluginExports) {
481
+ startupBody = [
482
+ ...topLevel,
483
+ ...exports,
484
+ ``,
485
+ `if (shouldRunIndependently !== false) {`,
486
+ ` runApp();`,
487
+ `}`
488
+ ].join("\n");
489
+ } else if (hasAsyncTopLevel) {
490
+ startupBody = [
491
+ `(async () => {`,
492
+ ...topLevel.map((l) => ` ${l}`),
493
+ ` runApp();`,
494
+ `})();`
495
+ ].join("\n");
496
+ } else {
497
+ startupBody = topLevel.length > 0 ? [...topLevel, `runApp();`].join("\n") : `runApp();`;
498
+ }
480
499
  return `// \u6B64\u6587\u4EF6\u7531 @4399ywkf/core \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539
481
500
  // Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
482
501
 
483
502
  ${imports.join("\n")}
484
503
 
485
- ${topLevel.length > 0 ? topLevel.join("\n") + "\n" : ""}${exports.length > 0 ? exports.join("\n") + "\n\n" : ""}${startupCode}
504
+ ${startupBody}
486
505
  `;
487
506
  }
488
507
 
@@ -531,12 +550,13 @@ async function getUserConfig(): Promise<Partial<AppConfig>> {
531
550
  * \u521B\u5EFA\u5E94\u7528\u914D\u7F6E
532
551
  */
533
552
  export function createAppConfig(userConfig: Partial<AppConfig> = {}): AppConfig {
534
- const router = createRouter(BASENAME);
553
+ const effectiveBasename = userConfig.basename || BASENAME;
554
+ const router = createRouter(effectiveBasename);
535
555
 
536
556
  const defaultConfig: AppConfig = {
537
557
  appName: APP_NAME,
538
558
  router,
539
- basename: BASENAME,
559
+ basename: effectiveBasename,
540
560
  rootId: APP_NAME,
541
561
  strictMode: true,
542
562
  antd: {
@@ -729,7 +749,7 @@ var YwkfGenerator = class {
729
749
  await hooks.afterGenerate(this.context);
730
750
  }
731
751
  }
732
- console.log(`[ywkf] \u5DF2\u751F\u6210 .ywkf \u76EE\u5F55`);
752
+ if (process.env.DEBUG) console.log(`[ywkf] \u5DF2\u751F\u6210 .ywkf \u76EE\u5F55`);
733
753
  }
734
754
  /**
735
755
  * 生成配置快照
@@ -955,13 +975,13 @@ var YwkfGeneratorPlugin = class {
955
975
  isProd: !isDev,
956
976
  config,
957
977
  logger: {
958
- info: (msg) => console.log(`[ywkf] ${msg}`),
978
+ info: (msg) => {
979
+ if (process.env.DEBUG) console.log(`[ywkf] ${msg}`);
980
+ },
959
981
  warn: (msg) => console.warn(`[ywkf] ${msg}`),
960
982
  error: (msg) => console.error(`[ywkf] ${msg}`),
961
983
  debug: (msg) => {
962
- if (process.env.DEBUG) {
963
- console.log(`[ywkf:debug] ${msg}`);
964
- }
984
+ if (process.env.DEBUG) console.log(`[ywkf:debug] ${msg}`);
965
985
  }
966
986
  }
967
987
  };
@@ -970,7 +990,7 @@ var YwkfGeneratorPlugin = class {
970
990
  if (plugin) {
971
991
  const hooks = await plugin.setup(context);
972
992
  this.pluginHooks.push(hooks);
973
- console.log(`[ywkf] \u63D2\u4EF6\u5DF2\u52A0\u8F7D: ${plugin.name}`);
993
+ if (process.env.DEBUG) console.log(`[ywkf] \u63D2\u4EF6\u5DF2\u52A0\u8F7D: ${plugin.name}`);
974
994
  }
975
995
  }
976
996
  this.generator = new YwkfGenerator(
@@ -1024,7 +1044,7 @@ var YwkfGeneratorPlugin = class {
1024
1044
  clearTimeout(debounceTimer);
1025
1045
  }
1026
1046
  debounceTimer = setTimeout(async () => {
1027
- console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
1047
+ if (process.env.DEBUG) console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
1028
1048
  if (this.generator) {
1029
1049
  await this.generator.generate();
1030
1050
  }
@@ -1041,7 +1061,8 @@ var YwkfGeneratorPlugin = class {
1041
1061
  var require2 = createRequire(import.meta.url);
1042
1062
  var __dirname = dirname(fileURLToPath(import.meta.url));
1043
1063
  var coreNodeModules = join5(__dirname, "../../node_modules");
1044
- function createBaseConfig(config, cwd) {
1064
+ function createBaseConfig(config, cwd, options = {}) {
1065
+ const isDev = options.isDev ?? process.env.NODE_ENV !== "production";
1045
1066
  const { resolveApp } = createPathResolver(cwd);
1046
1067
  const {
1047
1068
  appName,
@@ -1072,12 +1093,11 @@ function createBaseConfig(config, cwd) {
1072
1093
  entry: [join5(ywkfOutputDir, "index.tsx")],
1073
1094
  resolve: {
1074
1095
  extensions: [".ts", ".tsx", ".jsx", ".js", ".json", ".mjs"],
1075
- symlinks: false,
1096
+ symlinks: true,
1076
1097
  alias: {
1077
1098
  ...alias,
1078
1099
  "process/browser.js": require2.resolve("process/browser.js"),
1079
1100
  "process/browser": require2.resolve("process/browser.js"),
1080
- // 确保 React 系列包从用户项目的 node_modules 解析
1081
1101
  react: resolveApp("node_modules/react"),
1082
1102
  "react-dom": resolveApp("node_modules/react-dom"),
1083
1103
  "react-router": resolveApp("node_modules/react-router")
@@ -1135,7 +1155,9 @@ function createBaseConfig(config, cwd) {
1135
1155
  },
1136
1156
  transform: {
1137
1157
  react: {
1138
- runtime: "automatic"
1158
+ runtime: "automatic",
1159
+ development: isDev,
1160
+ refresh: isDev
1139
1161
  }
1140
1162
  },
1141
1163
  target: "es2015"
@@ -1249,7 +1271,7 @@ function convertProxyToArray(proxy) {
1249
1271
  });
1250
1272
  }
1251
1273
  function createDevConfig(config, cwd) {
1252
- const baseConfig = createBaseConfig(config, cwd);
1274
+ const baseConfig = createBaseConfig(config, cwd, { isDev: true });
1253
1275
  const { resolveApp } = createPathResolver(cwd);
1254
1276
  const { dev: dev2, style } = config;
1255
1277
  const styleRules = {
@@ -1433,6 +1455,9 @@ function createDevConfig(config, cwd) {
1433
1455
  clean: false
1434
1456
  },
1435
1457
  stats: "errors-only",
1458
+ plugins: [
1459
+ new ReactRefreshPlugin()
1460
+ ],
1436
1461
  devServer: {
1437
1462
  host: dev2.host,
1438
1463
  port: dev2.port,
@@ -1455,7 +1480,7 @@ function createDevConfig(config, cwd) {
1455
1480
  import { rspack as rspack2 } from "@rspack/core";
1456
1481
  import { merge as merge2 } from "webpack-merge";
1457
1482
  function createProdConfig(config, cwd) {
1458
- const baseConfig = createBaseConfig(config, cwd);
1483
+ const baseConfig = createBaseConfig(config, cwd, { isDev: false });
1459
1484
  const { resolveApp } = createPathResolver(cwd);
1460
1485
  const { style, performance, output } = config;
1461
1486
  const styleRules = {
@@ -1757,14 +1782,15 @@ function loadEnv(config, cwd, mode) {
1757
1782
  // src/plugin/manager.ts
1758
1783
  function createLogger(pluginName) {
1759
1784
  const prefix = `[${pluginName}]`;
1785
+ const verbose = !!process.env.DEBUG;
1760
1786
  return {
1761
- info: (msg) => console.log(`${prefix} ${msg}`),
1787
+ info: (msg) => {
1788
+ if (verbose) console.log(`${prefix} ${msg}`);
1789
+ },
1762
1790
  warn: (msg) => console.warn(`${prefix} ${msg}`),
1763
1791
  error: (msg) => console.error(`${prefix} ${msg}`),
1764
1792
  debug: (msg) => {
1765
- if (process.env.DEBUG) {
1766
- console.debug(`${prefix} ${msg}`);
1767
- }
1793
+ if (verbose) console.debug(`${prefix} ${msg}`);
1768
1794
  }
1769
1795
  };
1770
1796
  }
@@ -1998,42 +2024,306 @@ var PluginManager = class {
1998
2024
  }
1999
2025
  };
2000
2026
 
2027
+ // src/cli/port.ts
2028
+ import net from "net";
2029
+ function isPortAvailable(port, host) {
2030
+ return new Promise((resolve3) => {
2031
+ const server = net.createServer();
2032
+ server.once("error", (err) => {
2033
+ if (err.code === "EADDRINUSE") {
2034
+ resolve3(false);
2035
+ } else {
2036
+ resolve3(false);
2037
+ }
2038
+ });
2039
+ server.once("listening", () => {
2040
+ server.close(() => resolve3(true));
2041
+ });
2042
+ server.listen(port, host);
2043
+ });
2044
+ }
2045
+ async function getAvailablePort(preferredPort, host) {
2046
+ const MAX_ATTEMPTS = 20;
2047
+ for (let i = 0; i < MAX_ATTEMPTS; i++) {
2048
+ const port = preferredPort + i;
2049
+ const available = await isPortAvailable(port, host);
2050
+ if (available) return port;
2051
+ }
2052
+ throw new Error(
2053
+ `No available port found in range ${preferredPort}-${preferredPort + MAX_ATTEMPTS - 1}`
2054
+ );
2055
+ }
2056
+
2057
+ // src/cli/printer.ts
2058
+ import chalk from "chalk";
2059
+ import os from "os";
2060
+ import { createRequire as createRequire3 } from "module";
2061
+ import { fileURLToPath as fileURLToPath2 } from "url";
2062
+ import { dirname as dirname2, join as join6 } from "path";
2063
+ var __filename = fileURLToPath2(import.meta.url);
2064
+ var __dirname2 = dirname2(__filename);
2065
+ var require4 = createRequire3(import.meta.url);
2066
+ var _version = null;
2067
+ function getFrameworkVersion() {
2068
+ if (_version) return _version;
2069
+ try {
2070
+ const pkgPath = join6(__dirname2, "../../package.json");
2071
+ const pkg = require4(pkgPath);
2072
+ _version = pkg.version || "0.0.0";
2073
+ } catch {
2074
+ _version = "0.0.0";
2075
+ }
2076
+ return _version;
2077
+ }
2078
+ function getNetworkAddress(port) {
2079
+ const interfaces = os.networkInterfaces();
2080
+ for (const entries of Object.values(interfaces)) {
2081
+ if (!entries) continue;
2082
+ for (const entry of entries) {
2083
+ if (entry.family === "IPv4" && !entry.internal) {
2084
+ return `http://${entry.address}:${port}/`;
2085
+ }
2086
+ }
2087
+ }
2088
+ return null;
2089
+ }
2090
+ var BAR_WIDTH = 30;
2091
+ function renderBar(percent) {
2092
+ const filled = Math.round(BAR_WIDTH * percent);
2093
+ const empty = BAR_WIDTH - filled;
2094
+ const bar = chalk.green("\u2501".repeat(filled)) + chalk.gray("\u2501".repeat(empty));
2095
+ return bar;
2096
+ }
2097
+ var DevPrinter = class {
2098
+ constructor(host, port, pluginNames) {
2099
+ this.host = host;
2100
+ this.port = port;
2101
+ this.pluginNames = pluginNames;
2102
+ }
2103
+ startTime = 0;
2104
+ lastProgressLine = "";
2105
+ firstCompileDone = false;
2106
+ /**
2107
+ * 打印框架 banner
2108
+ */
2109
+ printBanner() {
2110
+ const version2 = getFrameworkVersion();
2111
+ console.log();
2112
+ console.log(
2113
+ ` ${chalk.bold.cyan("@4399ywkf/core")} ${chalk.green(`Framework v${version2}`)}`
2114
+ );
2115
+ console.log();
2116
+ }
2117
+ /**
2118
+ * 打印 "start build started..."
2119
+ */
2120
+ printBuildStart() {
2121
+ this.startTime = Date.now();
2122
+ this.compileDone = false;
2123
+ const label = chalk.gray("start");
2124
+ console.log(` ${label} build started...`);
2125
+ }
2126
+ /**
2127
+ * 更新编译进度条(原地覆写同一行)
2128
+ */
2129
+ updateProgress(percent, message) {
2130
+ const pct = Math.min(Math.round(percent * 100), 100);
2131
+ const bar = renderBar(percent);
2132
+ const status = message || "compiling";
2133
+ const line = ` ${chalk.yellow("\u25CF")} client ${bar} ${chalk.bold(`(${pct}%)`)} ${chalk.gray(status)}`;
2134
+ if (process.stdout.isTTY) {
2135
+ if (this.lastProgressLine) {
2136
+ process.stdout.write("\x1B[1A\x1B[2K");
2137
+ }
2138
+ process.stdout.write(line + "\n");
2139
+ } else if (!this.firstCompileDone && pct === 100) {
2140
+ console.log(line);
2141
+ }
2142
+ this.lastProgressLine = line;
2143
+ }
2144
+ /**
2145
+ * 编译完成
2146
+ */
2147
+ printBuildDone(hasErrors = false) {
2148
+ if (this.firstCompileDone) {
2149
+ if (!hasErrors) {
2150
+ const elapsed2 = ((Date.now() - this.startTime) / 1e3).toFixed(2);
2151
+ console.log(
2152
+ ` ${chalk.green("hmr")} update in ${chalk.bold(`${elapsed2} s`)}`
2153
+ );
2154
+ }
2155
+ return;
2156
+ }
2157
+ this.firstCompileDone = true;
2158
+ this.lastProgressLine = "";
2159
+ if (hasErrors) return;
2160
+ const elapsed = ((Date.now() - this.startTime) / 1e3).toFixed(2);
2161
+ const label = chalk.green("ready");
2162
+ console.log(` ${label} built in ${chalk.bold(`${elapsed} s`)}`);
2163
+ console.log();
2164
+ this.printServerInfo();
2165
+ }
2166
+ /**
2167
+ * 标记新一轮编译开始(HMR)
2168
+ */
2169
+ markRebuildStart() {
2170
+ this.startTime = Date.now();
2171
+ this.lastProgressLine = "";
2172
+ }
2173
+ /**
2174
+ * 打印服务器信息面板
2175
+ */
2176
+ printServerInfo() {
2177
+ const localUrl = `http://localhost:${this.port}/`;
2178
+ const networkUrl = getNetworkAddress(this.port);
2179
+ console.log(` ${chalk.bold(">")} Local: ${chalk.cyan(localUrl)}`);
2180
+ if (networkUrl) {
2181
+ console.log(` ${chalk.bold(">")} Network: ${chalk.cyan(networkUrl)}`);
2182
+ }
2183
+ console.log();
2184
+ if (this.pluginNames.length > 0) {
2185
+ console.log(` ${chalk.bold(">")} Plugins:`);
2186
+ for (const name of this.pluginNames) {
2187
+ const shortName = name.replace("@4399ywkf/plugin-", "").replace("@4399ywkf/", "");
2188
+ console.log(` ${chalk.green("\u2713")} ${shortName}`);
2189
+ }
2190
+ console.log();
2191
+ }
2192
+ console.log(
2193
+ ` ${chalk.bold(">")} press ${chalk.bold("h + enter")} to show shortcuts`
2194
+ );
2195
+ console.log();
2196
+ }
2197
+ /**
2198
+ * 打印快捷键帮助
2199
+ */
2200
+ printShortcuts() {
2201
+ console.log();
2202
+ console.log(` ${chalk.bold("Shortcuts:")}`);
2203
+ console.log(` ${chalk.bold("o + enter")} open in browser`);
2204
+ console.log(` ${chalk.bold("c + enter")} clear console`);
2205
+ console.log(` ${chalk.bold("q + enter")} quit`);
2206
+ console.log();
2207
+ }
2208
+ };
2209
+ function createProgressHandler(printer) {
2210
+ return (percent, message, ..._details) => {
2211
+ printer.updateProgress(percent, message);
2212
+ };
2213
+ }
2214
+ function registerShortcuts(printer, opts) {
2215
+ if (!process.stdin.isTTY) return;
2216
+ process.stdin.setEncoding("utf-8");
2217
+ process.stdin.setRawMode?.(false);
2218
+ let buffer = "";
2219
+ const handler = (data) => {
2220
+ buffer += data;
2221
+ if (!buffer.includes("\n")) return;
2222
+ const cmd = buffer.trim().toLowerCase();
2223
+ buffer = "";
2224
+ switch (cmd) {
2225
+ case "h":
2226
+ printer.printShortcuts();
2227
+ break;
2228
+ case "o": {
2229
+ const url = `http://localhost:${opts.port}/`;
2230
+ import("child_process").then((cp) => {
2231
+ const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
2232
+ cp.exec(`${command} ${url}`);
2233
+ });
2234
+ console.log(` ${chalk.green("\u279C")} Opening ${chalk.cyan(url)}...`);
2235
+ break;
2236
+ }
2237
+ case "c":
2238
+ console.clear();
2239
+ break;
2240
+ case "q":
2241
+ opts.onQuit();
2242
+ break;
2243
+ }
2244
+ };
2245
+ process.stdin.on("data", handler);
2246
+ process.stdin.resume();
2247
+ }
2248
+
2001
2249
  // src/cli/dev.ts
2002
2250
  async function dev(options = {}) {
2003
2251
  const cwd = options.cwd || process.cwd();
2004
- const spinner = ora("\u6B63\u5728\u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668...").start();
2005
2252
  try {
2006
2253
  preloadEnv(cwd, "development");
2007
- const { config, configPath } = await resolveConfig(cwd);
2008
- if (configPath) {
2009
- spinner.text = `\u5DF2\u52A0\u8F7D\u914D\u7F6E: ${configPath}`;
2010
- }
2254
+ const { config } = await resolveConfig(cwd);
2011
2255
  loadEnv(config, cwd, "development");
2012
2256
  const pluginManager = new PluginManager(config, cwd, true);
2013
2257
  if (config.plugins && config.plugins.length > 0) {
2014
- spinner.text = "\u52A0\u8F7D\u63D2\u4EF6...";
2015
2258
  await pluginManager.loadPlugins(config.plugins);
2016
2259
  }
2017
2260
  await pluginManager.runBeforeDevServer();
2018
2261
  let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
2019
2262
  rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
2263
+ const host = config.dev.host || "localhost";
2264
+ const preferredPort = config.dev.port || 3e3;
2265
+ const port = await getAvailablePort(preferredPort, host);
2266
+ const pluginNames = pluginManager.getPluginNames();
2267
+ if (port !== preferredPort) {
2268
+ console.log(
2269
+ chalk2.yellow(` Port ${preferredPort} is in use, using ${port} instead.
2270
+ `)
2271
+ );
2272
+ }
2273
+ const printer = new DevPrinter(host, port, pluginNames);
2274
+ printer.printBanner();
2275
+ printer.printBuildStart();
2276
+ printer.updateProgress(0, "preparing");
2277
+ rspackConfig.plugins = rspackConfig.plugins || [];
2278
+ rspackConfig.plugins.push(
2279
+ new rspack3.ProgressPlugin(createProgressHandler(printer))
2280
+ );
2281
+ rspackConfig.stats = "none";
2282
+ rspackConfig.infrastructureLogging = { level: "none" };
2283
+ if (rspackConfig.devServer) {
2284
+ const ds = rspackConfig.devServer;
2285
+ const existingClient = ds.client ?? {};
2286
+ ds.client = {
2287
+ ...existingClient,
2288
+ logging: "warn",
2289
+ overlay: false,
2290
+ progress: false
2291
+ };
2292
+ }
2020
2293
  const compiler = rspack3(rspackConfig);
2021
- const devServerOptions = rspackConfig.devServer || {};
2294
+ compiler.hooks.done.tap("ywkf-dev-printer", (stats) => {
2295
+ const hasErrors = stats.hasErrors();
2296
+ if (hasErrors) {
2297
+ const info = stats.toJson({ errors: true });
2298
+ console.log();
2299
+ console.log(chalk2.red(" Compile error:"));
2300
+ for (const err of info.errors || []) {
2301
+ console.log(chalk2.red(` ${err.message}`));
2302
+ }
2303
+ console.log();
2304
+ }
2305
+ printer.printBuildDone(hasErrors);
2306
+ });
2307
+ compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
2308
+ printer.markRebuildStart();
2309
+ printer.updateProgress(0, "rebuilding");
2310
+ });
2311
+ const devServerOptions = {
2312
+ ...rspackConfig.devServer || {},
2313
+ host,
2314
+ port
2315
+ };
2022
2316
  const server = new RspackDevServer(devServerOptions, compiler);
2023
- const host = config.dev.host || "localhost";
2024
- const port = config.dev.port || 3e3;
2025
2317
  await server.start();
2026
2318
  await pluginManager.runAfterDevServer({ host, port });
2027
- spinner.succeed(chalk.green("\u5F00\u53D1\u670D\u52A1\u5668\u542F\u52A8\u6210\u529F!"));
2028
- console.log();
2029
- console.log(
2030
- ` ${chalk.bold("Local:")} ${chalk.cyan(`http://${host}:${port}`)}`
2031
- );
2032
- const pluginNames = pluginManager.getPluginNames();
2033
- if (pluginNames.length > 0) {
2034
- console.log(` ${chalk.bold("\u63D2\u4EF6:")} ${chalk.dim(pluginNames.join(", "))}`);
2035
- }
2036
- console.log();
2319
+ registerShortcuts(printer, {
2320
+ port,
2321
+ onQuit: async () => {
2322
+ console.log(chalk2.gray("\n Shutting down...\n"));
2323
+ await server.stop();
2324
+ process.exit(0);
2325
+ }
2326
+ });
2037
2327
  const signals = ["SIGINT", "SIGTERM"];
2038
2328
  for (const signal of signals) {
2039
2329
  process.on(signal, async () => {
@@ -2042,7 +2332,8 @@ async function dev(options = {}) {
2042
2332
  });
2043
2333
  }
2044
2334
  } catch (error) {
2045
- spinner.fail(chalk.red("\u5F00\u53D1\u670D\u52A1\u5668\u542F\u52A8\u5931\u8D25"));
2335
+ console.error();
2336
+ console.error(chalk2.red(" \u2716 Dev server failed to start"));
2046
2337
  console.error(error);
2047
2338
  process.exit(1);
2048
2339
  }
@@ -2050,8 +2341,7 @@ async function dev(options = {}) {
2050
2341
 
2051
2342
  // src/cli/build.ts
2052
2343
  import { rspack as rspack4 } from "@rspack/core";
2053
- import chalk2 from "chalk";
2054
- import ora2 from "ora";
2344
+ import chalk3 from "chalk";
2055
2345
  function formatSize(bytes) {
2056
2346
  if (bytes < 1024) return `${bytes} B`;
2057
2347
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
@@ -2064,57 +2354,57 @@ function printBuildResult(stats) {
2064
2354
  warnings: true
2065
2355
  });
2066
2356
  if (info.errors && info.errors.length > 0) {
2067
- console.log(chalk2.red("\n\u6784\u5EFA\u9519\u8BEF:"));
2357
+ console.log(chalk3.red("\n Compile errors:"));
2068
2358
  for (const error of info.errors) {
2069
- console.log(chalk2.red(` ${error.message}`));
2359
+ console.log(chalk3.red(` ${error.message}`));
2070
2360
  }
2071
2361
  return;
2072
2362
  }
2073
2363
  if (info.warnings && info.warnings.length > 0) {
2074
- console.log(chalk2.yellow("\n\u6784\u5EFA\u8B66\u544A:"));
2364
+ console.log(chalk3.yellow("\n Warnings:"));
2075
2365
  for (const warning of info.warnings) {
2076
- console.log(chalk2.yellow(` ${warning.message}`));
2366
+ console.log(chalk3.yellow(` ${warning.message}`));
2077
2367
  }
2078
2368
  }
2079
- console.log(chalk2.bold("\n\u6784\u5EFA\u4EA7\u7269:"));
2369
+ console.log(chalk3.bold("\n Build output:"));
2080
2370
  console.log();
2081
2371
  const assets = info.assets || [];
2082
2372
  const sortedAssets = assets.filter((asset) => !asset.name.endsWith(".map")).sort((a, b) => b.size - a.size);
2083
2373
  for (const asset of sortedAssets.slice(0, 15)) {
2084
- const sizeColor = asset.size > 500 * 1024 ? chalk2.yellow : chalk2.green;
2374
+ const sizeColor = asset.size > 500 * 1024 ? chalk3.yellow : chalk3.green;
2085
2375
  console.log(
2086
- ` ${chalk2.dim(asset.name.padEnd(50))} ${sizeColor(formatSize(asset.size))}`
2376
+ ` ${chalk3.dim(asset.name.padEnd(50))} ${sizeColor(formatSize(asset.size))}`
2087
2377
  );
2088
2378
  }
2089
2379
  if (sortedAssets.length > 15) {
2090
- console.log(chalk2.dim(` ... \u8FD8\u6709 ${sortedAssets.length - 15} \u4E2A\u6587\u4EF6`));
2380
+ console.log(chalk3.dim(` ... and ${sortedAssets.length - 15} more files`));
2091
2381
  }
2092
2382
  console.log();
2093
- console.log(
2094
- chalk2.green(
2095
- `\u2713 \u6784\u5EFA\u5B8C\u6210\uFF0C\u8017\u65F6 ${((info.time || 0) / 1e3).toFixed(2)}s`
2096
- )
2097
- );
2098
2383
  }
2099
2384
  async function build(options = {}) {
2100
2385
  const cwd = options.cwd || process.cwd();
2101
- const spinner = ora2("\u6B63\u5728\u6784\u5EFA\u751F\u4EA7\u73AF\u5883...").start();
2102
2386
  try {
2103
2387
  preloadEnv(cwd, "production");
2104
- const { config, configPath } = await resolveConfig(cwd);
2105
- if (configPath) {
2106
- spinner.text = `\u5DF2\u52A0\u8F7D\u914D\u7F6E: ${configPath}`;
2107
- }
2388
+ const { config } = await resolveConfig(cwd);
2108
2389
  loadEnv(config, cwd, "production");
2109
2390
  const pluginManager = new PluginManager(config, cwd, false);
2110
2391
  if (config.plugins && config.plugins.length > 0) {
2111
- spinner.text = "\u52A0\u8F7D\u63D2\u4EF6...";
2112
2392
  await pluginManager.loadPlugins(config.plugins);
2113
2393
  }
2114
2394
  await pluginManager.runBeforeBuild();
2115
2395
  let rspackConfig = createRspackConfig(config, cwd, { isDev: false });
2116
2396
  rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
2117
- spinner.text = "\u6B63\u5728\u7F16\u8BD1...";
2397
+ const pluginNames = pluginManager.getPluginNames();
2398
+ const printer = new DevPrinter("localhost", 0, pluginNames);
2399
+ printer.printBanner();
2400
+ printer.printBuildStart();
2401
+ printer.updateProgress(0, "preparing");
2402
+ rspackConfig.plugins = rspackConfig.plugins || [];
2403
+ rspackConfig.plugins.push(
2404
+ new rspack4.ProgressPlugin(createProgressHandler(printer))
2405
+ );
2406
+ rspackConfig.stats = "none";
2407
+ rspackConfig.infrastructureLogging = { level: "none" };
2118
2408
  const compiler = rspack4(rspackConfig);
2119
2409
  const stats = await new Promise((resolve3, reject) => {
2120
2410
  compiler.run((err, stats2) => {
@@ -2123,7 +2413,7 @@ async function build(options = {}) {
2123
2413
  return;
2124
2414
  }
2125
2415
  if (!stats2) {
2126
- reject(new Error("\u6784\u5EFA\u5931\u8D25: \u65E0\u6CD5\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F"));
2416
+ reject(new Error("Build failed: no stats available"));
2127
2417
  return;
2128
2418
  }
2129
2419
  resolve3(stats2);
@@ -2141,23 +2431,32 @@ async function build(options = {}) {
2141
2431
  success: !hasErrors,
2142
2432
  errors: statsInfo.errors?.map((e) => e.message)
2143
2433
  });
2434
+ printer.printBuildDone(hasErrors);
2144
2435
  if (hasErrors) {
2145
- spinner.fail(chalk2.red("\u6784\u5EFA\u5931\u8D25"));
2146
2436
  printBuildResult(stats);
2147
2437
  process.exit(1);
2148
2438
  }
2149
- spinner.succeed(chalk2.green("\u6784\u5EFA\u5B8C\u6210!"));
2150
2439
  printBuildResult(stats);
2151
2440
  } catch (error) {
2152
- spinner.fail(chalk2.red("\u6784\u5EFA\u5931\u8D25"));
2441
+ console.error();
2442
+ console.error(chalk3.red(" \u2716 Build failed"));
2153
2443
  console.error(error);
2154
2444
  process.exit(1);
2155
2445
  }
2156
2446
  }
2157
2447
 
2158
2448
  // src/cli/index.ts
2449
+ var __filename2 = fileURLToPath3(import.meta.url);
2450
+ var __dirname3 = dirname3(__filename2);
2451
+ var require5 = createRequire4(import.meta.url);
2452
+ var version = "0.0.0";
2453
+ try {
2454
+ const pkg = require5(join7(__dirname3, "../../package.json"));
2455
+ version = pkg.version;
2456
+ } catch {
2457
+ }
2159
2458
  var program = new Command();
2160
- program.name("ywkf").description("4399\u8FD0\u7EF4\u5F00\u53D1\u524D\u7AEF\u6846\u67B6 CLI").version("1.0.0");
2459
+ program.name("ywkf").description("4399\u8FD0\u7EF4\u5F00\u53D1\u524D\u7AEF\u6846\u67B6 CLI").version(version);
2161
2460
  program.command("dev").description("\u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668").option("-p, --port <port>", "\u6307\u5B9A\u7AEF\u53E3\u53F7").option("-h, --host <host>", "\u6307\u5B9A\u4E3B\u673A").action(async (options) => {
2162
2461
  if (options.port) {
2163
2462
  process.env.APP_PORT = options.port;
@@ -2174,7 +2473,7 @@ program.command("build").description("\u6784\u5EFA\u751F\u4EA7\u73AF\u5883").opt
2174
2473
  await build({ cwd: process.cwd() });
2175
2474
  });
2176
2475
  program.command("start").description("\u542F\u52A8\u751F\u4EA7\u670D\u52A1\u5668\uFF08\u9700\u8981\u5148\u6267\u884C build\uFF09").action(() => {
2177
- console.log(chalk3.yellow("\u26A0\uFE0F start \u547D\u4EE4\u6682\u672A\u5B9E\u73B0\uFF0C\u8BF7\u4F7F\u7528 nginx \u6216\u5176\u4ED6\u9759\u6001\u670D\u52A1\u5668"));
2476
+ console.log(chalk4.yellow("\u26A0\uFE0F start \u547D\u4EE4\u6682\u672A\u5B9E\u73B0\uFF0C\u8BF7\u4F7F\u7528 nginx \u6216\u5176\u4ED6\u9759\u6001\u670D\u52A1\u5668"));
2178
2477
  });
2179
2478
  program.parse();
2180
2479
  //# sourceMappingURL=index.js.map