@rsbuild/core 1.0.9 → 1.0.10

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.cjs CHANGED
@@ -4194,6 +4194,7 @@ var init_config = __esm({
4194
4194
  getDefaultDevConfig = () => ({
4195
4195
  hmr: true,
4196
4196
  liveReload: true,
4197
+ // Temporary placeholder, default: `${server.base}`
4197
4198
  assetPrefix: DEFAULT_ASSET_PREFIX,
4198
4199
  writeToDisk: false,
4199
4200
  client: {
@@ -4208,6 +4209,7 @@ var init_config = __esm({
4208
4209
  port: DEFAULT_PORT,
4209
4210
  host: DEFAULT_DEV_HOST,
4210
4211
  open: false,
4212
+ base: "/",
4211
4213
  htmlFallback: "index",
4212
4214
  compress: true,
4213
4215
  printUrls: true,
@@ -4271,6 +4273,7 @@ var init_config = __esm({
4271
4273
  image: IMAGE_DIST_DIR,
4272
4274
  media: MEDIA_DIST_DIR
4273
4275
  },
4276
+ // Temporary placeholder, default: `${server.base}`
4274
4277
  assetPrefix: DEFAULT_ASSET_PREFIX,
4275
4278
  filename: {},
4276
4279
  charset: "utf8",
@@ -4315,6 +4318,16 @@ var init_config = __esm({
4315
4318
  const merged = mergeRsbuildConfig(createDefaultConfig(), config);
4316
4319
  merged.root ||= rootPath;
4317
4320
  merged.source ||= {};
4321
+ if (merged.server?.base) {
4322
+ if (config.dev?.assetPrefix === void 0) {
4323
+ merged.dev ||= {};
4324
+ merged.dev.assetPrefix = merged.server.base;
4325
+ }
4326
+ if (config.output?.assetPrefix === void 0) {
4327
+ merged.output ||= {};
4328
+ merged.output.assetPrefix = merged.server.base;
4329
+ }
4330
+ }
4318
4331
  if (!merged.source.tsconfigPath) {
4319
4332
  const tsconfigPath = (0, import_node_path6.join)(rootPath, TS_CONFIG_FILE);
4320
4333
  if (await isFileExists(tsconfigPath)) {
@@ -5982,7 +5995,7 @@ async function createContext(options, userConfig, bundlerType) {
5982
5995
  const rsbuildConfig = await withDefaultConfig(rootPath, userConfig);
5983
5996
  const cachePath = (0, import_node_path10.join)(rootPath, "node_modules", ".cache");
5984
5997
  return {
5985
- version: "1.0.9",
5998
+ version: "1.0.10",
5986
5999
  rootPath,
5987
6000
  distPath: "",
5988
6001
  cachePath,
@@ -7279,128 +7292,472 @@ var init_environment = __esm({
7279
7292
  }
7280
7293
  });
7281
7294
 
7282
- // src/server/middlewares.ts
7283
- var import_node_path16, import_picocolors9, faviconFallbackMiddleware, getStatusCodeColor, getRequestLoggerMiddleware, notFoundMiddleware, isFileExists2, maybeHTMLRequest, postfixRE, getUrlPathname, getHtmlCompletionMiddleware, getHtmlFallbackMiddleware;
7284
- var init_middlewares = __esm({
7285
- "src/server/middlewares.ts"() {
7295
+ // src/server/helper.ts
7296
+ function getURLMessages(urls, routes) {
7297
+ if (routes.length === 1) {
7298
+ return urls.map(
7299
+ ({ label, url: url2 }) => ` ${`➜ ${label.padEnd(10)}`}${import_picocolors9.default.cyan(
7300
+ normalizeUrl(`${url2}${routes[0].pathname}`)
7301
+ )}
7302
+ `
7303
+ ).join("");
7304
+ }
7305
+ let message = "";
7306
+ const maxNameLength = Math.max(...routes.map((r) => r.entryName.length));
7307
+ urls.forEach(({ label, url: url2 }, index) => {
7308
+ if (index > 0) {
7309
+ message += "\n";
7310
+ }
7311
+ message += ` ${`➜ ${label}`}
7312
+ `;
7313
+ for (const r of routes) {
7314
+ message += ` ${import_picocolors9.default.dim("-")} ${import_picocolors9.default.dim(
7315
+ r.entryName.padEnd(maxNameLength + 4)
7316
+ )}${import_picocolors9.default.cyan(normalizeUrl(`${url2}${r.pathname}`))}
7317
+ `;
7318
+ }
7319
+ });
7320
+ return message;
7321
+ }
7322
+ function printServerURLs({
7323
+ urls: originalUrls,
7324
+ port,
7325
+ routes,
7326
+ protocol,
7327
+ printUrls
7328
+ }) {
7329
+ if (printUrls === false) {
7330
+ return null;
7331
+ }
7332
+ let urls = originalUrls;
7333
+ if (isFunction(printUrls)) {
7334
+ const newUrls = printUrls({
7335
+ urls: urls.map((item) => item.url),
7336
+ port,
7337
+ routes,
7338
+ protocol
7339
+ });
7340
+ if (!newUrls) {
7341
+ return null;
7342
+ }
7343
+ if (!Array.isArray(newUrls)) {
7344
+ throw new Error(
7345
+ `"server.printUrls" must return an array, but got ${typeof newUrls}.`
7346
+ );
7347
+ }
7348
+ urls = newUrls.map((url2) => ({
7349
+ url: url2,
7350
+ label: getUrlLabel(url2)
7351
+ }));
7352
+ }
7353
+ if (urls.length === 0 || routes.length === 0) {
7354
+ return null;
7355
+ }
7356
+ const message = getURLMessages(urls, routes);
7357
+ import_rslog.logger.log(message);
7358
+ return message;
7359
+ }
7360
+ function getServerTerminator(server) {
7361
+ let listened = false;
7362
+ const pendingSockets = /* @__PURE__ */ new Set();
7363
+ const onConnection = (socket) => {
7364
+ pendingSockets.add(socket);
7365
+ socket.on("close", () => {
7366
+ pendingSockets.delete(socket);
7367
+ });
7368
+ };
7369
+ server.on("connection", onConnection);
7370
+ server.on("secureConnection", onConnection);
7371
+ server.once("listening", () => {
7372
+ listened = true;
7373
+ });
7374
+ return () => new Promise((resolve2, reject) => {
7375
+ for (const socket of pendingSockets) {
7376
+ socket.destroy();
7377
+ }
7378
+ if (listened) {
7379
+ server.close((err) => err ? reject(err) : resolve2());
7380
+ } else {
7381
+ resolve2();
7382
+ }
7383
+ });
7384
+ }
7385
+ var import_node_net, import_node_os, import_node_path16, import_picocolors9, normalizeUrl, formatPrefix, joinUrlSegments, stripBase, getRoutes, formatRoutes, getPort, getServerConfig, getIpv4Interfaces, isLoopbackHost, getHostInUrl, concatUrl, LOCAL_LABEL, NETWORK_LABEL, getUrlLabel, getAddressUrls, COMPILATION_ID_REGEX, getCompilationId;
7386
+ var init_helper = __esm({
7387
+ "src/server/helper.ts"() {
7286
7388
  "use strict";
7287
- import_node_path16 = __toESM(require("path"));
7389
+ import_node_net = __toESM(require("net"));
7390
+ import_node_os = __toESM(require("os"));
7391
+ import_node_path16 = require("path");
7288
7392
  import_picocolors9 = __toESM(require("../compiled/picocolors/index.js"));
7393
+ init_constants();
7394
+ init_helpers();
7289
7395
  init_logger();
7290
- faviconFallbackMiddleware = (req, res, next) => {
7291
- if (req.url === "/favicon.ico") {
7292
- res.statusCode = 204;
7293
- res.end();
7294
- } else {
7295
- next();
7296
- }
7297
- };
7298
- getStatusCodeColor = (status) => {
7299
- if (status >= 500) {
7300
- return import_picocolors9.default.red;
7396
+ normalizeUrl = (url2) => url2.replace(/([^:]\/)\/+/g, "$1");
7397
+ formatPrefix = (input) => {
7398
+ let prefix = input;
7399
+ if (prefix?.startsWith("./")) {
7400
+ prefix = prefix.replace("./", "");
7301
7401
  }
7302
- if (status >= 400) {
7303
- return import_picocolors9.default.yellow;
7402
+ if (!prefix) {
7403
+ return "/";
7304
7404
  }
7305
- if (status >= 300) {
7306
- return import_picocolors9.default.cyan;
7405
+ const hasLeadingSlash = prefix.startsWith("/");
7406
+ const hasTailSlash = prefix.endsWith("/");
7407
+ return `${hasLeadingSlash ? "" : "/"}${prefix}${hasTailSlash ? "" : "/"}`;
7408
+ };
7409
+ joinUrlSegments = (s1, s2) => {
7410
+ if (!s1 || !s2) {
7411
+ return s1 || s2 || "";
7307
7412
  }
7308
- if (status >= 200) {
7309
- return import_picocolors9.default.green;
7413
+ return addTrailingSlash(s1) + removeLeadingSlash(s2);
7414
+ };
7415
+ stripBase = (path21, base) => {
7416
+ if (path21 === base) {
7417
+ return "/";
7310
7418
  }
7311
- return (res) => res;
7419
+ const trailingSlashBase = addTrailingSlash(base);
7420
+ return path21.startsWith(trailingSlashBase) ? path21.slice(trailingSlashBase.length - 1) : path21;
7312
7421
  };
7313
- getRequestLoggerMiddleware = async () => {
7314
- const { default: onFinished } = await import("../compiled/on-finished/index.js");
7315
- return (req, res, next) => {
7316
- const _startAt = process.hrtime();
7317
- const logRequest = () => {
7318
- const method = req.method;
7319
- const url2 = req.originalUrl || req.url;
7320
- const status = Number(res.statusCode);
7321
- const statusColor = getStatusCodeColor(status);
7322
- const endAt = process.hrtime();
7323
- const totalTime = (endAt[0] - _startAt[0]) * 1e3 + (endAt[1] - _startAt[1]) * 1e-6;
7324
- import_rslog.logger.debug(
7325
- `${statusColor(status)} ${method} ${import_picocolors9.default.gray(url2)} ${import_picocolors9.default.gray(
7326
- `${totalTime.toFixed(3)} ms`
7327
- )}`
7422
+ getRoutes = (context) => {
7423
+ return Object.values(context.environments).reduce(
7424
+ (prev, environmentContext) => {
7425
+ const { distPath, config } = environmentContext;
7426
+ const distPrefix = import_node_path16.posix.relative(context.distPath, distPath);
7427
+ const routes = formatRoutes(
7428
+ environmentContext.htmlPaths,
7429
+ context.normalizedConfig.server.base,
7430
+ import_node_path16.posix.join(distPrefix, config.output.distPath.html),
7431
+ config.html.outputStructure
7328
7432
  );
7329
- };
7330
- onFinished(res, logRequest);
7331
- next();
7332
- };
7433
+ return prev.concat(...routes);
7434
+ },
7435
+ []
7436
+ );
7333
7437
  };
7334
- notFoundMiddleware = (_req, res, _next) => {
7335
- res.statusCode = 404;
7336
- res.end();
7438
+ formatRoutes = (entry, base, distPathPrefix, outputStructure) => {
7439
+ const prefix = joinUrlSegments(base, formatPrefix(distPathPrefix));
7440
+ return Object.keys(entry).map((entryName) => {
7441
+ const isIndex = entryName === "index" && outputStructure !== "nested";
7442
+ const displayName = isIndex ? "" : entryName;
7443
+ return {
7444
+ entryName,
7445
+ pathname: prefix + displayName
7446
+ };
7447
+ }).sort((a) => a.entryName === "index" ? -1 : 1);
7337
7448
  };
7338
- isFileExists2 = async (filePath, outputFileSystem) => new Promise((resolve2) => {
7339
- outputFileSystem.stat(filePath, (_error, stats) => {
7340
- resolve2(stats?.isFile());
7341
- });
7342
- });
7343
- maybeHTMLRequest = (req) => {
7344
- if (
7345
- // require headers and url
7346
- !req.url || !req.headers || // only accept GET or HEAD
7347
- req.method !== "GET" && req.method !== "HEAD"
7348
- ) {
7349
- return false;
7449
+ getPort = async ({
7450
+ host,
7451
+ port,
7452
+ strictPort,
7453
+ tryLimits = 20
7454
+ }) => {
7455
+ if (typeof port === "string") {
7456
+ port = Number.parseInt(port, 10);
7350
7457
  }
7351
- const { accept } = req.headers;
7352
- return typeof accept === "string" && (accept.includes("text/html") || accept.includes("*/*"));
7353
- };
7354
- postfixRE = /[?#].*$/;
7355
- getUrlPathname = (url2) => {
7356
- return url2.replace(postfixRE, "");
7357
- };
7358
- getHtmlCompletionMiddleware = ({ distPath, callback, outputFileSystem }) => {
7359
- return async (req, res, next) => {
7360
- if (!maybeHTMLRequest(req)) {
7361
- return next();
7362
- }
7363
- const url2 = req.url;
7364
- const pathname = getUrlPathname(url2);
7365
- const rewrite = (newUrl) => {
7366
- req.url = newUrl;
7367
- return callback(req, res, (...args) => {
7368
- next(...args);
7458
+ if (strictPort) {
7459
+ tryLimits = 1;
7460
+ }
7461
+ const original = port;
7462
+ let found = false;
7463
+ let attempts = 0;
7464
+ while (!found && attempts <= tryLimits) {
7465
+ try {
7466
+ await new Promise((resolve2, reject) => {
7467
+ const server = import_node_net.default.createServer();
7468
+ server.unref();
7469
+ server.on("error", reject);
7470
+ server.listen({ port, host }, () => {
7471
+ found = true;
7472
+ server.close(resolve2);
7473
+ });
7369
7474
  });
7370
- };
7371
- if (pathname.endsWith("/")) {
7372
- const newUrl = `${pathname}index.html`;
7373
- const filePath = import_node_path16.default.join(distPath, newUrl);
7374
- if (await isFileExists2(filePath, outputFileSystem)) {
7375
- return rewrite(newUrl);
7376
- }
7377
- } else if (!import_node_path16.default.extname(pathname)) {
7378
- const newUrl = `${pathname}.html`;
7379
- const filePath = import_node_path16.default.join(distPath, newUrl);
7380
- if (await isFileExists2(filePath, outputFileSystem)) {
7381
- return rewrite(newUrl);
7475
+ } catch (e) {
7476
+ if (e.code !== "EADDRINUSE") {
7477
+ throw e;
7382
7478
  }
7479
+ port++;
7480
+ attempts++;
7383
7481
  }
7384
- next();
7385
- };
7386
- };
7387
- getHtmlFallbackMiddleware = ({ htmlFallback, distPath, callback, outputFileSystem }) => {
7388
- return async (req, res, next) => {
7389
- if (!maybeHTMLRequest(req) || "/favicon.ico" === req.url || htmlFallback !== "index") {
7390
- return next();
7391
- }
7392
- const filePath = import_node_path16.default.join(distPath, "index.html");
7393
- if (await isFileExists2(filePath, outputFileSystem)) {
7394
- const newUrl = "/index.html";
7395
- if (import_rslog.logger.level === "verbose") {
7396
- import_rslog.logger.debug(
7397
- `${req.method} ${import_picocolors9.default.gray(
7398
- `${req.url} ${import_picocolors9.default.yellow("fallback")} to ${newUrl}`
7399
- )}`
7400
- );
7401
- }
7402
- req.url = newUrl;
7403
- return callback(req, res, (...args) => next(...args));
7482
+ }
7483
+ if (port !== original) {
7484
+ if (strictPort) {
7485
+ throw new Error(
7486
+ `Port "${original}" is occupied, please choose another one.`
7487
+ );
7488
+ }
7489
+ }
7490
+ return port;
7491
+ };
7492
+ getServerConfig = async ({
7493
+ config
7494
+ }) => {
7495
+ const host = config.server.host || DEFAULT_DEV_HOST;
7496
+ const originalPort = config.server.port || DEFAULT_PORT;
7497
+ const port = await getPort({
7498
+ host,
7499
+ port: originalPort,
7500
+ strictPort: config.server.strictPort || false
7501
+ });
7502
+ const https = Boolean(config.server.https) || false;
7503
+ const portTip = port !== originalPort ? `Port ${originalPort} is in use, ${import_picocolors9.default.yellow(`using port ${port}.`)}` : void 0;
7504
+ return {
7505
+ port,
7506
+ host,
7507
+ https,
7508
+ portTip
7509
+ };
7510
+ };
7511
+ getIpv4Interfaces = () => {
7512
+ const interfaces = import_node_os.default.networkInterfaces();
7513
+ const ipv4Interfaces = /* @__PURE__ */ new Map();
7514
+ for (const key of Object.keys(interfaces)) {
7515
+ for (const detail of interfaces[key]) {
7516
+ const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
7517
+ if (detail.family === familyV4Value && !ipv4Interfaces.has(detail.address)) {
7518
+ ipv4Interfaces.set(detail.address, detail);
7519
+ }
7520
+ }
7521
+ }
7522
+ return Array.from(ipv4Interfaces.values());
7523
+ };
7524
+ isLoopbackHost = (host) => {
7525
+ const loopbackHosts = [
7526
+ "localhost",
7527
+ "127.0.0.1",
7528
+ "::1",
7529
+ "0000:0000:0000:0000:0000:0000:0000:0001"
7530
+ ];
7531
+ return loopbackHosts.includes(host);
7532
+ };
7533
+ getHostInUrl = (host) => {
7534
+ if (import_node_net.default.isIPv6(host)) {
7535
+ return host === "::" ? "[::1]" : `[${host}]`;
7536
+ }
7537
+ return host;
7538
+ };
7539
+ concatUrl = ({
7540
+ host,
7541
+ port,
7542
+ protocol
7543
+ }) => `${protocol}://${host}:${port}`;
7544
+ LOCAL_LABEL = "Local: ";
7545
+ NETWORK_LABEL = "Network: ";
7546
+ getUrlLabel = (url2) => {
7547
+ try {
7548
+ const { host } = new URL(url2);
7549
+ return isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL;
7550
+ } catch (err) {
7551
+ return NETWORK_LABEL;
7552
+ }
7553
+ };
7554
+ getAddressUrls = ({
7555
+ protocol = "http",
7556
+ port,
7557
+ host
7558
+ }) => {
7559
+ if (host && host !== DEFAULT_DEV_HOST) {
7560
+ return [
7561
+ {
7562
+ label: isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL,
7563
+ url: concatUrl({
7564
+ port,
7565
+ host: getHostInUrl(host),
7566
+ protocol
7567
+ })
7568
+ }
7569
+ ];
7570
+ }
7571
+ const ipv4Interfaces = getIpv4Interfaces();
7572
+ const addressUrls = [];
7573
+ let hasLocalUrl = false;
7574
+ for (const detail of ipv4Interfaces) {
7575
+ if (isLoopbackHost(detail.address) || detail.internal) {
7576
+ if (hasLocalUrl) {
7577
+ continue;
7578
+ }
7579
+ addressUrls.push({
7580
+ label: LOCAL_LABEL,
7581
+ url: concatUrl({ host: "localhost", port, protocol })
7582
+ });
7583
+ hasLocalUrl = true;
7584
+ } else {
7585
+ addressUrls.push({
7586
+ label: NETWORK_LABEL,
7587
+ url: concatUrl({ host: detail.address, port, protocol })
7588
+ });
7589
+ }
7590
+ }
7591
+ return addressUrls;
7592
+ };
7593
+ COMPILATION_ID_REGEX = /[^a-zA-Z0-9_-]/g;
7594
+ getCompilationId = (compiler) => {
7595
+ const uniqueName = compiler.options.output.uniqueName ?? "";
7596
+ return `${compiler.name ?? ""}_${uniqueName.replace(COMPILATION_ID_REGEX, "_")}`;
7597
+ };
7598
+ }
7599
+ });
7600
+
7601
+ // src/server/middlewares.ts
7602
+ var import_node_path17, import_picocolors10, faviconFallbackMiddleware, getStatusCodeColor, getRequestLoggerMiddleware, notFoundMiddleware, isFileExists2, maybeHTMLRequest, postfixRE, getUrlPathname, getHtmlCompletionMiddleware, getBaseMiddleware, getHtmlFallbackMiddleware;
7603
+ var init_middlewares = __esm({
7604
+ "src/server/middlewares.ts"() {
7605
+ "use strict";
7606
+ import_node_path17 = __toESM(require("path"));
7607
+ import_picocolors10 = __toESM(require("../compiled/picocolors/index.js"));
7608
+ init_helpers();
7609
+ init_logger();
7610
+ init_helper();
7611
+ faviconFallbackMiddleware = (req, res, next) => {
7612
+ if (req.url === "/favicon.ico") {
7613
+ res.statusCode = 204;
7614
+ res.end();
7615
+ } else {
7616
+ next();
7617
+ }
7618
+ };
7619
+ getStatusCodeColor = (status) => {
7620
+ if (status >= 500) {
7621
+ return import_picocolors10.default.red;
7622
+ }
7623
+ if (status >= 400) {
7624
+ return import_picocolors10.default.yellow;
7625
+ }
7626
+ if (status >= 300) {
7627
+ return import_picocolors10.default.cyan;
7628
+ }
7629
+ if (status >= 200) {
7630
+ return import_picocolors10.default.green;
7631
+ }
7632
+ return (res) => res;
7633
+ };
7634
+ getRequestLoggerMiddleware = async () => {
7635
+ const { default: onFinished } = await import("../compiled/on-finished/index.js");
7636
+ return (req, res, next) => {
7637
+ const _startAt = process.hrtime();
7638
+ const logRequest = () => {
7639
+ const method = req.method;
7640
+ const url2 = req.originalUrl || req.url;
7641
+ const status = Number(res.statusCode);
7642
+ const statusColor = getStatusCodeColor(status);
7643
+ const endAt = process.hrtime();
7644
+ const totalTime = (endAt[0] - _startAt[0]) * 1e3 + (endAt[1] - _startAt[1]) * 1e-6;
7645
+ import_rslog.logger.debug(
7646
+ `${statusColor(status)} ${method} ${import_picocolors10.default.gray(url2)} ${import_picocolors10.default.gray(
7647
+ `${totalTime.toFixed(3)} ms`
7648
+ )}`
7649
+ );
7650
+ };
7651
+ onFinished(res, logRequest);
7652
+ next();
7653
+ };
7654
+ };
7655
+ notFoundMiddleware = (_req, res, _next) => {
7656
+ res.statusCode = 404;
7657
+ res.end();
7658
+ };
7659
+ isFileExists2 = async (filePath, outputFileSystem) => new Promise((resolve2) => {
7660
+ outputFileSystem.stat(filePath, (_error, stats) => {
7661
+ resolve2(stats?.isFile());
7662
+ });
7663
+ });
7664
+ maybeHTMLRequest = (req) => {
7665
+ if (
7666
+ // require headers and url
7667
+ !req.url || !req.headers || // only accept GET or HEAD
7668
+ req.method !== "GET" && req.method !== "HEAD"
7669
+ ) {
7670
+ return false;
7671
+ }
7672
+ const { accept } = req.headers;
7673
+ return typeof accept === "string" && (accept.includes("text/html") || accept.includes("*/*"));
7674
+ };
7675
+ postfixRE = /[?#].*$/;
7676
+ getUrlPathname = (url2) => {
7677
+ return url2.replace(postfixRE, "");
7678
+ };
7679
+ getHtmlCompletionMiddleware = ({ distPath, callback, outputFileSystem }) => {
7680
+ return async (req, res, next) => {
7681
+ if (!maybeHTMLRequest(req)) {
7682
+ return next();
7683
+ }
7684
+ const url2 = req.url;
7685
+ const pathname = getUrlPathname(url2);
7686
+ const rewrite = (newUrl) => {
7687
+ req.url = newUrl;
7688
+ return callback(req, res, (...args) => {
7689
+ next(...args);
7690
+ });
7691
+ };
7692
+ if (pathname.endsWith("/")) {
7693
+ const newUrl = `${pathname}index.html`;
7694
+ const filePath = import_node_path17.default.join(distPath, newUrl);
7695
+ if (await isFileExists2(filePath, outputFileSystem)) {
7696
+ return rewrite(newUrl);
7697
+ }
7698
+ } else if (!import_node_path17.default.extname(pathname)) {
7699
+ const newUrl = `${pathname}.html`;
7700
+ const filePath = import_node_path17.default.join(distPath, newUrl);
7701
+ if (await isFileExists2(filePath, outputFileSystem)) {
7702
+ return rewrite(newUrl);
7703
+ }
7704
+ }
7705
+ next();
7706
+ };
7707
+ };
7708
+ getBaseMiddleware = ({
7709
+ base
7710
+ }) => {
7711
+ return async (req, res, next) => {
7712
+ const url2 = req.url;
7713
+ const pathname = getUrlPathname(url2);
7714
+ if (pathname.startsWith(base)) {
7715
+ req.url = stripBase(url2, base);
7716
+ return next();
7717
+ }
7718
+ const redirectPath = addTrailingSlash(url2) !== base ? joinUrlSegments(base, url2) : base;
7719
+ if (pathname === "/" || pathname === "/index.html") {
7720
+ res.writeHead(302, {
7721
+ Location: redirectPath
7722
+ });
7723
+ res.end();
7724
+ return;
7725
+ }
7726
+ if (req.headers.accept?.includes("text/html")) {
7727
+ res.writeHead(404, {
7728
+ "Content-Type": "text/html"
7729
+ });
7730
+ res.end(
7731
+ `The server is configured with a base URL of ${base} - did you mean to visit <a href="${redirectPath}">${redirectPath}</a> instead?`
7732
+ );
7733
+ return;
7734
+ }
7735
+ res.writeHead(404, {
7736
+ "Content-Type": "text/plain"
7737
+ });
7738
+ res.end(
7739
+ `The server is configured with a base URL of ${base} - did you mean to visit ${redirectPath} instead?`
7740
+ );
7741
+ return;
7742
+ };
7743
+ };
7744
+ getHtmlFallbackMiddleware = ({ htmlFallback, distPath, callback, outputFileSystem }) => {
7745
+ return async (req, res, next) => {
7746
+ if (!maybeHTMLRequest(req) || "/favicon.ico" === req.url || htmlFallback !== "index") {
7747
+ return next();
7748
+ }
7749
+ const filePath = import_node_path17.default.join(distPath, "index.html");
7750
+ if (await isFileExists2(filePath, outputFileSystem)) {
7751
+ const newUrl = "/index.html";
7752
+ if (import_rslog.logger.level === "verbose") {
7753
+ import_rslog.logger.debug(
7754
+ `${req.method} ${import_picocolors10.default.gray(
7755
+ `${req.url} ${import_picocolors10.default.yellow("fallback")} to ${newUrl}`
7756
+ )}`
7757
+ );
7758
+ }
7759
+ req.url = newUrl;
7760
+ return callback(req, res, (...args) => next(...args));
7404
7761
  }
7405
7762
  next();
7406
7763
  };
@@ -7584,11 +7941,11 @@ var init_proxy = __esm({
7584
7941
  });
7585
7942
 
7586
7943
  // src/server/getDevMiddlewares.ts
7587
- var import_node_path17, import_node_url2, applySetupMiddlewares, applyDefaultMiddlewares, getMiddlewares;
7944
+ var import_node_path18, import_node_url2, applySetupMiddlewares, applyDefaultMiddlewares, getMiddlewares;
7588
7945
  var init_getDevMiddlewares = __esm({
7589
7946
  "src/server/getDevMiddlewares.ts"() {
7590
7947
  "use strict";
7591
- import_node_path17 = require("path");
7948
+ import_node_path18 = require("path");
7592
7949
  import_node_url2 = __toESM(require("url"));
7593
7950
  init_config();
7594
7951
  init_logger();
@@ -7605,437 +7962,148 @@ var init_getDevMiddlewares = __esm({
7605
7962
  handler(
7606
7963
  {
7607
7964
  unshift: (...handlers) => before.unshift(...handlers),
7608
- push: (...handlers) => after.push(...handlers)
7609
- },
7610
- serverOptions
7611
- );
7612
- }
7613
- return { before, after };
7614
- };
7615
- applyDefaultMiddlewares = async ({
7616
- middlewares,
7617
- server,
7618
- compileMiddlewareAPI,
7619
- output,
7620
- pwd,
7621
- outputFileSystem
7622
- }) => {
7623
- const upgradeEvents = [];
7624
- if (server.compress) {
7625
- const { gzipMiddleware: gzipMiddleware2 } = await Promise.resolve().then(() => (init_gzipMiddleware(), gzipMiddleware_exports));
7626
- middlewares.push(gzipMiddleware2());
7627
- }
7628
- middlewares.push((req, res, next) => {
7629
- res.setHeader("Access-Control-Allow-Origin", "*");
7630
- const path21 = req.url ? import_node_url2.default.parse(req.url).pathname : "";
7631
- if (path21?.includes("hot-update")) {
7632
- res.setHeader("Access-Control-Allow-Credentials", "false");
7633
- }
7634
- const confHeaders = server.headers;
7635
- if (confHeaders) {
7636
- for (const [key, value] of Object.entries(confHeaders)) {
7637
- res.setHeader(key, value);
7638
- }
7639
- }
7640
- next();
7641
- });
7642
- if (server.proxy) {
7643
- const { createProxyMiddleware: createProxyMiddleware2 } = await Promise.resolve().then(() => (init_proxy(), proxy_exports));
7644
- const { middlewares: proxyMiddlewares, upgrade } = await createProxyMiddleware2(server.proxy);
7645
- upgradeEvents.push(upgrade);
7646
- for (const middleware of proxyMiddlewares) {
7647
- middlewares.push(middleware);
7648
- }
7649
- }
7650
- const { default: launchEditorMiddleware } = await import("../compiled/launch-editor-middleware/index.js");
7651
- middlewares.push(["/__open-in-editor", launchEditorMiddleware()]);
7652
- if (compileMiddlewareAPI) {
7653
- middlewares.push(compileMiddlewareAPI.middleware);
7654
- upgradeEvents.push(
7655
- compileMiddlewareAPI.onUpgrade.bind(compileMiddlewareAPI)
7656
- );
7657
- middlewares.push((req, res, next) => {
7658
- if (req.url?.endsWith(".hot-update.json") && req.method !== "OPTIONS") {
7659
- res.statusCode = 404;
7660
- res.end();
7661
- } else {
7662
- next();
7663
- }
7664
- });
7665
- }
7666
- const distPath = (0, import_node_path17.isAbsolute)(output.distPath) ? output.distPath : (0, import_node_path17.join)(pwd, output.distPath);
7667
- if (compileMiddlewareAPI) {
7668
- middlewares.push(
7669
- getHtmlCompletionMiddleware({
7670
- distPath,
7671
- callback: compileMiddlewareAPI.middleware,
7672
- outputFileSystem
7673
- })
7674
- );
7675
- }
7676
- const publicDirs = normalizePublicDirs(server?.publicDir);
7677
- for (const publicDir of publicDirs) {
7678
- const { default: sirv } = await import("../compiled/sirv/index.js");
7679
- const { name } = publicDir;
7680
- const normalizedPath = (0, import_node_path17.isAbsolute)(name) ? name : (0, import_node_path17.join)(pwd, name);
7681
- const assetMiddleware = sirv(normalizedPath, {
7682
- etag: true,
7683
- dev: true
7684
- });
7685
- middlewares.push(assetMiddleware);
7686
- }
7687
- if (compileMiddlewareAPI) {
7688
- middlewares.push(
7689
- getHtmlFallbackMiddleware({
7690
- distPath,
7691
- callback: compileMiddlewareAPI.middleware,
7692
- htmlFallback: server.htmlFallback,
7693
- outputFileSystem
7694
- })
7695
- );
7696
- }
7697
- if (server.historyApiFallback) {
7698
- const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
7699
- const historyApiFallbackMiddleware = connectHistoryApiFallback(
7700
- server.historyApiFallback === true ? {} : server.historyApiFallback
7701
- );
7702
- middlewares.push(historyApiFallbackMiddleware);
7703
- compileMiddlewareAPI?.middleware && middlewares.push(compileMiddlewareAPI.middleware);
7704
- }
7705
- middlewares.push(faviconFallbackMiddleware);
7706
- middlewares.push((req, res, next) => {
7707
- if (req.method === "OPTIONS") {
7708
- res.statusCode = 204;
7709
- res.setHeader("Content-Length", "0");
7710
- res.end();
7711
- return;
7712
- }
7713
- next();
7714
- });
7715
- return {
7716
- onUpgrade: (...args) => {
7717
- for (const cb of upgradeEvents) {
7718
- cb(...args);
7719
- }
7720
- }
7721
- };
7722
- };
7723
- getMiddlewares = async (options) => {
7724
- const middlewares = [];
7725
- const { environments, compileMiddlewareAPI } = options;
7726
- if (import_rslog.logger.level === "verbose") {
7727
- middlewares.push(await getRequestLoggerMiddleware());
7728
- }
7729
- const { before, after } = applySetupMiddlewares(
7730
- options.dev,
7731
- environments,
7732
- compileMiddlewareAPI
7733
- );
7734
- middlewares.push(...before);
7735
- const { onUpgrade } = await applyDefaultMiddlewares({
7736
- ...options,
7737
- middlewares
7738
- });
7739
- middlewares.push(...after);
7740
- return {
7741
- close: async () => {
7742
- compileMiddlewareAPI?.close();
7743
- },
7744
- onUpgrade,
7745
- middlewares
7746
- };
7747
- };
7748
- }
7749
- });
7750
-
7751
- // src/server/helper.ts
7752
- function getURLMessages(urls, routes) {
7753
- if (routes.length === 1) {
7754
- return urls.map(
7755
- ({ label, url: url2 }) => ` ${`➜ ${label.padEnd(10)}`}${import_picocolors10.default.cyan(
7756
- normalizeUrl(`${url2}${routes[0].pathname}`)
7757
- )}
7758
- `
7759
- ).join("");
7760
- }
7761
- let message = "";
7762
- const maxNameLength = Math.max(...routes.map((r) => r.entryName.length));
7763
- urls.forEach(({ label, url: url2 }, index) => {
7764
- if (index > 0) {
7765
- message += "\n";
7766
- }
7767
- message += ` ${`➜ ${label}`}
7768
- `;
7769
- for (const r of routes) {
7770
- message += ` ${import_picocolors10.default.dim("-")} ${import_picocolors10.default.dim(
7771
- r.entryName.padEnd(maxNameLength + 4)
7772
- )}${import_picocolors10.default.cyan(normalizeUrl(`${url2}${r.pathname}`))}
7773
- `;
7774
- }
7775
- });
7776
- return message;
7777
- }
7778
- function printServerURLs({
7779
- urls: originalUrls,
7780
- port,
7781
- routes,
7782
- protocol,
7783
- printUrls
7784
- }) {
7785
- if (printUrls === false) {
7786
- return null;
7787
- }
7788
- let urls = originalUrls;
7789
- if (isFunction(printUrls)) {
7790
- const newUrls = printUrls({
7791
- urls: urls.map((item) => item.url),
7792
- port,
7793
- routes,
7794
- protocol
7795
- });
7796
- if (!newUrls) {
7797
- return null;
7798
- }
7799
- if (!Array.isArray(newUrls)) {
7800
- throw new Error(
7801
- `"server.printUrls" must return an array, but got ${typeof newUrls}.`
7802
- );
7803
- }
7804
- urls = newUrls.map((url2) => ({
7805
- url: url2,
7806
- label: getUrlLabel(url2)
7807
- }));
7808
- }
7809
- if (urls.length === 0 || routes.length === 0) {
7810
- return null;
7811
- }
7812
- const message = getURLMessages(urls, routes);
7813
- import_rslog.logger.log(message);
7814
- return message;
7815
- }
7816
- function getServerTerminator(server) {
7817
- let listened = false;
7818
- const pendingSockets = /* @__PURE__ */ new Set();
7819
- const onConnection = (socket) => {
7820
- pendingSockets.add(socket);
7821
- socket.on("close", () => {
7822
- pendingSockets.delete(socket);
7823
- });
7824
- };
7825
- server.on("connection", onConnection);
7826
- server.on("secureConnection", onConnection);
7827
- server.once("listening", () => {
7828
- listened = true;
7829
- });
7830
- return () => new Promise((resolve2, reject) => {
7831
- for (const socket of pendingSockets) {
7832
- socket.destroy();
7833
- }
7834
- if (listened) {
7835
- server.close((err) => err ? reject(err) : resolve2());
7836
- } else {
7837
- resolve2();
7838
- }
7839
- });
7840
- }
7841
- var import_node_net, import_node_os, import_node_path18, import_picocolors10, normalizeUrl, formatPrefix, getRoutes, formatRoutes, getPort, getServerConfig, getIpv4Interfaces, isLoopbackHost, getHostInUrl, concatUrl, LOCAL_LABEL, NETWORK_LABEL, getUrlLabel, getAddressUrls, COMPILATION_ID_REGEX, getCompilationId;
7842
- var init_helper = __esm({
7843
- "src/server/helper.ts"() {
7844
- "use strict";
7845
- import_node_net = __toESM(require("net"));
7846
- import_node_os = __toESM(require("os"));
7847
- import_node_path18 = require("path");
7848
- import_picocolors10 = __toESM(require("../compiled/picocolors/index.js"));
7849
- init_constants();
7850
- init_helpers();
7851
- init_logger();
7852
- normalizeUrl = (url2) => url2.replace(/([^:]\/)\/+/g, "$1");
7853
- formatPrefix = (input) => {
7854
- let prefix = input;
7855
- if (prefix?.startsWith("./")) {
7856
- prefix = prefix.replace("./", "");
7857
- }
7858
- if (!prefix) {
7859
- return "/";
7860
- }
7861
- const hasLeadingSlash = prefix.startsWith("/");
7862
- const hasTailSlash = prefix.endsWith("/");
7863
- return `${hasLeadingSlash ? "" : "/"}${prefix}${hasTailSlash ? "" : "/"}`;
7864
- };
7865
- getRoutes = (context) => {
7866
- return Object.values(context.environments).reduce(
7867
- (prev, environmentContext) => {
7868
- const { distPath, config } = environmentContext;
7869
- const distPrefix = import_node_path18.posix.relative(context.distPath, distPath);
7870
- const routes = formatRoutes(
7871
- environmentContext.htmlPaths,
7872
- import_node_path18.posix.join(distPrefix, config.output.distPath.html),
7873
- config.html.outputStructure
7874
- );
7875
- return prev.concat(...routes);
7876
- },
7877
- []
7878
- );
7879
- };
7880
- formatRoutes = (entry, prefix, outputStructure) => {
7881
- const formattedPrefix = formatPrefix(prefix);
7882
- return Object.keys(entry).map((entryName) => {
7883
- const isIndex = entryName === "index" && outputStructure !== "nested";
7884
- const displayName = isIndex ? "" : entryName;
7885
- return {
7886
- entryName,
7887
- pathname: formattedPrefix + displayName
7888
- };
7889
- }).sort((a) => a.entryName === "index" ? -1 : 1);
7890
- };
7891
- getPort = async ({
7892
- host,
7893
- port,
7894
- strictPort,
7895
- tryLimits = 20
7896
- }) => {
7897
- if (typeof port === "string") {
7898
- port = Number.parseInt(port, 10);
7965
+ push: (...handlers) => after.push(...handlers)
7966
+ },
7967
+ serverOptions
7968
+ );
7899
7969
  }
7900
- if (strictPort) {
7901
- tryLimits = 1;
7970
+ return { before, after };
7971
+ };
7972
+ applyDefaultMiddlewares = async ({
7973
+ middlewares,
7974
+ server,
7975
+ compileMiddlewareAPI,
7976
+ output,
7977
+ pwd,
7978
+ outputFileSystem
7979
+ }) => {
7980
+ const upgradeEvents = [];
7981
+ if (server.compress) {
7982
+ const { gzipMiddleware: gzipMiddleware2 } = await Promise.resolve().then(() => (init_gzipMiddleware(), gzipMiddleware_exports));
7983
+ middlewares.push(gzipMiddleware2());
7902
7984
  }
7903
- const original = port;
7904
- let found = false;
7905
- let attempts = 0;
7906
- while (!found && attempts <= tryLimits) {
7907
- try {
7908
- await new Promise((resolve2, reject) => {
7909
- const server = import_node_net.default.createServer();
7910
- server.unref();
7911
- server.on("error", reject);
7912
- server.listen({ port, host }, () => {
7913
- found = true;
7914
- server.close(resolve2);
7915
- });
7916
- });
7917
- } catch (e) {
7918
- if (e.code !== "EADDRINUSE") {
7919
- throw e;
7985
+ middlewares.push((req, res, next) => {
7986
+ res.setHeader("Access-Control-Allow-Origin", "*");
7987
+ const path21 = req.url ? import_node_url2.default.parse(req.url).pathname : "";
7988
+ if (path21?.includes("hot-update")) {
7989
+ res.setHeader("Access-Control-Allow-Credentials", "false");
7990
+ }
7991
+ const confHeaders = server.headers;
7992
+ if (confHeaders) {
7993
+ for (const [key, value] of Object.entries(confHeaders)) {
7994
+ res.setHeader(key, value);
7920
7995
  }
7921
- port++;
7922
- attempts++;
7923
7996
  }
7924
- }
7925
- if (port !== original) {
7926
- if (strictPort) {
7927
- throw new Error(
7928
- `Port "${original}" is occupied, please choose another one.`
7929
- );
7997
+ next();
7998
+ });
7999
+ if (server.proxy) {
8000
+ const { createProxyMiddleware: createProxyMiddleware2 } = await Promise.resolve().then(() => (init_proxy(), proxy_exports));
8001
+ const { middlewares: proxyMiddlewares, upgrade } = await createProxyMiddleware2(server.proxy);
8002
+ upgradeEvents.push(upgrade);
8003
+ for (const middleware of proxyMiddlewares) {
8004
+ middlewares.push(middleware);
7930
8005
  }
7931
8006
  }
7932
- return port;
7933
- };
7934
- getServerConfig = async ({
7935
- config
7936
- }) => {
7937
- const host = config.server.host || DEFAULT_DEV_HOST;
7938
- const originalPort = config.server.port || DEFAULT_PORT;
7939
- const port = await getPort({
7940
- host,
7941
- port: originalPort,
7942
- strictPort: config.server.strictPort || false
7943
- });
7944
- const https = Boolean(config.server.https) || false;
7945
- const portTip = port !== originalPort ? `Port ${originalPort} is in use, ${import_picocolors10.default.yellow(`using port ${port}.`)}` : void 0;
7946
- return {
7947
- port,
7948
- host,
7949
- https,
7950
- portTip
7951
- };
7952
- };
7953
- getIpv4Interfaces = () => {
7954
- const interfaces = import_node_os.default.networkInterfaces();
7955
- const ipv4Interfaces = /* @__PURE__ */ new Map();
7956
- for (const key of Object.keys(interfaces)) {
7957
- for (const detail of interfaces[key]) {
7958
- const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
7959
- if (detail.family === familyV4Value && !ipv4Interfaces.has(detail.address)) {
7960
- ipv4Interfaces.set(detail.address, detail);
8007
+ if (server.base && server.base !== "/") {
8008
+ middlewares.push(getBaseMiddleware({ base: server.base }));
8009
+ }
8010
+ const { default: launchEditorMiddleware } = await import("../compiled/launch-editor-middleware/index.js");
8011
+ middlewares.push(["/__open-in-editor", launchEditorMiddleware()]);
8012
+ if (compileMiddlewareAPI) {
8013
+ middlewares.push(compileMiddlewareAPI.middleware);
8014
+ upgradeEvents.push(
8015
+ compileMiddlewareAPI.onUpgrade.bind(compileMiddlewareAPI)
8016
+ );
8017
+ middlewares.push((req, res, next) => {
8018
+ if (req.url?.endsWith(".hot-update.json") && req.method !== "OPTIONS") {
8019
+ res.statusCode = 404;
8020
+ res.end();
8021
+ } else {
8022
+ next();
7961
8023
  }
7962
- }
8024
+ });
7963
8025
  }
7964
- return Array.from(ipv4Interfaces.values());
7965
- };
7966
- isLoopbackHost = (host) => {
7967
- const loopbackHosts = [
7968
- "localhost",
7969
- "127.0.0.1",
7970
- "::1",
7971
- "0000:0000:0000:0000:0000:0000:0000:0001"
7972
- ];
7973
- return loopbackHosts.includes(host);
7974
- };
7975
- getHostInUrl = (host) => {
7976
- if (import_node_net.default.isIPv6(host)) {
7977
- return host === "::" ? "[::1]" : `[${host}]`;
8026
+ const distPath = (0, import_node_path18.isAbsolute)(output.distPath) ? output.distPath : (0, import_node_path18.join)(pwd, output.distPath);
8027
+ if (compileMiddlewareAPI) {
8028
+ middlewares.push(
8029
+ getHtmlCompletionMiddleware({
8030
+ distPath,
8031
+ callback: compileMiddlewareAPI.middleware,
8032
+ outputFileSystem
8033
+ })
8034
+ );
7978
8035
  }
7979
- return host;
7980
- };
7981
- concatUrl = ({
7982
- host,
7983
- port,
7984
- protocol
7985
- }) => `${protocol}://${host}:${port}`;
7986
- LOCAL_LABEL = "Local: ";
7987
- NETWORK_LABEL = "Network: ";
7988
- getUrlLabel = (url2) => {
7989
- try {
7990
- const { host } = new URL(url2);
7991
- return isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL;
7992
- } catch (err) {
7993
- return NETWORK_LABEL;
8036
+ const publicDirs = normalizePublicDirs(server?.publicDir);
8037
+ for (const publicDir of publicDirs) {
8038
+ const { default: sirv } = await import("../compiled/sirv/index.js");
8039
+ const { name } = publicDir;
8040
+ const normalizedPath = (0, import_node_path18.isAbsolute)(name) ? name : (0, import_node_path18.join)(pwd, name);
8041
+ const assetMiddleware = sirv(normalizedPath, {
8042
+ etag: true,
8043
+ dev: true
8044
+ });
8045
+ middlewares.push(assetMiddleware);
7994
8046
  }
7995
- };
7996
- getAddressUrls = ({
7997
- protocol = "http",
7998
- port,
7999
- host
8000
- }) => {
8001
- if (host && host !== DEFAULT_DEV_HOST) {
8002
- return [
8003
- {
8004
- label: isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL,
8005
- url: concatUrl({
8006
- port,
8007
- host: getHostInUrl(host),
8008
- protocol
8009
- })
8010
- }
8011
- ];
8047
+ if (compileMiddlewareAPI) {
8048
+ middlewares.push(
8049
+ getHtmlFallbackMiddleware({
8050
+ distPath,
8051
+ callback: compileMiddlewareAPI.middleware,
8052
+ htmlFallback: server.htmlFallback,
8053
+ outputFileSystem
8054
+ })
8055
+ );
8012
8056
  }
8013
- const ipv4Interfaces = getIpv4Interfaces();
8014
- const addressUrls = [];
8015
- let hasLocalUrl = false;
8016
- for (const detail of ipv4Interfaces) {
8017
- if (isLoopbackHost(detail.address) || detail.internal) {
8018
- if (hasLocalUrl) {
8019
- continue;
8057
+ if (server.historyApiFallback) {
8058
+ const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
8059
+ const historyApiFallbackMiddleware = connectHistoryApiFallback(
8060
+ server.historyApiFallback === true ? {} : server.historyApiFallback
8061
+ );
8062
+ middlewares.push(historyApiFallbackMiddleware);
8063
+ compileMiddlewareAPI?.middleware && middlewares.push(compileMiddlewareAPI.middleware);
8064
+ }
8065
+ middlewares.push(faviconFallbackMiddleware);
8066
+ middlewares.push((req, res, next) => {
8067
+ if (req.method === "OPTIONS") {
8068
+ res.statusCode = 204;
8069
+ res.setHeader("Content-Length", "0");
8070
+ res.end();
8071
+ return;
8072
+ }
8073
+ next();
8074
+ });
8075
+ return {
8076
+ onUpgrade: (...args) => {
8077
+ for (const cb of upgradeEvents) {
8078
+ cb(...args);
8020
8079
  }
8021
- addressUrls.push({
8022
- label: LOCAL_LABEL,
8023
- url: concatUrl({ host: "localhost", port, protocol })
8024
- });
8025
- hasLocalUrl = true;
8026
- } else {
8027
- addressUrls.push({
8028
- label: NETWORK_LABEL,
8029
- url: concatUrl({ host: detail.address, port, protocol })
8030
- });
8031
8080
  }
8032
- }
8033
- return addressUrls;
8081
+ };
8034
8082
  };
8035
- COMPILATION_ID_REGEX = /[^a-zA-Z0-9_-]/g;
8036
- getCompilationId = (compiler) => {
8037
- const uniqueName = compiler.options.output.uniqueName ?? "";
8038
- return `${compiler.name ?? ""}_${uniqueName.replace(COMPILATION_ID_REGEX, "_")}`;
8083
+ getMiddlewares = async (options) => {
8084
+ const middlewares = [];
8085
+ const { environments, compileMiddlewareAPI } = options;
8086
+ if (import_rslog.logger.level === "verbose") {
8087
+ middlewares.push(await getRequestLoggerMiddleware());
8088
+ }
8089
+ const { before, after } = applySetupMiddlewares(
8090
+ options.dev,
8091
+ environments,
8092
+ compileMiddlewareAPI
8093
+ );
8094
+ middlewares.push(...before);
8095
+ const { onUpgrade } = await applyDefaultMiddlewares({
8096
+ ...options,
8097
+ middlewares
8098
+ });
8099
+ middlewares.push(...after);
8100
+ return {
8101
+ close: async () => {
8102
+ compileMiddlewareAPI?.close();
8103
+ },
8104
+ onUpgrade,
8105
+ middlewares
8106
+ };
8039
8107
  };
8040
8108
  }
8041
8109
  });
@@ -8606,6 +8674,7 @@ var init_compilerDevMiddleware = __esm({
8606
8674
  "use strict";
8607
8675
  init_path();
8608
8676
  init_devMiddleware();
8677
+ init_helper();
8609
8678
  init_socketServer();
8610
8679
  noop = () => {
8611
8680
  };
@@ -8642,7 +8711,10 @@ var init_compilerDevMiddleware = __esm({
8642
8711
  });
8643
8712
  }
8644
8713
  setupDevMiddleware(devMiddleware, publicPaths) {
8645
- const { devConfig, serverConfig } = this;
8714
+ const {
8715
+ devConfig,
8716
+ serverConfig: { headers, base }
8717
+ } = this;
8646
8718
  const callbacks = {
8647
8719
  onInvalid: (compilationId) => {
8648
8720
  this.socketServer.sockWrite({
@@ -8656,7 +8728,7 @@ var init_compilerDevMiddleware = __esm({
8656
8728
  };
8657
8729
  const clientPaths = getClientPaths(devConfig);
8658
8730
  const middleware = devMiddleware({
8659
- headers: serverConfig.headers,
8731
+ headers,
8660
8732
  publicPath: "/",
8661
8733
  stats: false,
8662
8734
  callbacks,
@@ -8669,7 +8741,9 @@ var init_compilerDevMiddleware = __esm({
8669
8741
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#weak_validation
8670
8742
  etag: "weak"
8671
8743
  });
8672
- const assetPrefixes = publicPaths.map(pathnameParse);
8744
+ const assetPrefixes = publicPaths.map(pathnameParse).map(
8745
+ (prefix) => base && base !== "/" ? stripBase(prefix, base) : prefix
8746
+ );
8673
8747
  const warp = async (req, res, next) => {
8674
8748
  const { url: url2 } = req;
8675
8749
  const assetPrefix = url2 && assetPrefixes.find((prefix) => url2.startsWith(prefix));
@@ -10881,13 +10955,16 @@ var init_define = __esm({
10881
10955
  setup(api) {
10882
10956
  api.modifyBundlerChain((chain, { CHAIN_ID: CHAIN_ID2, bundler, environment }) => {
10883
10957
  const { config } = environment;
10958
+ const baseUrl = JSON.stringify(config.server.base);
10884
10959
  const builtinVars = {
10885
10960
  "import.meta.env.MODE": JSON.stringify(config.mode),
10886
10961
  "import.meta.env.DEV": config.mode === "development",
10887
10962
  "import.meta.env.PROD": config.mode === "production",
10963
+ "import.meta.env.BASE_URL": baseUrl,
10888
10964
  "process.env.ASSET_PREFIX": JSON.stringify(
10889
10965
  getPublicPathFromChain(chain, false)
10890
- )
10966
+ ),
10967
+ "process.env.BASE_URL": baseUrl
10891
10968
  };
10892
10969
  chain.plugin(CHAIN_ID2.PLUGIN.DEFINE).use(bundler.DefinePlugin, [
10893
10970
  { ...builtinVars, ...config.source.define }
@@ -12895,7 +12972,7 @@ var init_prodServer = __esm({
12895
12972
  await this.applyDefaultMiddlewares();
12896
12973
  }
12897
12974
  async applyDefaultMiddlewares() {
12898
- const { headers, proxy, historyApiFallback, compress } = this.options.serverConfig;
12975
+ const { headers, proxy, historyApiFallback, compress, base } = this.options.serverConfig;
12899
12976
  if (import_rslog.logger.level === "verbose") {
12900
12977
  this.middlewares.use(await getRequestLoggerMiddleware());
12901
12978
  }
@@ -12924,6 +13001,9 @@ var init_prodServer = __esm({
12924
13001
  }
12925
13002
  this.app.on("upgrade", upgrade);
12926
13003
  }
13004
+ if (base && base !== "/") {
13005
+ this.middlewares.use(getBaseMiddleware({ base }));
13006
+ }
12927
13007
  this.applyStaticAssetMiddleware();
12928
13008
  if (historyApiFallback) {
12929
13009
  const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
@@ -13267,7 +13347,7 @@ var init_init = __esm({
13267
13347
 
13268
13348
  // src/cli/commands.ts
13269
13349
  function runCli() {
13270
- program.name("rsbuild").usage("<command> [options]").version("1.0.9");
13350
+ program.name("rsbuild").usage("<command> [options]").version("1.0.10");
13271
13351
  const devCommand = program.command("dev");
13272
13352
  const buildCommand = program.command("build");
13273
13353
  const previewCommand = program.command("preview");
@@ -13386,16 +13466,25 @@ function initNodeEnv() {
13386
13466
  }
13387
13467
  function prepareCli() {
13388
13468
  initNodeEnv();
13469
+ const { enableCompileCache } = import_node_module.default;
13470
+ if (enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) {
13471
+ try {
13472
+ enableCompileCache();
13473
+ } catch {
13474
+ }
13475
+ }
13389
13476
  const { npm_execpath } = process.env;
13390
13477
  if (!npm_execpath || npm_execpath.includes("npx-cli.js") || npm_execpath.includes(".bun")) {
13391
13478
  console.log();
13392
13479
  }
13393
- import_rslog.logger.greet(` ${`Rsbuild v${"1.0.9"}`}
13480
+ import_rslog.logger.greet(` ${`Rsbuild v${"1.0.10"}`}
13394
13481
  `);
13395
13482
  }
13483
+ var import_node_module;
13396
13484
  var init_prepare = __esm({
13397
13485
  "src/cli/prepare.ts"() {
13398
13486
  "use strict";
13487
+ import_node_module = __toESM(require("module"));
13399
13488
  init_logger();
13400
13489
  }
13401
13490
  });
@@ -13474,7 +13563,7 @@ init_logger();
13474
13563
  init_mergeConfig();
13475
13564
  init_helpers();
13476
13565
  init_constants();
13477
- var version = "1.0.9";
13566
+ var version = "1.0.10";
13478
13567
  // Annotate the CommonJS export names for ESM import in node:
13479
13568
  0 && (module.exports = {
13480
13569
  PLUGIN_CSS_NAME,