@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.js CHANGED
@@ -46,12 +46,12 @@ var __publicField = (obj, key, value) => {
46
46
  return value;
47
47
  };
48
48
 
49
- // ../../node_modules/.pnpm/@modern-js+module-tools@2.60.2_typescript@5.5.2/node_modules/@modern-js/module-tools/shims/esm.js
49
+ // ../../node_modules/.pnpm/@modern-js+module-tools@2.60.2_typescript@5.6.2/node_modules/@modern-js/module-tools/shims/esm.js
50
50
  import path from "path";
51
51
  import { fileURLToPath } from "url";
52
52
  var getFilename, getDirname, __dirname, __filename;
53
53
  var init_esm = __esm({
54
- "../../node_modules/.pnpm/@modern-js+module-tools@2.60.2_typescript@5.5.2/node_modules/@modern-js/module-tools/shims/esm.js"() {
54
+ "../../node_modules/.pnpm/@modern-js+module-tools@2.60.2_typescript@5.6.2/node_modules/@modern-js/module-tools/shims/esm.js"() {
55
55
  "use strict";
56
56
  getFilename = () => fileURLToPath(import.meta.url);
57
57
  getDirname = () => path.dirname(getFilename());
@@ -4235,6 +4235,7 @@ var init_config = __esm({
4235
4235
  getDefaultDevConfig = () => ({
4236
4236
  hmr: true,
4237
4237
  liveReload: true,
4238
+ // Temporary placeholder, default: `${server.base}`
4238
4239
  assetPrefix: DEFAULT_ASSET_PREFIX,
4239
4240
  writeToDisk: false,
4240
4241
  client: {
@@ -4249,6 +4250,7 @@ var init_config = __esm({
4249
4250
  port: DEFAULT_PORT,
4250
4251
  host: DEFAULT_DEV_HOST,
4251
4252
  open: false,
4253
+ base: "/",
4252
4254
  htmlFallback: "index",
4253
4255
  compress: true,
4254
4256
  printUrls: true,
@@ -4312,6 +4314,7 @@ var init_config = __esm({
4312
4314
  image: IMAGE_DIST_DIR,
4313
4315
  media: MEDIA_DIST_DIR
4314
4316
  },
4317
+ // Temporary placeholder, default: `${server.base}`
4315
4318
  assetPrefix: DEFAULT_ASSET_PREFIX,
4316
4319
  filename: {},
4317
4320
  charset: "utf8",
@@ -4356,6 +4359,16 @@ var init_config = __esm({
4356
4359
  const merged = mergeRsbuildConfig(createDefaultConfig(), config);
4357
4360
  merged.root ||= rootPath;
4358
4361
  merged.source ||= {};
4362
+ if (merged.server?.base) {
4363
+ if (config.dev?.assetPrefix === void 0) {
4364
+ merged.dev ||= {};
4365
+ merged.dev.assetPrefix = merged.server.base;
4366
+ }
4367
+ if (config.output?.assetPrefix === void 0) {
4368
+ merged.output ||= {};
4369
+ merged.output.assetPrefix = merged.server.base;
4370
+ }
4371
+ }
4359
4372
  if (!merged.source.tsconfigPath) {
4360
4373
  const tsconfigPath = join3(rootPath, TS_CONFIG_FILE);
4361
4374
  if (await isFileExists(tsconfigPath)) {
@@ -6031,7 +6044,7 @@ async function createContext(options, userConfig, bundlerType) {
6031
6044
  const rsbuildConfig = await withDefaultConfig(rootPath, userConfig);
6032
6045
  const cachePath = join6(rootPath, "node_modules", ".cache");
6033
6046
  return {
6034
- version: "1.0.9",
6047
+ version: "1.0.10",
6035
6048
  rootPath,
6036
6049
  distPath: "",
6037
6050
  cachePath,
@@ -7340,124 +7353,469 @@ var init_environment = __esm({
7340
7353
  }
7341
7354
  });
7342
7355
 
7343
- // src/server/middlewares.ts
7344
- import path8 from "path";
7356
+ // src/server/helper.ts
7357
+ import net from "net";
7358
+ import os from "os";
7359
+ import { posix as posix3 } from "path";
7345
7360
  import color9 from "../compiled/picocolors/index.js";
7346
- var faviconFallbackMiddleware, getStatusCodeColor, getRequestLoggerMiddleware, notFoundMiddleware, isFileExists2, maybeHTMLRequest, postfixRE, getUrlPathname, getHtmlCompletionMiddleware, getHtmlFallbackMiddleware;
7347
- var init_middlewares = __esm({
7348
- "src/server/middlewares.ts"() {
7361
+ function getURLMessages(urls, routes) {
7362
+ if (routes.length === 1) {
7363
+ return urls.map(
7364
+ ({ label, url: url2 }) => ` ${`➜ ${label.padEnd(10)}`}${color9.cyan(
7365
+ normalizeUrl(`${url2}${routes[0].pathname}`)
7366
+ )}
7367
+ `
7368
+ ).join("");
7369
+ }
7370
+ let message = "";
7371
+ const maxNameLength = Math.max(...routes.map((r) => r.entryName.length));
7372
+ urls.forEach(({ label, url: url2 }, index) => {
7373
+ if (index > 0) {
7374
+ message += "\n";
7375
+ }
7376
+ message += ` ${`➜ ${label}`}
7377
+ `;
7378
+ for (const r of routes) {
7379
+ message += ` ${color9.dim("-")} ${color9.dim(
7380
+ r.entryName.padEnd(maxNameLength + 4)
7381
+ )}${color9.cyan(normalizeUrl(`${url2}${r.pathname}`))}
7382
+ `;
7383
+ }
7384
+ });
7385
+ return message;
7386
+ }
7387
+ function printServerURLs({
7388
+ urls: originalUrls,
7389
+ port,
7390
+ routes,
7391
+ protocol,
7392
+ printUrls
7393
+ }) {
7394
+ if (printUrls === false) {
7395
+ return null;
7396
+ }
7397
+ let urls = originalUrls;
7398
+ if (isFunction(printUrls)) {
7399
+ const newUrls = printUrls({
7400
+ urls: urls.map((item) => item.url),
7401
+ port,
7402
+ routes,
7403
+ protocol
7404
+ });
7405
+ if (!newUrls) {
7406
+ return null;
7407
+ }
7408
+ if (!Array.isArray(newUrls)) {
7409
+ throw new Error(
7410
+ `"server.printUrls" must return an array, but got ${typeof newUrls}.`
7411
+ );
7412
+ }
7413
+ urls = newUrls.map((url2) => ({
7414
+ url: url2,
7415
+ label: getUrlLabel(url2)
7416
+ }));
7417
+ }
7418
+ if (urls.length === 0 || routes.length === 0) {
7419
+ return null;
7420
+ }
7421
+ const message = getURLMessages(urls, routes);
7422
+ logger.log(message);
7423
+ return message;
7424
+ }
7425
+ function getServerTerminator(server) {
7426
+ let listened = false;
7427
+ const pendingSockets = /* @__PURE__ */ new Set();
7428
+ const onConnection = (socket) => {
7429
+ pendingSockets.add(socket);
7430
+ socket.on("close", () => {
7431
+ pendingSockets.delete(socket);
7432
+ });
7433
+ };
7434
+ server.on("connection", onConnection);
7435
+ server.on("secureConnection", onConnection);
7436
+ server.once("listening", () => {
7437
+ listened = true;
7438
+ });
7439
+ return () => new Promise((resolve2, reject) => {
7440
+ for (const socket of pendingSockets) {
7441
+ socket.destroy();
7442
+ }
7443
+ if (listened) {
7444
+ server.close((err) => err ? reject(err) : resolve2());
7445
+ } else {
7446
+ resolve2();
7447
+ }
7448
+ });
7449
+ }
7450
+ var normalizeUrl, formatPrefix, joinUrlSegments, stripBase, getRoutes, formatRoutes, getPort, getServerConfig, getIpv4Interfaces, isLoopbackHost, getHostInUrl, concatUrl, LOCAL_LABEL, NETWORK_LABEL, getUrlLabel, getAddressUrls, COMPILATION_ID_REGEX, getCompilationId;
7451
+ var init_helper = __esm({
7452
+ "src/server/helper.ts"() {
7349
7453
  "use strict";
7350
7454
  init_esm();
7455
+ init_constants();
7456
+ init_helpers();
7351
7457
  init_logger();
7352
- faviconFallbackMiddleware = (req, res, next) => {
7353
- if (req.url === "/favicon.ico") {
7354
- res.statusCode = 204;
7355
- res.end();
7356
- } else {
7357
- next();
7358
- }
7359
- };
7360
- getStatusCodeColor = (status) => {
7361
- if (status >= 500) {
7362
- return color9.red;
7458
+ normalizeUrl = (url2) => url2.replace(/([^:]\/)\/+/g, "$1");
7459
+ formatPrefix = (input) => {
7460
+ let prefix = input;
7461
+ if (prefix?.startsWith("./")) {
7462
+ prefix = prefix.replace("./", "");
7363
7463
  }
7364
- if (status >= 400) {
7365
- return color9.yellow;
7464
+ if (!prefix) {
7465
+ return "/";
7366
7466
  }
7367
- if (status >= 300) {
7368
- return color9.cyan;
7467
+ const hasLeadingSlash = prefix.startsWith("/");
7468
+ const hasTailSlash = prefix.endsWith("/");
7469
+ return `${hasLeadingSlash ? "" : "/"}${prefix}${hasTailSlash ? "" : "/"}`;
7470
+ };
7471
+ joinUrlSegments = (s1, s2) => {
7472
+ if (!s1 || !s2) {
7473
+ return s1 || s2 || "";
7369
7474
  }
7370
- if (status >= 200) {
7371
- return color9.green;
7475
+ return addTrailingSlash(s1) + removeLeadingSlash(s2);
7476
+ };
7477
+ stripBase = (path22, base) => {
7478
+ if (path22 === base) {
7479
+ return "/";
7372
7480
  }
7373
- return (res) => res;
7481
+ const trailingSlashBase = addTrailingSlash(base);
7482
+ return path22.startsWith(trailingSlashBase) ? path22.slice(trailingSlashBase.length - 1) : path22;
7374
7483
  };
7375
- getRequestLoggerMiddleware = async () => {
7376
- const { default: onFinished } = await import("../compiled/on-finished/index.js");
7377
- return (req, res, next) => {
7378
- const _startAt = process.hrtime();
7379
- const logRequest = () => {
7380
- const method = req.method;
7381
- const url2 = req.originalUrl || req.url;
7382
- const status = Number(res.statusCode);
7383
- const statusColor = getStatusCodeColor(status);
7384
- const endAt = process.hrtime();
7385
- const totalTime = (endAt[0] - _startAt[0]) * 1e3 + (endAt[1] - _startAt[1]) * 1e-6;
7386
- logger.debug(
7387
- `${statusColor(status)} ${method} ${color9.gray(url2)} ${color9.gray(
7388
- `${totalTime.toFixed(3)} ms`
7389
- )}`
7484
+ getRoutes = (context) => {
7485
+ return Object.values(context.environments).reduce(
7486
+ (prev, environmentContext) => {
7487
+ const { distPath, config } = environmentContext;
7488
+ const distPrefix = posix3.relative(context.distPath, distPath);
7489
+ const routes = formatRoutes(
7490
+ environmentContext.htmlPaths,
7491
+ context.normalizedConfig.server.base,
7492
+ posix3.join(distPrefix, config.output.distPath.html),
7493
+ config.html.outputStructure
7390
7494
  );
7391
- };
7392
- onFinished(res, logRequest);
7393
- next();
7394
- };
7495
+ return prev.concat(...routes);
7496
+ },
7497
+ []
7498
+ );
7395
7499
  };
7396
- notFoundMiddleware = (_req, res, _next) => {
7397
- res.statusCode = 404;
7398
- res.end();
7500
+ formatRoutes = (entry, base, distPathPrefix, outputStructure) => {
7501
+ const prefix = joinUrlSegments(base, formatPrefix(distPathPrefix));
7502
+ return Object.keys(entry).map((entryName) => {
7503
+ const isIndex = entryName === "index" && outputStructure !== "nested";
7504
+ const displayName = isIndex ? "" : entryName;
7505
+ return {
7506
+ entryName,
7507
+ pathname: prefix + displayName
7508
+ };
7509
+ }).sort((a) => a.entryName === "index" ? -1 : 1);
7399
7510
  };
7400
- isFileExists2 = async (filePath, outputFileSystem) => new Promise((resolve2) => {
7401
- outputFileSystem.stat(filePath, (_error, stats) => {
7402
- resolve2(stats?.isFile());
7403
- });
7404
- });
7405
- maybeHTMLRequest = (req) => {
7406
- if (
7407
- // require headers and url
7408
- !req.url || !req.headers || // only accept GET or HEAD
7409
- req.method !== "GET" && req.method !== "HEAD"
7410
- ) {
7411
- return false;
7511
+ getPort = async ({
7512
+ host,
7513
+ port,
7514
+ strictPort,
7515
+ tryLimits = 20
7516
+ }) => {
7517
+ if (typeof port === "string") {
7518
+ port = Number.parseInt(port, 10);
7412
7519
  }
7413
- const { accept } = req.headers;
7414
- return typeof accept === "string" && (accept.includes("text/html") || accept.includes("*/*"));
7415
- };
7416
- postfixRE = /[?#].*$/;
7417
- getUrlPathname = (url2) => {
7418
- return url2.replace(postfixRE, "");
7419
- };
7420
- getHtmlCompletionMiddleware = ({ distPath, callback, outputFileSystem }) => {
7421
- return async (req, res, next) => {
7422
- if (!maybeHTMLRequest(req)) {
7423
- return next();
7424
- }
7425
- const url2 = req.url;
7426
- const pathname = getUrlPathname(url2);
7427
- const rewrite = (newUrl) => {
7428
- req.url = newUrl;
7429
- return callback(req, res, (...args) => {
7430
- next(...args);
7520
+ if (strictPort) {
7521
+ tryLimits = 1;
7522
+ }
7523
+ const original = port;
7524
+ let found = false;
7525
+ let attempts = 0;
7526
+ while (!found && attempts <= tryLimits) {
7527
+ try {
7528
+ await new Promise((resolve2, reject) => {
7529
+ const server = net.createServer();
7530
+ server.unref();
7531
+ server.on("error", reject);
7532
+ server.listen({ port, host }, () => {
7533
+ found = true;
7534
+ server.close(resolve2);
7535
+ });
7431
7536
  });
7432
- };
7433
- if (pathname.endsWith("/")) {
7434
- const newUrl = `${pathname}index.html`;
7435
- const filePath = path8.join(distPath, newUrl);
7436
- if (await isFileExists2(filePath, outputFileSystem)) {
7437
- return rewrite(newUrl);
7438
- }
7439
- } else if (!path8.extname(pathname)) {
7440
- const newUrl = `${pathname}.html`;
7441
- const filePath = path8.join(distPath, newUrl);
7442
- if (await isFileExists2(filePath, outputFileSystem)) {
7443
- return rewrite(newUrl);
7537
+ } catch (e) {
7538
+ if (e.code !== "EADDRINUSE") {
7539
+ throw e;
7444
7540
  }
7541
+ port++;
7542
+ attempts++;
7445
7543
  }
7446
- next();
7447
- };
7448
- };
7449
- getHtmlFallbackMiddleware = ({ htmlFallback, distPath, callback, outputFileSystem }) => {
7450
- return async (req, res, next) => {
7451
- if (!maybeHTMLRequest(req) || "/favicon.ico" === req.url || htmlFallback !== "index") {
7452
- return next();
7544
+ }
7545
+ if (port !== original) {
7546
+ if (strictPort) {
7547
+ throw new Error(
7548
+ `Port "${original}" is occupied, please choose another one.`
7549
+ );
7453
7550
  }
7454
- const filePath = path8.join(distPath, "index.html");
7455
- if (await isFileExists2(filePath, outputFileSystem)) {
7456
- const newUrl = "/index.html";
7551
+ }
7552
+ return port;
7553
+ };
7554
+ getServerConfig = async ({
7555
+ config
7556
+ }) => {
7557
+ const host = config.server.host || DEFAULT_DEV_HOST;
7558
+ const originalPort = config.server.port || DEFAULT_PORT;
7559
+ const port = await getPort({
7560
+ host,
7561
+ port: originalPort,
7562
+ strictPort: config.server.strictPort || false
7563
+ });
7564
+ const https = Boolean(config.server.https) || false;
7565
+ const portTip = port !== originalPort ? `Port ${originalPort} is in use, ${color9.yellow(`using port ${port}.`)}` : void 0;
7566
+ return {
7567
+ port,
7568
+ host,
7569
+ https,
7570
+ portTip
7571
+ };
7572
+ };
7573
+ getIpv4Interfaces = () => {
7574
+ const interfaces = os.networkInterfaces();
7575
+ const ipv4Interfaces = /* @__PURE__ */ new Map();
7576
+ for (const key of Object.keys(interfaces)) {
7577
+ for (const detail of interfaces[key]) {
7578
+ const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
7579
+ if (detail.family === familyV4Value && !ipv4Interfaces.has(detail.address)) {
7580
+ ipv4Interfaces.set(detail.address, detail);
7581
+ }
7582
+ }
7583
+ }
7584
+ return Array.from(ipv4Interfaces.values());
7585
+ };
7586
+ isLoopbackHost = (host) => {
7587
+ const loopbackHosts = [
7588
+ "localhost",
7589
+ "127.0.0.1",
7590
+ "::1",
7591
+ "0000:0000:0000:0000:0000:0000:0000:0001"
7592
+ ];
7593
+ return loopbackHosts.includes(host);
7594
+ };
7595
+ getHostInUrl = (host) => {
7596
+ if (net.isIPv6(host)) {
7597
+ return host === "::" ? "[::1]" : `[${host}]`;
7598
+ }
7599
+ return host;
7600
+ };
7601
+ concatUrl = ({
7602
+ host,
7603
+ port,
7604
+ protocol
7605
+ }) => `${protocol}://${host}:${port}`;
7606
+ LOCAL_LABEL = "Local: ";
7607
+ NETWORK_LABEL = "Network: ";
7608
+ getUrlLabel = (url2) => {
7609
+ try {
7610
+ const { host } = new URL(url2);
7611
+ return isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL;
7612
+ } catch (err) {
7613
+ return NETWORK_LABEL;
7614
+ }
7615
+ };
7616
+ getAddressUrls = ({
7617
+ protocol = "http",
7618
+ port,
7619
+ host
7620
+ }) => {
7621
+ if (host && host !== DEFAULT_DEV_HOST) {
7622
+ return [
7623
+ {
7624
+ label: isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL,
7625
+ url: concatUrl({
7626
+ port,
7627
+ host: getHostInUrl(host),
7628
+ protocol
7629
+ })
7630
+ }
7631
+ ];
7632
+ }
7633
+ const ipv4Interfaces = getIpv4Interfaces();
7634
+ const addressUrls = [];
7635
+ let hasLocalUrl = false;
7636
+ for (const detail of ipv4Interfaces) {
7637
+ if (isLoopbackHost(detail.address) || detail.internal) {
7638
+ if (hasLocalUrl) {
7639
+ continue;
7640
+ }
7641
+ addressUrls.push({
7642
+ label: LOCAL_LABEL,
7643
+ url: concatUrl({ host: "localhost", port, protocol })
7644
+ });
7645
+ hasLocalUrl = true;
7646
+ } else {
7647
+ addressUrls.push({
7648
+ label: NETWORK_LABEL,
7649
+ url: concatUrl({ host: detail.address, port, protocol })
7650
+ });
7651
+ }
7652
+ }
7653
+ return addressUrls;
7654
+ };
7655
+ COMPILATION_ID_REGEX = /[^a-zA-Z0-9_-]/g;
7656
+ getCompilationId = (compiler) => {
7657
+ const uniqueName = compiler.options.output.uniqueName ?? "";
7658
+ return `${compiler.name ?? ""}_${uniqueName.replace(COMPILATION_ID_REGEX, "_")}`;
7659
+ };
7660
+ }
7661
+ });
7662
+
7663
+ // src/server/middlewares.ts
7664
+ import path8 from "path";
7665
+ import color10 from "../compiled/picocolors/index.js";
7666
+ var faviconFallbackMiddleware, getStatusCodeColor, getRequestLoggerMiddleware, notFoundMiddleware, isFileExists2, maybeHTMLRequest, postfixRE, getUrlPathname, getHtmlCompletionMiddleware, getBaseMiddleware, getHtmlFallbackMiddleware;
7667
+ var init_middlewares = __esm({
7668
+ "src/server/middlewares.ts"() {
7669
+ "use strict";
7670
+ init_esm();
7671
+ init_helpers();
7672
+ init_logger();
7673
+ init_helper();
7674
+ faviconFallbackMiddleware = (req, res, next) => {
7675
+ if (req.url === "/favicon.ico") {
7676
+ res.statusCode = 204;
7677
+ res.end();
7678
+ } else {
7679
+ next();
7680
+ }
7681
+ };
7682
+ getStatusCodeColor = (status) => {
7683
+ if (status >= 500) {
7684
+ return color10.red;
7685
+ }
7686
+ if (status >= 400) {
7687
+ return color10.yellow;
7688
+ }
7689
+ if (status >= 300) {
7690
+ return color10.cyan;
7691
+ }
7692
+ if (status >= 200) {
7693
+ return color10.green;
7694
+ }
7695
+ return (res) => res;
7696
+ };
7697
+ getRequestLoggerMiddleware = async () => {
7698
+ const { default: onFinished } = await import("../compiled/on-finished/index.js");
7699
+ return (req, res, next) => {
7700
+ const _startAt = process.hrtime();
7701
+ const logRequest = () => {
7702
+ const method = req.method;
7703
+ const url2 = req.originalUrl || req.url;
7704
+ const status = Number(res.statusCode);
7705
+ const statusColor = getStatusCodeColor(status);
7706
+ const endAt = process.hrtime();
7707
+ const totalTime = (endAt[0] - _startAt[0]) * 1e3 + (endAt[1] - _startAt[1]) * 1e-6;
7708
+ logger.debug(
7709
+ `${statusColor(status)} ${method} ${color10.gray(url2)} ${color10.gray(
7710
+ `${totalTime.toFixed(3)} ms`
7711
+ )}`
7712
+ );
7713
+ };
7714
+ onFinished(res, logRequest);
7715
+ next();
7716
+ };
7717
+ };
7718
+ notFoundMiddleware = (_req, res, _next) => {
7719
+ res.statusCode = 404;
7720
+ res.end();
7721
+ };
7722
+ isFileExists2 = async (filePath, outputFileSystem) => new Promise((resolve2) => {
7723
+ outputFileSystem.stat(filePath, (_error, stats) => {
7724
+ resolve2(stats?.isFile());
7725
+ });
7726
+ });
7727
+ maybeHTMLRequest = (req) => {
7728
+ if (
7729
+ // require headers and url
7730
+ !req.url || !req.headers || // only accept GET or HEAD
7731
+ req.method !== "GET" && req.method !== "HEAD"
7732
+ ) {
7733
+ return false;
7734
+ }
7735
+ const { accept } = req.headers;
7736
+ return typeof accept === "string" && (accept.includes("text/html") || accept.includes("*/*"));
7737
+ };
7738
+ postfixRE = /[?#].*$/;
7739
+ getUrlPathname = (url2) => {
7740
+ return url2.replace(postfixRE, "");
7741
+ };
7742
+ getHtmlCompletionMiddleware = ({ distPath, callback, outputFileSystem }) => {
7743
+ return async (req, res, next) => {
7744
+ if (!maybeHTMLRequest(req)) {
7745
+ return next();
7746
+ }
7747
+ const url2 = req.url;
7748
+ const pathname = getUrlPathname(url2);
7749
+ const rewrite = (newUrl) => {
7750
+ req.url = newUrl;
7751
+ return callback(req, res, (...args) => {
7752
+ next(...args);
7753
+ });
7754
+ };
7755
+ if (pathname.endsWith("/")) {
7756
+ const newUrl = `${pathname}index.html`;
7757
+ const filePath = path8.join(distPath, newUrl);
7758
+ if (await isFileExists2(filePath, outputFileSystem)) {
7759
+ return rewrite(newUrl);
7760
+ }
7761
+ } else if (!path8.extname(pathname)) {
7762
+ const newUrl = `${pathname}.html`;
7763
+ const filePath = path8.join(distPath, newUrl);
7764
+ if (await isFileExists2(filePath, outputFileSystem)) {
7765
+ return rewrite(newUrl);
7766
+ }
7767
+ }
7768
+ next();
7769
+ };
7770
+ };
7771
+ getBaseMiddleware = ({
7772
+ base
7773
+ }) => {
7774
+ return async (req, res, next) => {
7775
+ const url2 = req.url;
7776
+ const pathname = getUrlPathname(url2);
7777
+ if (pathname.startsWith(base)) {
7778
+ req.url = stripBase(url2, base);
7779
+ return next();
7780
+ }
7781
+ const redirectPath = addTrailingSlash(url2) !== base ? joinUrlSegments(base, url2) : base;
7782
+ if (pathname === "/" || pathname === "/index.html") {
7783
+ res.writeHead(302, {
7784
+ Location: redirectPath
7785
+ });
7786
+ res.end();
7787
+ return;
7788
+ }
7789
+ if (req.headers.accept?.includes("text/html")) {
7790
+ res.writeHead(404, {
7791
+ "Content-Type": "text/html"
7792
+ });
7793
+ res.end(
7794
+ `The server is configured with a base URL of ${base} - did you mean to visit <a href="${redirectPath}">${redirectPath}</a> instead?`
7795
+ );
7796
+ return;
7797
+ }
7798
+ res.writeHead(404, {
7799
+ "Content-Type": "text/plain"
7800
+ });
7801
+ res.end(
7802
+ `The server is configured with a base URL of ${base} - did you mean to visit ${redirectPath} instead?`
7803
+ );
7804
+ return;
7805
+ };
7806
+ };
7807
+ getHtmlFallbackMiddleware = ({ htmlFallback, distPath, callback, outputFileSystem }) => {
7808
+ return async (req, res, next) => {
7809
+ if (!maybeHTMLRequest(req) || "/favicon.ico" === req.url || htmlFallback !== "index") {
7810
+ return next();
7811
+ }
7812
+ const filePath = path8.join(distPath, "index.html");
7813
+ if (await isFileExists2(filePath, outputFileSystem)) {
7814
+ const newUrl = "/index.html";
7457
7815
  if (logger.level === "verbose") {
7458
7816
  logger.debug(
7459
- `${req.method} ${color9.gray(
7460
- `${req.url} ${color9.yellow("fallback")} to ${newUrl}`
7817
+ `${req.method} ${color10.gray(
7818
+ `${req.url} ${color10.yellow("fallback")} to ${newUrl}`
7461
7819
  )}`
7462
7820
  );
7463
7821
  }
@@ -7672,436 +8030,146 @@ var init_getDevMiddlewares = __esm({
7672
8030
  unshift: (...handlers) => before.unshift(...handlers),
7673
8031
  push: (...handlers) => after.push(...handlers)
7674
8032
  },
7675
- serverOptions
7676
- );
7677
- }
7678
- return { before, after };
7679
- };
7680
- applyDefaultMiddlewares = async ({
7681
- middlewares,
7682
- server,
7683
- compileMiddlewareAPI,
7684
- output,
7685
- pwd,
7686
- outputFileSystem
7687
- }) => {
7688
- const upgradeEvents = [];
7689
- if (server.compress) {
7690
- const { gzipMiddleware: gzipMiddleware2 } = await Promise.resolve().then(() => (init_gzipMiddleware(), gzipMiddleware_exports));
7691
- middlewares.push(gzipMiddleware2());
7692
- }
7693
- middlewares.push((req, res, next) => {
7694
- res.setHeader("Access-Control-Allow-Origin", "*");
7695
- const path22 = req.url ? url.parse(req.url).pathname : "";
7696
- if (path22?.includes("hot-update")) {
7697
- res.setHeader("Access-Control-Allow-Credentials", "false");
7698
- }
7699
- const confHeaders = server.headers;
7700
- if (confHeaders) {
7701
- for (const [key, value] of Object.entries(confHeaders)) {
7702
- res.setHeader(key, value);
7703
- }
7704
- }
7705
- next();
7706
- });
7707
- if (server.proxy) {
7708
- const { createProxyMiddleware: createProxyMiddleware2 } = await Promise.resolve().then(() => (init_proxy(), proxy_exports));
7709
- const { middlewares: proxyMiddlewares, upgrade } = await createProxyMiddleware2(server.proxy);
7710
- upgradeEvents.push(upgrade);
7711
- for (const middleware of proxyMiddlewares) {
7712
- middlewares.push(middleware);
7713
- }
7714
- }
7715
- const { default: launchEditorMiddleware } = await import("../compiled/launch-editor-middleware/index.js");
7716
- middlewares.push(["/__open-in-editor", launchEditorMiddleware()]);
7717
- if (compileMiddlewareAPI) {
7718
- middlewares.push(compileMiddlewareAPI.middleware);
7719
- upgradeEvents.push(
7720
- compileMiddlewareAPI.onUpgrade.bind(compileMiddlewareAPI)
7721
- );
7722
- middlewares.push((req, res, next) => {
7723
- if (req.url?.endsWith(".hot-update.json") && req.method !== "OPTIONS") {
7724
- res.statusCode = 404;
7725
- res.end();
7726
- } else {
7727
- next();
7728
- }
7729
- });
7730
- }
7731
- const distPath = isAbsolute4(output.distPath) ? output.distPath : join9(pwd, output.distPath);
7732
- if (compileMiddlewareAPI) {
7733
- middlewares.push(
7734
- getHtmlCompletionMiddleware({
7735
- distPath,
7736
- callback: compileMiddlewareAPI.middleware,
7737
- outputFileSystem
7738
- })
7739
- );
7740
- }
7741
- const publicDirs = normalizePublicDirs(server?.publicDir);
7742
- for (const publicDir of publicDirs) {
7743
- const { default: sirv } = await import("../compiled/sirv/index.js");
7744
- const { name } = publicDir;
7745
- const normalizedPath = isAbsolute4(name) ? name : join9(pwd, name);
7746
- const assetMiddleware = sirv(normalizedPath, {
7747
- etag: true,
7748
- dev: true
7749
- });
7750
- middlewares.push(assetMiddleware);
7751
- }
7752
- if (compileMiddlewareAPI) {
7753
- middlewares.push(
7754
- getHtmlFallbackMiddleware({
7755
- distPath,
7756
- callback: compileMiddlewareAPI.middleware,
7757
- htmlFallback: server.htmlFallback,
7758
- outputFileSystem
7759
- })
7760
- );
7761
- }
7762
- if (server.historyApiFallback) {
7763
- const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
7764
- const historyApiFallbackMiddleware = connectHistoryApiFallback(
7765
- server.historyApiFallback === true ? {} : server.historyApiFallback
7766
- );
7767
- middlewares.push(historyApiFallbackMiddleware);
7768
- compileMiddlewareAPI?.middleware && middlewares.push(compileMiddlewareAPI.middleware);
7769
- }
7770
- middlewares.push(faviconFallbackMiddleware);
7771
- middlewares.push((req, res, next) => {
7772
- if (req.method === "OPTIONS") {
7773
- res.statusCode = 204;
7774
- res.setHeader("Content-Length", "0");
7775
- res.end();
7776
- return;
7777
- }
7778
- next();
7779
- });
7780
- return {
7781
- onUpgrade: (...args) => {
7782
- for (const cb of upgradeEvents) {
7783
- cb(...args);
7784
- }
7785
- }
7786
- };
7787
- };
7788
- getMiddlewares = async (options) => {
7789
- const middlewares = [];
7790
- const { environments, compileMiddlewareAPI } = options;
7791
- if (logger.level === "verbose") {
7792
- middlewares.push(await getRequestLoggerMiddleware());
7793
- }
7794
- const { before, after } = applySetupMiddlewares(
7795
- options.dev,
7796
- environments,
7797
- compileMiddlewareAPI
7798
- );
7799
- middlewares.push(...before);
7800
- const { onUpgrade } = await applyDefaultMiddlewares({
7801
- ...options,
7802
- middlewares
7803
- });
7804
- middlewares.push(...after);
7805
- return {
7806
- close: async () => {
7807
- compileMiddlewareAPI?.close();
7808
- },
7809
- onUpgrade,
7810
- middlewares
7811
- };
7812
- };
7813
- }
7814
- });
7815
-
7816
- // src/server/helper.ts
7817
- import net from "net";
7818
- import os from "os";
7819
- import { posix as posix3 } from "path";
7820
- import color10 from "../compiled/picocolors/index.js";
7821
- function getURLMessages(urls, routes) {
7822
- if (routes.length === 1) {
7823
- return urls.map(
7824
- ({ label, url: url2 }) => ` ${`➜ ${label.padEnd(10)}`}${color10.cyan(
7825
- normalizeUrl(`${url2}${routes[0].pathname}`)
7826
- )}
7827
- `
7828
- ).join("");
7829
- }
7830
- let message = "";
7831
- const maxNameLength = Math.max(...routes.map((r) => r.entryName.length));
7832
- urls.forEach(({ label, url: url2 }, index) => {
7833
- if (index > 0) {
7834
- message += "\n";
7835
- }
7836
- message += ` ${`➜ ${label}`}
7837
- `;
7838
- for (const r of routes) {
7839
- message += ` ${color10.dim("-")} ${color10.dim(
7840
- r.entryName.padEnd(maxNameLength + 4)
7841
- )}${color10.cyan(normalizeUrl(`${url2}${r.pathname}`))}
7842
- `;
7843
- }
7844
- });
7845
- return message;
7846
- }
7847
- function printServerURLs({
7848
- urls: originalUrls,
7849
- port,
7850
- routes,
7851
- protocol,
7852
- printUrls
7853
- }) {
7854
- if (printUrls === false) {
7855
- return null;
7856
- }
7857
- let urls = originalUrls;
7858
- if (isFunction(printUrls)) {
7859
- const newUrls = printUrls({
7860
- urls: urls.map((item) => item.url),
7861
- port,
7862
- routes,
7863
- protocol
7864
- });
7865
- if (!newUrls) {
7866
- return null;
7867
- }
7868
- if (!Array.isArray(newUrls)) {
7869
- throw new Error(
7870
- `"server.printUrls" must return an array, but got ${typeof newUrls}.`
7871
- );
7872
- }
7873
- urls = newUrls.map((url2) => ({
7874
- url: url2,
7875
- label: getUrlLabel(url2)
7876
- }));
7877
- }
7878
- if (urls.length === 0 || routes.length === 0) {
7879
- return null;
7880
- }
7881
- const message = getURLMessages(urls, routes);
7882
- logger.log(message);
7883
- return message;
7884
- }
7885
- function getServerTerminator(server) {
7886
- let listened = false;
7887
- const pendingSockets = /* @__PURE__ */ new Set();
7888
- const onConnection = (socket) => {
7889
- pendingSockets.add(socket);
7890
- socket.on("close", () => {
7891
- pendingSockets.delete(socket);
7892
- });
7893
- };
7894
- server.on("connection", onConnection);
7895
- server.on("secureConnection", onConnection);
7896
- server.once("listening", () => {
7897
- listened = true;
7898
- });
7899
- return () => new Promise((resolve2, reject) => {
7900
- for (const socket of pendingSockets) {
7901
- socket.destroy();
7902
- }
7903
- if (listened) {
7904
- server.close((err) => err ? reject(err) : resolve2());
7905
- } else {
7906
- resolve2();
7907
- }
7908
- });
7909
- }
7910
- var normalizeUrl, formatPrefix, getRoutes, formatRoutes, getPort, getServerConfig, getIpv4Interfaces, isLoopbackHost, getHostInUrl, concatUrl, LOCAL_LABEL, NETWORK_LABEL, getUrlLabel, getAddressUrls, COMPILATION_ID_REGEX, getCompilationId;
7911
- var init_helper = __esm({
7912
- "src/server/helper.ts"() {
7913
- "use strict";
7914
- init_esm();
7915
- init_constants();
7916
- init_helpers();
7917
- init_logger();
7918
- normalizeUrl = (url2) => url2.replace(/([^:]\/)\/+/g, "$1");
7919
- formatPrefix = (input) => {
7920
- let prefix = input;
7921
- if (prefix?.startsWith("./")) {
7922
- prefix = prefix.replace("./", "");
7923
- }
7924
- if (!prefix) {
7925
- return "/";
7926
- }
7927
- const hasLeadingSlash = prefix.startsWith("/");
7928
- const hasTailSlash = prefix.endsWith("/");
7929
- return `${hasLeadingSlash ? "" : "/"}${prefix}${hasTailSlash ? "" : "/"}`;
7930
- };
7931
- getRoutes = (context) => {
7932
- return Object.values(context.environments).reduce(
7933
- (prev, environmentContext) => {
7934
- const { distPath, config } = environmentContext;
7935
- const distPrefix = posix3.relative(context.distPath, distPath);
7936
- const routes = formatRoutes(
7937
- environmentContext.htmlPaths,
7938
- posix3.join(distPrefix, config.output.distPath.html),
7939
- config.html.outputStructure
7940
- );
7941
- return prev.concat(...routes);
7942
- },
7943
- []
7944
- );
7945
- };
7946
- formatRoutes = (entry, prefix, outputStructure) => {
7947
- const formattedPrefix = formatPrefix(prefix);
7948
- return Object.keys(entry).map((entryName) => {
7949
- const isIndex = entryName === "index" && outputStructure !== "nested";
7950
- const displayName = isIndex ? "" : entryName;
7951
- return {
7952
- entryName,
7953
- pathname: formattedPrefix + displayName
7954
- };
7955
- }).sort((a) => a.entryName === "index" ? -1 : 1);
7956
- };
7957
- getPort = async ({
7958
- host,
7959
- port,
7960
- strictPort,
7961
- tryLimits = 20
7962
- }) => {
7963
- if (typeof port === "string") {
7964
- port = Number.parseInt(port, 10);
8033
+ serverOptions
8034
+ );
7965
8035
  }
7966
- if (strictPort) {
7967
- tryLimits = 1;
8036
+ return { before, after };
8037
+ };
8038
+ applyDefaultMiddlewares = async ({
8039
+ middlewares,
8040
+ server,
8041
+ compileMiddlewareAPI,
8042
+ output,
8043
+ pwd,
8044
+ outputFileSystem
8045
+ }) => {
8046
+ const upgradeEvents = [];
8047
+ if (server.compress) {
8048
+ const { gzipMiddleware: gzipMiddleware2 } = await Promise.resolve().then(() => (init_gzipMiddleware(), gzipMiddleware_exports));
8049
+ middlewares.push(gzipMiddleware2());
7968
8050
  }
7969
- const original = port;
7970
- let found = false;
7971
- let attempts = 0;
7972
- while (!found && attempts <= tryLimits) {
7973
- try {
7974
- await new Promise((resolve2, reject) => {
7975
- const server = net.createServer();
7976
- server.unref();
7977
- server.on("error", reject);
7978
- server.listen({ port, host }, () => {
7979
- found = true;
7980
- server.close(resolve2);
7981
- });
7982
- });
7983
- } catch (e) {
7984
- if (e.code !== "EADDRINUSE") {
7985
- throw e;
8051
+ middlewares.push((req, res, next) => {
8052
+ res.setHeader("Access-Control-Allow-Origin", "*");
8053
+ const path22 = req.url ? url.parse(req.url).pathname : "";
8054
+ if (path22?.includes("hot-update")) {
8055
+ res.setHeader("Access-Control-Allow-Credentials", "false");
8056
+ }
8057
+ const confHeaders = server.headers;
8058
+ if (confHeaders) {
8059
+ for (const [key, value] of Object.entries(confHeaders)) {
8060
+ res.setHeader(key, value);
7986
8061
  }
7987
- port++;
7988
- attempts++;
7989
8062
  }
7990
- }
7991
- if (port !== original) {
7992
- if (strictPort) {
7993
- throw new Error(
7994
- `Port "${original}" is occupied, please choose another one.`
7995
- );
8063
+ next();
8064
+ });
8065
+ if (server.proxy) {
8066
+ const { createProxyMiddleware: createProxyMiddleware2 } = await Promise.resolve().then(() => (init_proxy(), proxy_exports));
8067
+ const { middlewares: proxyMiddlewares, upgrade } = await createProxyMiddleware2(server.proxy);
8068
+ upgradeEvents.push(upgrade);
8069
+ for (const middleware of proxyMiddlewares) {
8070
+ middlewares.push(middleware);
7996
8071
  }
7997
8072
  }
7998
- return port;
7999
- };
8000
- getServerConfig = async ({
8001
- config
8002
- }) => {
8003
- const host = config.server.host || DEFAULT_DEV_HOST;
8004
- const originalPort = config.server.port || DEFAULT_PORT;
8005
- const port = await getPort({
8006
- host,
8007
- port: originalPort,
8008
- strictPort: config.server.strictPort || false
8009
- });
8010
- const https = Boolean(config.server.https) || false;
8011
- const portTip = port !== originalPort ? `Port ${originalPort} is in use, ${color10.yellow(`using port ${port}.`)}` : void 0;
8012
- return {
8013
- port,
8014
- host,
8015
- https,
8016
- portTip
8017
- };
8018
- };
8019
- getIpv4Interfaces = () => {
8020
- const interfaces = os.networkInterfaces();
8021
- const ipv4Interfaces = /* @__PURE__ */ new Map();
8022
- for (const key of Object.keys(interfaces)) {
8023
- for (const detail of interfaces[key]) {
8024
- const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
8025
- if (detail.family === familyV4Value && !ipv4Interfaces.has(detail.address)) {
8026
- ipv4Interfaces.set(detail.address, detail);
8073
+ if (server.base && server.base !== "/") {
8074
+ middlewares.push(getBaseMiddleware({ base: server.base }));
8075
+ }
8076
+ const { default: launchEditorMiddleware } = await import("../compiled/launch-editor-middleware/index.js");
8077
+ middlewares.push(["/__open-in-editor", launchEditorMiddleware()]);
8078
+ if (compileMiddlewareAPI) {
8079
+ middlewares.push(compileMiddlewareAPI.middleware);
8080
+ upgradeEvents.push(
8081
+ compileMiddlewareAPI.onUpgrade.bind(compileMiddlewareAPI)
8082
+ );
8083
+ middlewares.push((req, res, next) => {
8084
+ if (req.url?.endsWith(".hot-update.json") && req.method !== "OPTIONS") {
8085
+ res.statusCode = 404;
8086
+ res.end();
8087
+ } else {
8088
+ next();
8027
8089
  }
8028
- }
8090
+ });
8029
8091
  }
8030
- return Array.from(ipv4Interfaces.values());
8031
- };
8032
- isLoopbackHost = (host) => {
8033
- const loopbackHosts = [
8034
- "localhost",
8035
- "127.0.0.1",
8036
- "::1",
8037
- "0000:0000:0000:0000:0000:0000:0000:0001"
8038
- ];
8039
- return loopbackHosts.includes(host);
8040
- };
8041
- getHostInUrl = (host) => {
8042
- if (net.isIPv6(host)) {
8043
- return host === "::" ? "[::1]" : `[${host}]`;
8092
+ const distPath = isAbsolute4(output.distPath) ? output.distPath : join9(pwd, output.distPath);
8093
+ if (compileMiddlewareAPI) {
8094
+ middlewares.push(
8095
+ getHtmlCompletionMiddleware({
8096
+ distPath,
8097
+ callback: compileMiddlewareAPI.middleware,
8098
+ outputFileSystem
8099
+ })
8100
+ );
8044
8101
  }
8045
- return host;
8046
- };
8047
- concatUrl = ({
8048
- host,
8049
- port,
8050
- protocol
8051
- }) => `${protocol}://${host}:${port}`;
8052
- LOCAL_LABEL = "Local: ";
8053
- NETWORK_LABEL = "Network: ";
8054
- getUrlLabel = (url2) => {
8055
- try {
8056
- const { host } = new URL(url2);
8057
- return isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL;
8058
- } catch (err) {
8059
- return NETWORK_LABEL;
8102
+ const publicDirs = normalizePublicDirs(server?.publicDir);
8103
+ for (const publicDir of publicDirs) {
8104
+ const { default: sirv } = await import("../compiled/sirv/index.js");
8105
+ const { name } = publicDir;
8106
+ const normalizedPath = isAbsolute4(name) ? name : join9(pwd, name);
8107
+ const assetMiddleware = sirv(normalizedPath, {
8108
+ etag: true,
8109
+ dev: true
8110
+ });
8111
+ middlewares.push(assetMiddleware);
8060
8112
  }
8061
- };
8062
- getAddressUrls = ({
8063
- protocol = "http",
8064
- port,
8065
- host
8066
- }) => {
8067
- if (host && host !== DEFAULT_DEV_HOST) {
8068
- return [
8069
- {
8070
- label: isLoopbackHost(host) ? LOCAL_LABEL : NETWORK_LABEL,
8071
- url: concatUrl({
8072
- port,
8073
- host: getHostInUrl(host),
8074
- protocol
8075
- })
8076
- }
8077
- ];
8113
+ if (compileMiddlewareAPI) {
8114
+ middlewares.push(
8115
+ getHtmlFallbackMiddleware({
8116
+ distPath,
8117
+ callback: compileMiddlewareAPI.middleware,
8118
+ htmlFallback: server.htmlFallback,
8119
+ outputFileSystem
8120
+ })
8121
+ );
8078
8122
  }
8079
- const ipv4Interfaces = getIpv4Interfaces();
8080
- const addressUrls = [];
8081
- let hasLocalUrl = false;
8082
- for (const detail of ipv4Interfaces) {
8083
- if (isLoopbackHost(detail.address) || detail.internal) {
8084
- if (hasLocalUrl) {
8085
- continue;
8123
+ if (server.historyApiFallback) {
8124
+ const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
8125
+ const historyApiFallbackMiddleware = connectHistoryApiFallback(
8126
+ server.historyApiFallback === true ? {} : server.historyApiFallback
8127
+ );
8128
+ middlewares.push(historyApiFallbackMiddleware);
8129
+ compileMiddlewareAPI?.middleware && middlewares.push(compileMiddlewareAPI.middleware);
8130
+ }
8131
+ middlewares.push(faviconFallbackMiddleware);
8132
+ middlewares.push((req, res, next) => {
8133
+ if (req.method === "OPTIONS") {
8134
+ res.statusCode = 204;
8135
+ res.setHeader("Content-Length", "0");
8136
+ res.end();
8137
+ return;
8138
+ }
8139
+ next();
8140
+ });
8141
+ return {
8142
+ onUpgrade: (...args) => {
8143
+ for (const cb of upgradeEvents) {
8144
+ cb(...args);
8086
8145
  }
8087
- addressUrls.push({
8088
- label: LOCAL_LABEL,
8089
- url: concatUrl({ host: "localhost", port, protocol })
8090
- });
8091
- hasLocalUrl = true;
8092
- } else {
8093
- addressUrls.push({
8094
- label: NETWORK_LABEL,
8095
- url: concatUrl({ host: detail.address, port, protocol })
8096
- });
8097
8146
  }
8098
- }
8099
- return addressUrls;
8147
+ };
8100
8148
  };
8101
- COMPILATION_ID_REGEX = /[^a-zA-Z0-9_-]/g;
8102
- getCompilationId = (compiler) => {
8103
- const uniqueName = compiler.options.output.uniqueName ?? "";
8104
- return `${compiler.name ?? ""}_${uniqueName.replace(COMPILATION_ID_REGEX, "_")}`;
8149
+ getMiddlewares = async (options) => {
8150
+ const middlewares = [];
8151
+ const { environments, compileMiddlewareAPI } = options;
8152
+ if (logger.level === "verbose") {
8153
+ middlewares.push(await getRequestLoggerMiddleware());
8154
+ }
8155
+ const { before, after } = applySetupMiddlewares(
8156
+ options.dev,
8157
+ environments,
8158
+ compileMiddlewareAPI
8159
+ );
8160
+ middlewares.push(...before);
8161
+ const { onUpgrade } = await applyDefaultMiddlewares({
8162
+ ...options,
8163
+ middlewares
8164
+ });
8165
+ middlewares.push(...after);
8166
+ return {
8167
+ close: async () => {
8168
+ compileMiddlewareAPI?.close();
8169
+ },
8170
+ onUpgrade,
8171
+ middlewares
8172
+ };
8105
8173
  };
8106
8174
  }
8107
8175
  });
@@ -8678,6 +8746,7 @@ var init_compilerDevMiddleware = __esm({
8678
8746
  init_esm();
8679
8747
  init_path();
8680
8748
  init_devMiddleware();
8749
+ init_helper();
8681
8750
  init_socketServer();
8682
8751
  noop = () => {
8683
8752
  };
@@ -8714,7 +8783,10 @@ var init_compilerDevMiddleware = __esm({
8714
8783
  });
8715
8784
  }
8716
8785
  setupDevMiddleware(devMiddleware, publicPaths) {
8717
- const { devConfig, serverConfig } = this;
8786
+ const {
8787
+ devConfig,
8788
+ serverConfig: { headers, base }
8789
+ } = this;
8718
8790
  const callbacks = {
8719
8791
  onInvalid: (compilationId) => {
8720
8792
  this.socketServer.sockWrite({
@@ -8728,7 +8800,7 @@ var init_compilerDevMiddleware = __esm({
8728
8800
  };
8729
8801
  const clientPaths = getClientPaths(devConfig);
8730
8802
  const middleware = devMiddleware({
8731
- headers: serverConfig.headers,
8803
+ headers,
8732
8804
  publicPath: "/",
8733
8805
  stats: false,
8734
8806
  callbacks,
@@ -8741,7 +8813,9 @@ var init_compilerDevMiddleware = __esm({
8741
8813
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#weak_validation
8742
8814
  etag: "weak"
8743
8815
  });
8744
- const assetPrefixes = publicPaths.map(pathnameParse);
8816
+ const assetPrefixes = publicPaths.map(pathnameParse).map(
8817
+ (prefix) => base && base !== "/" ? stripBase(prefix, base) : prefix
8818
+ );
8745
8819
  const warp = async (req, res, next) => {
8746
8820
  const { url: url2 } = req;
8747
8821
  const assetPrefix = url2 && assetPrefixes.find((prefix) => url2.startsWith(prefix));
@@ -10973,13 +11047,16 @@ var init_define = __esm({
10973
11047
  setup(api) {
10974
11048
  api.modifyBundlerChain((chain, { CHAIN_ID: CHAIN_ID2, bundler, environment }) => {
10975
11049
  const { config } = environment;
11050
+ const baseUrl = JSON.stringify(config.server.base);
10976
11051
  const builtinVars = {
10977
11052
  "import.meta.env.MODE": JSON.stringify(config.mode),
10978
11053
  "import.meta.env.DEV": config.mode === "development",
10979
11054
  "import.meta.env.PROD": config.mode === "production",
11055
+ "import.meta.env.BASE_URL": baseUrl,
10980
11056
  "process.env.ASSET_PREFIX": JSON.stringify(
10981
11057
  getPublicPathFromChain(chain, false)
10982
- )
11058
+ ),
11059
+ "process.env.BASE_URL": baseUrl
10983
11060
  };
10984
11061
  chain.plugin(CHAIN_ID2.PLUGIN.DEFINE).use(bundler.DefinePlugin, [
10985
11062
  { ...builtinVars, ...config.source.define }
@@ -13010,7 +13087,7 @@ var init_prodServer = __esm({
13010
13087
  await this.applyDefaultMiddlewares();
13011
13088
  }
13012
13089
  async applyDefaultMiddlewares() {
13013
- const { headers, proxy, historyApiFallback, compress } = this.options.serverConfig;
13090
+ const { headers, proxy, historyApiFallback, compress, base } = this.options.serverConfig;
13014
13091
  if (logger.level === "verbose") {
13015
13092
  this.middlewares.use(await getRequestLoggerMiddleware());
13016
13093
  }
@@ -13039,6 +13116,9 @@ var init_prodServer = __esm({
13039
13116
  }
13040
13117
  this.app.on("upgrade", upgrade);
13041
13118
  }
13119
+ if (base && base !== "/") {
13120
+ this.middlewares.use(getBaseMiddleware({ base }));
13121
+ }
13042
13122
  this.applyStaticAssetMiddleware();
13043
13123
  if (historyApiFallback) {
13044
13124
  const { default: connectHistoryApiFallback } = await import("../compiled/connect-history-api-fallback/index.js");
@@ -13386,7 +13466,7 @@ var init_init = __esm({
13386
13466
  import { existsSync } from "fs";
13387
13467
  import color16 from "../compiled/picocolors/index.js";
13388
13468
  function runCli() {
13389
- program.name("rsbuild").usage("<command> [options]").version("1.0.9");
13469
+ program.name("rsbuild").usage("<command> [options]").version("1.0.10");
13390
13470
  const devCommand = program.command("dev");
13391
13471
  const buildCommand = program.command("build");
13392
13472
  const previewCommand = program.command("preview");
@@ -13496,6 +13576,7 @@ var init_commands = __esm({
13496
13576
  });
13497
13577
 
13498
13578
  // src/cli/prepare.ts
13579
+ import nodeModule from "module";
13499
13580
  function initNodeEnv() {
13500
13581
  if (!process.env.NODE_ENV) {
13501
13582
  const command = process.argv[2];
@@ -13504,11 +13585,18 @@ function initNodeEnv() {
13504
13585
  }
13505
13586
  function prepareCli() {
13506
13587
  initNodeEnv();
13588
+ const { enableCompileCache } = nodeModule;
13589
+ if (enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) {
13590
+ try {
13591
+ enableCompileCache();
13592
+ } catch {
13593
+ }
13594
+ }
13507
13595
  const { npm_execpath } = process.env;
13508
13596
  if (!npm_execpath || npm_execpath.includes("npx-cli.js") || npm_execpath.includes(".bun")) {
13509
13597
  console.log();
13510
13598
  }
13511
- logger.greet(` ${`Rsbuild v${"1.0.9"}`}
13599
+ logger.greet(` ${`Rsbuild v${"1.0.10"}`}
13512
13600
  `);
13513
13601
  }
13514
13602
  var init_prepare = __esm({
@@ -13579,7 +13667,7 @@ init_mergeConfig();
13579
13667
  init_helpers();
13580
13668
  init_constants();
13581
13669
  import { rspack as rspack10 } from "@rspack/core";
13582
- var version = "1.0.9";
13670
+ var version = "1.0.10";
13583
13671
  export {
13584
13672
  PLUGIN_CSS_NAME,
13585
13673
  PLUGIN_SWC_NAME,