Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"singleQuote": true
"singleQuote": true,
"plugins": ["@prettier/plugin-oxc"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
},
"devDependencies": {
"@biomejs/biome": "^2.3.2",
"@prettier/plugin-oxc": "^0.0.4",
"@rsbuild/config": "workspace:*",
"@rslint/core": "^0.1.13",
"@rstest/core": "^0.6.1",
Expand Down
7 changes: 7 additions & 0 deletions packages/core/rslib.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,11 @@ export default defineConfig({
},
},
],
tools: {
rspack: {
experiments: {
deferImport: true,
},
},
},
});
2 changes: 1 addition & 1 deletion packages/core/src/createContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export async function updateEnvironmentContext(
const { entry = {}, tsconfigPath } = config.source;
const htmlPaths = getEnvironmentHTMLPaths(entry, config);
const webSocketToken =
context.action === 'dev' ? await hash(context.rootPath + name) : '';
context.action === 'dev' ? hash(context.rootPath + name) : '';

const environmentContext: EnvironmentContext = {
index,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import defer * as crypto from 'node:crypto';
import deepmerge from 'deepmerge';
import RspackChain from '../../compiled/rspack-chain';
import type {
Expand Down Expand Up @@ -210,8 +211,7 @@ export const isTTY = (type: 'stdin' | 'stdout' = 'stdout'): boolean => {
);
};

export async function hash(data: string): Promise<string> {
const crypto = await import('node:crypto');
export function hash(data: string): string {
// Available in Node.js v20.12.0
// faster than `crypto.createHash()` when hashing a smaller amount of data (<= 5MB)
if (crypto.hash) {
Expand Down
13 changes: 8 additions & 5 deletions packages/core/src/loadConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'node:fs';
import { isAbsolute, join } from 'node:path';
import { pathToFileURL } from 'node:url';
import defer * as jiti from 'jiti';
import { __filename } from './constants';
import { color, getNodeEnv, isObject } from './helpers';
import { logger } from './logger';
Expand Down Expand Up @@ -167,8 +168,7 @@ export async function loadConfig({

if (configExport === undefined) {
try {
const { createJiti } = await import('jiti');
const jiti = createJiti(__filename, {
const instance = jiti.createJiti(__filename, {
// disable require cache to support restart CLI and read the new config
moduleCache: false,
interopDefault: true,
Expand All @@ -177,9 +177,12 @@ export async function loadConfig({
nativeModules: ['@rspack/core', 'typescript'],
});

configExport = await jiti.import<RsbuildConfigExport>(configFilePath, {
default: true,
});
configExport = await instance.import<RsbuildConfigExport>(
configFilePath,
{
default: true,
},
);
} catch (err) {
logger.error(
`Failed to load file with jiti: ${color.dim(configFilePath)}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/plugins/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const pluginCache = (): RsbuildPlugin => ({

// set cache name to avoid cache conflicts between different environments
const cacheVersion = useDigest
? `${environment.name}-${env}-${await hash(JSON.stringify(cacheConfig.cacheDigest))}`
? `${environment.name}-${env}-${hash(JSON.stringify(cacheConfig.cacheDigest))}`
: `${environment.name}-${env}`;

if (bundlerType === 'rspack') {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/server/cliShortcuts.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import defer * as readline from 'node:readline';
import { color, isTTY } from '../helpers';
import { logger } from '../logger';
import type { CliShortcut, NormalizedConfig } from '../types/config';
Expand Down Expand Up @@ -78,8 +79,7 @@ export async function setupCliShortcuts({
);
}

const { createInterface } = await import('node:readline');
const rl = createInterface({
const rl = readline.createInterface({
input: process.stdin,
});

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/server/devServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ export async function createDevServer<

const httpServer = middlewareMode
? null
: await createHttpServer({
: createHttpServer({
serverConfig: config.server,
middlewares,
});
Expand Down
11 changes: 5 additions & 6 deletions packages/core/src/server/helper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IncomingMessage, Server } from 'node:http';
import type { Http2SecureServer } from 'node:http2';
import type { Socket } from 'node:net';
import defer * as net from 'node:net';
import os from 'node:os';
import { posix, relative, sep } from 'node:path';
import { DEFAULT_DEV_HOST } from '../constants';
Expand Down Expand Up @@ -270,7 +271,6 @@ export const getPort = async ({
tryLimits = 1;
}

const { createServer } = await import('node:net');
const original = port;

let found = false;
Expand All @@ -279,7 +279,7 @@ export const getPort = async ({
while (!found && attempts <= tryLimits) {
try {
await new Promise((resolve, reject) => {
const server = createServer();
const server = net.createServer();
server.unref();
server.on('error', reject);
server.listen({ port, host }, () => {
Expand Down Expand Up @@ -379,13 +379,12 @@ const isLoopbackHost = (host: string) => {
return loopbackHosts.has(host);
};

export const getHostInUrl = async (host: string): Promise<string> => {
export const getHostInUrl = (host: string): string => {
if (host === DEFAULT_DEV_HOST) {
return 'localhost';
}

const { isIPv6 } = await import('node:net');
if (isIPv6(host)) {
if (net.isIPv6(host)) {
return host === '::' ? '[::1]' : `[${host}]`;
}
return host;
Expand Down Expand Up @@ -427,7 +426,7 @@ export const getAddressUrls = async ({
if (host && host !== DEFAULT_DEV_HOST) {
const url = concatUrl({
port,
host: await getHostInUrl(host),
host: getHostInUrl(host),
protocol,
});
return [
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/server/hmrFallback.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import defer * as dns from 'node:dns';
import { isWildcardHost } from './helper';

/**
Expand All @@ -8,10 +9,9 @@ import { isWildcardHost } from './helper';
* This helps detect cases where IPv4/IPv6 resolution might vary.
*/
async function getLocalhostResolvedAddress(): Promise<string | undefined> {
const { promises: dns } = await import('node:dns');
const [defaultLookup, explicitLookup] = await Promise.all([
dns.lookup('localhost'),
dns.lookup('localhost', { verbatim: true }),
dns.promises.lookup('localhost'),
dns.promises.lookup('localhost', { verbatim: true }),
]);
const match =
defaultLookup.family === explicitLookup.family &&
Expand Down
16 changes: 8 additions & 8 deletions packages/core/src/server/httpServer.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import type { Server } from 'node:http';
import defer * as http from 'node:http';
import type { Http2SecureServer } from 'node:http2';
import defer * as http2 from 'node:http2';
import defer * as https from 'node:https';
import type { Connect, ServerConfig } from '../types';

export const createHttpServer = async ({
export const createHttpServer = ({
serverConfig,
middlewares,
}: {
serverConfig: ServerConfig;
middlewares: Connect.Server;
}): Promise<Http2SecureServer | Server> => {
}): Http2SecureServer | Server => {
if (serverConfig.https) {
// http-proxy does not supports http2
if (serverConfig.proxy) {
const { createServer } = await import('node:https');
return createServer(serverConfig.https, middlewares);
return https.createServer(serverConfig.https, middlewares);
}

const { createSecureServer } = await import('node:http2');
return createSecureServer(
return http2.createSecureServer(
{
allowHTTP1: true,
// increase the maximum memory (MiB)
Expand All @@ -29,6 +30,5 @@ export const createHttpServer = async ({
);
}

const { createServer } = await import('node:http');
return createServer(middlewares);
return http.createServer(middlewares);
};
8 changes: 4 additions & 4 deletions packages/core/src/server/open.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import defer * as childProcess from 'node:child_process';
import defer * as nodeUtil from 'node:util';
import { STATIC_PATH } from '../constants';
import { castArray, color } from '../helpers';
import { canParse } from '../helpers/url';
Expand Down Expand Up @@ -64,9 +66,7 @@ async function openBrowser(url: string): Promise<boolean> {
// a Chromium browser with AppleScript. This lets us reuse an
// existing tab when possible instead of creating a new one.
if (shouldTryAppleScript(browser, browserArgs)) {
const { exec } = await import('node:child_process');
const { promisify } = await import('node:util');
const execAsync = promisify(exec);
const execAsync = nodeUtil.promisify(childProcess.exec);

/**
* Find the browser that is currently running
Expand Down Expand Up @@ -203,7 +203,7 @@ export async function open({

const urls: string[] = [];
const protocol = https ? 'https' : 'http';
const host = await getHostInUrl(config.server.host);
const host = getHostInUrl(config.server.host);
const baseUrl = `${protocol}://${host}:${port}`;

if (!targets.length) {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/server/prodServer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Server } from 'node:http';
import type { Http2SecureServer } from 'node:http2';
import defer * as zlib from 'node:zlib';
import { getPathnameFromUrl } from '../helpers/path';
import { requireCompiledPackage } from '../helpers/vendors';
import { isVerbose, logger } from '../logger';
Expand Down Expand Up @@ -104,11 +105,10 @@ export class RsbuildProdServer {
// compression is placed after proxy middleware to avoid breaking SSE (Server-Sent Events),
// but before other middlewares to ensure responses are properly compressed
if (compress) {
const { constants } = await import('node:zlib');
this.middlewares.use(
gzipMiddleware({
// simulates the common gzip compression rates
level: constants.Z_DEFAULT_COMPRESSION,
level: zlib.constants.Z_DEFAULT_COMPRESSION,
...(typeof compress === 'object' ? compress : undefined),
}),
);
Expand Down Expand Up @@ -201,7 +201,7 @@ export async function startProdServer(

await context.hooks.onBeforeStartProdServer.callBatch();

const httpServer = await createHttpServer({
const httpServer = createHttpServer({
serverConfig,
middlewares: server.middlewares,
});
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/server/runner/asModule.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Module, ModuleLinker, SyntheticModule } from 'node:vm';
import defer * as vm from 'node:vm';

export const asModule = async (
something: Record<string, any>,
context: Record<string, any>,
unlinked?: boolean,
): Promise<Module | SyntheticModule> => {
const { Module, SyntheticModule } = await import('node:vm');
const { Module, SyntheticModule } = vm;

if (something instanceof Module) {
return something;
Expand Down
Loading
Loading