Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion e2e/cases/html/favicon/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ for (const filename of ['favicon.ico', 'favicon.png', 'favicon.svg']) {
const rsbuild = await build({
config: {
server: {
publicDir: [{ name: publicPath }],
publicDir: { name: publicPath },
},
},
});
Expand Down
45 changes: 31 additions & 14 deletions packages/core/src/defaultConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRequire } from 'node:module';
import { dirname, join } from 'node:path';
import { dirname, isAbsolute, join } from 'node:path';
import {
ASSETS_DIST_DIR,
CSS_DIST_DIR,
Expand Down Expand Up @@ -301,11 +301,15 @@ export const withDefaultConfig = async (
*/
export const normalizeConfigStructure = (
config: RsbuildConfig,
rootPath: string,
): RsbuildConfig => {
const { dev, output } = config;

config.server ||= {};
config.server.publicDir = normalizePublicDirs(config.server.publicDir);
config.server.publicDir = normalizePublicDirs(
rootPath,
config.server.publicDir,
);

if (typeof output?.distPath === 'string') {
config = {
Expand Down Expand Up @@ -334,7 +338,10 @@ export const normalizeConfigStructure = (
* Normalizes the user configuration by merging it with defaults and ensuring
* consistent structure.
*/
export const normalizeConfig = (config: RsbuildConfig): NormalizedConfig => {
export const normalizeConfig = (
config: RsbuildConfig,
rootPath: string,
): NormalizedConfig => {
const getMode = (): RsbuildMode => {
if (config.mode) {
return config.mode;
Expand All @@ -350,21 +357,22 @@ export const normalizeConfig = (config: RsbuildConfig): NormalizedConfig => {
...createDefaultConfig(),
mode: getMode(),
},
normalizeConfigStructure(config),
normalizeConfigStructure(config, rootPath),
) as Required<RsbuildConfig>;

return mergedConfig as unknown as NormalizedConfig;
};

const normalizePublicDirs = (
rootPath: string,
publicDir?: PublicDir,
): Required<PublicDirOptions>[] => {
if (publicDir === false) {
return [];
}

const defaultConfig: Required<PublicDirOptions> = {
name: 'public',
name: join(rootPath, 'public'),
copyOnBuild: 'auto',
watch: false,
};
Expand All @@ -374,17 +382,26 @@ const normalizePublicDirs = (
return [defaultConfig];
}

if (Array.isArray(publicDir)) {
return publicDir.map((options) => ({
const mergeWithDefault = (options: PublicDirOptions) => {
if (options.name === '') {
throw new Error(
'[rsbuild:config] `publicDir.name` cannot be empty string.',
);
}

const merged = {
...defaultConfig,
...options,
}));
};
if (!isAbsolute(merged.name)) {
merged.name = join(rootPath, merged.name);
}
return merged;
};

if (Array.isArray(publicDir)) {
return publicDir.map((options) => mergeWithDefault(options));
}

return [
{
...defaultConfig,
...publicDir,
},
];
return [mergeWithDefault(publicDir)];
};
9 changes: 1 addition & 8 deletions packages/core/src/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,9 @@ export const pluginHtml = (context: InternalContext): RsbuildPlugin => ({
return defaultFavicon;
}

const { rootPath } = api.context;
const { publicDir } = api.getNormalizedConfig().server;
const extensions = ['ico', 'png', 'svg'];
const publicDirs = Array.from(
new Set(
publicDir.map(({ name }) =>
isAbsolute(name) ? name : path.join(rootPath, name),
),
),
);
const publicDirs = Array.from(new Set(publicDir.map(({ name }) => name)));

const faviconPaths: string[] = [];
for (const publicDir of publicDirs) {
Expand Down
15 changes: 5 additions & 10 deletions packages/core/src/plugins/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import fs from 'node:fs';
import { isAbsolute, join } from 'node:path';
import { isDeno } from '../constants';
import { color } from '../helpers';
import { dedupeNestedPaths } from '../helpers/path';
Expand Down Expand Up @@ -31,16 +30,12 @@ export const pluginServer = (): RsbuildPlugin => ({
}
const config = api.getNormalizedConfig();

for (const { name, copyOnBuild } of config.server.publicDir) {
if (copyOnBuild === false || !name) {
for (const { name: publicDir, copyOnBuild } of config.server.publicDir) {
if (copyOnBuild === false) {
continue;
}

const normalizedPath = isAbsolute(name)
? name
: join(api.context.rootPath, name);

if (!fs.existsSync(normalizedPath)) {
if (!fs.existsSync(publicDir)) {
continue;
}

Expand All @@ -67,7 +62,7 @@ export const pluginServer = (): RsbuildPlugin => ({
});
}

return fs.promises.cp(normalizedPath, distPath, {
return fs.promises.cp(publicDir, distPath, {
recursive: true,
// dereference symlinks
dereference: true,
Expand All @@ -76,7 +71,7 @@ export const pluginServer = (): RsbuildPlugin => ({
);
} catch (err) {
if (err instanceof Error) {
err.message = `Failed to copy public directory '${color.yellow(normalizedPath)}' to output directory. To disable public directory copying, set \`${color.cyan('server.publicDir: false')}\` in your config.\n${err.message}`;
err.message = `Failed to copy public directory '${color.yellow(publicDir)}' to output directory. To disable public directory copying, set \`${color.cyan('server.publicDir: false')}\` in your config.\n${err.message}`;
}

throw err;
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/provider/initConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const initEnvironmentConfigs = (
...baseConfig,
dev: pick(dev, allowedEnvironmentDevKeys),
},
normalizeConfigStructure(config),
normalizeConfigStructure(config, rootPath),
),
} as unknown as MergedEnvironmentConfig;

Expand Down Expand Up @@ -247,7 +247,10 @@ export async function initRsbuildConfig({

await modifyRsbuildConfig(context);

const normalizedBaseConfig = normalizeConfig(context.config);
const normalizedBaseConfig = normalizeConfig(
context.config,
context.rootPath,
);
const environments: Record<string, NormalizedEnvironmentConfig> = {};

const mergedEnvironments = initEnvironmentConfigs(
Expand Down
8 changes: 1 addition & 7 deletions packages/core/src/server/devMiddlewares.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { isAbsolute, join } from 'node:path';
import { castArray, pick } from '../helpers';
import { isMultiCompiler } from '../helpers/compiler';
import { requireCompiledPackage } from '../helpers/vendors';
Expand Down Expand Up @@ -34,7 +33,6 @@ export type RsbuildDevMiddlewareOptions = {
* Callbacks returned by the `onBeforeStartDevServer` hook.
*/
postCallbacks: (() => void)[];
pwd: string;
};

const applySetupMiddlewares = (
Expand Down Expand Up @@ -72,7 +70,6 @@ const applyDefaultMiddlewares = ({
context,
devServerAPI,
middlewares,
pwd,
postCallbacks,
}: RsbuildDevMiddlewareOptions & {
middlewares: Middlewares;
Expand Down Expand Up @@ -202,13 +199,10 @@ const applyDefaultMiddlewares = ({

for (const { name } of server.publicDir) {
const sirv = requireCompiledPackage('sirv');
const normalizedPath = isAbsolute(name) ? name : join(pwd, name);

const servePublicDirMiddleware = sirv(normalizedPath, {
const servePublicDirMiddleware = sirv(name, {
etag: true,
dev: true,
});

middlewares.push(servePublicDirMiddleware);
}

Expand Down
1 change: 0 additions & 1 deletion packages/core/src/server/devServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,6 @@ export async function createDevServer<
});

devMiddlewares = getDevMiddlewares({
pwd: root,
buildManager,
config,
devServerAPI,
Expand Down
18 changes: 9 additions & 9 deletions packages/core/tests/__snapshots__/environments.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ exports[`environment config > should normalize environment config correctly 1`]
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -281,7 +281,7 @@ exports[`environment config > should normalize environment config correctly 2`]
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -439,7 +439,7 @@ exports[`environment config > should print environment config when inspect confi
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -593,7 +593,7 @@ exports[`environment config > should print environment config when inspect confi
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -767,7 +767,7 @@ exports[`environment config > should support modify environment config by api.mo
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -922,7 +922,7 @@ exports[`environment config > should support modify environment config by api.mo
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -1077,7 +1077,7 @@ exports[`environment config > should support modify environment config by api.mo
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -1234,7 +1234,7 @@ exports[`environment config > should support modify single environment config by
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down Expand Up @@ -1389,7 +1389,7 @@ exports[`environment config > should support modify single environment config by
"publicDir": [
{
"copyOnBuild": "auto",
"name": "public",
"name": "<ROOT>/public",
"watch": false,
},
],
Expand Down
Loading