Skip to content

Commit

Permalink
feat: support server.base configuration (#3542)
Browse files Browse the repository at this point in the history
Co-authored-by: neverland <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 2, 2024
1 parent dbad5d5 commit c681381
Show file tree
Hide file tree
Showing 39 changed files with 626 additions and 29 deletions.
133 changes: 133 additions & 0 deletions e2e/cases/server/base/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { build, dev, proxyConsole } from '@e2e/helper';
import { expect, test } from '@playwright/test';

test('server.base when dev', async ({ page }) => {
const { logs, restore } = proxyConsole('log');

const rsbuild = await dev({
cwd: __dirname,
page,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
printUrls: true,
base: '/base',
},
},
});

// should redirect root visit to based url
await expect(page.locator('#test')).toHaveText('Hello Rsbuild!');

expect(page.url().includes('/base/')).toBeTruthy();

// should define `process.env.BASE_URL` correctly
await expect(page.locator('#public-base-path')).toHaveText('/base');

// should print url with base path
const baseUrlLog = logs.find(
(log) =>
log.includes('Local:') && log.includes(`localhost:${rsbuild.port}/base`),
);

expect(baseUrlLog).toBeTruthy();

// should visit base url correctly
await page.goto(`http://localhost:${rsbuild.port}/base`);

await expect(page.locator('#test')).toHaveText('Hello Rsbuild!');

// should 404 when visit resource without base prefix
const indexRes = await page.goto(`http://localhost:${rsbuild.port}/a`);
expect(indexRes?.status()).toBe(404);
expect(await page.content()).toContain(
'The server is configured with a base URL of /base',
);

// should visit public dir correctly with base prefix
await page.goto(`http://localhost:${rsbuild.port}/base/aaa.txt`);

expect(await page.content()).toContain('aaaa');

restore();
await rsbuild.close();
});

test('server.base when build & preview', async ({ page }) => {
const { logs, restore } = proxyConsole('log');

const rsbuild = await build({
cwd: __dirname,
page,
runServer: true,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
printUrls: true,
base: '/base',
},
},
});

// should redirect root visit to based url
await expect(page.locator('#test')).toHaveText('Hello Rsbuild!');

expect(page.url().includes('/base/')).toBeTruthy();

// should define `process.env.BASE_URL` correctly
await expect(page.locator('#public-base-path')).toHaveText('/base');

// should print url with base path
const baseUrlLog = logs.find(
(log) =>
log.includes('Local:') && log.includes(`localhost:${rsbuild.port}/base`),
);

expect(baseUrlLog).toBeTruthy();

// should visit base url correctly
await page.goto(`http://localhost:${rsbuild.port}/base`);

await expect(page.locator('#test')).toHaveText('Hello Rsbuild!');

// should 404 when visit resource without base prefix
const indexRes = await page.goto(`http://localhost:${rsbuild.port}/a`);
expect(indexRes?.status()).toBe(404);
expect(await page.content()).toContain(
'The server is configured with a base URL of /base',
);

// should visit public dir correctly with base prefix
await page.goto(`http://localhost:${rsbuild.port}/base/aaa.txt`);

expect(await page.content()).toContain('aaaa');

restore();
await rsbuild.close();
});

test('should serve resource correctly when assetPrefix is a subPath of server.base', async ({
page,
}) => {
const rsbuild = await dev({
cwd: __dirname,
page,
rsbuildConfig: {
dev: {
assetPrefix: '/base/aaa',
},
server: {
base: '/base',
},
},
});

const locator = page.locator('#test');
await expect(locator).toHaveText('Hello Rsbuild!');

await rsbuild.close();
});
1 change: 1 addition & 0 deletions e2e/cases/server/base/public/aaa.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aaaa
13 changes: 13 additions & 0 deletions e2e/cases/server/base/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html>

<head></head>

<body>
<div id="public-base-path">
<%= process.env.BASE_URL %>
</div>
<div id="root"></div>
</body>

</html>
5 changes: 5 additions & 0 deletions e2e/cases/server/base/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const testEl = document.createElement('div');
testEl.id = 'test';
testEl.innerHTML = 'Hello Rsbuild!';

document.body.appendChild(testEl);
6 changes: 4 additions & 2 deletions packages/compat/plugin-webpack-swc/src/minimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,15 @@ export class SwcMinimizerPlugin {

if (jsMinify) {
const userSourceMapJS = this.rsbuildSourceMapConfig.js;
jsMinify.sourceMap = userSourceMapJS === undefined ? enableMinify : !!userSourceMapJS;
jsMinify.sourceMap =
userSourceMapJS === undefined ? enableMinify : !!userSourceMapJS;
jsMinify.inlineSourcesContent = inlineSourceContent;
}

if (cssMinify) {
const userSourceMapCss = this.rsbuildSourceMapConfig.css;
cssMinify.sourceMap = userSourceMapCss === undefined ? enableMinify : !!userSourceMapCss;
cssMinify.sourceMap =
userSourceMapCss === undefined ? enableMinify : !!userSourceMapCss;
cssMinify.inlineSourceContent = inlineSourceContent;
}

Expand Down
8 changes: 4 additions & 4 deletions packages/compat/plugin-webpack-swc/tests/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ describe('plugin-webpack-swc', () => {
const configs = await rsbuild.initConfigs();

expect(configs).toMatchSnapshot();
process.env.NODE_ENV = 'test'
process.env.NODE_ENV = 'test';
});

it('output.sourceMap config for swcMinimizerPlugin', async () => {
Expand All @@ -482,7 +482,7 @@ describe('plugin-webpack-swc', () => {
sourceMap: {
js: 'cheap-source-map',
css: false,
}
},
},
},
},
Expand All @@ -491,7 +491,7 @@ describe('plugin-webpack-swc', () => {
const configs = await rsbuild.initConfigs();

expect(configs).toMatchSnapshot();
process.env.NODE_ENV = 'test'

process.env.NODE_ENV = 'test';
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly 1`] = `
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
"process.env.ASSET_PREFIX": """",
"process.env.BASE_URL": "\\"/\\"",
},
},
ProgressPlugin {
Expand Down Expand Up @@ -664,6 +665,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when produ
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
"process.env.ASSET_PREFIX": """",
"process.env.BASE_URL": "\\"/\\"",
},
},
ProgressPlugin {
Expand Down Expand Up @@ -971,6 +973,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
"process.env.ASSET_PREFIX": """",
"process.env.BASE_URL": "\\"/\\"",
},
},
ProgressPlugin {
Expand Down Expand Up @@ -1261,6 +1264,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
"process.env.ASSET_PREFIX": """",
"process.env.BASE_URL": "\\"/\\"",
},
},
ProgressPlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ exports[`webpackConfig > should allow to append and prepend plugins 1`] = `
"import.meta.env.MODE": ""none"",
"import.meta.env.PROD": false,
"process.env.ASSET_PREFIX": """",
"process.env.BASE_URL": "\\"/\\"",
},
},
ProgressPlugin {
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import type {
const getDefaultDevConfig = (): NormalizedDevConfig => ({
hmr: true,
liveReload: true,
// Temporary placeholder, default: `${server.base}`
assetPrefix: DEFAULT_ASSET_PREFIX,
writeToDisk: false,
client: {
Expand All @@ -70,6 +71,7 @@ const getDefaultServerConfig = (): NormalizedServerConfig => ({
port: DEFAULT_PORT,
host: DEFAULT_DEV_HOST,
open: false,
base: '/',
htmlFallback: 'index',
compress: true,
printUrls: true,
Expand Down Expand Up @@ -139,6 +141,7 @@ const getDefaultOutputConfig = (): NormalizedOutputConfig => ({
image: IMAGE_DIST_DIR,
media: MEDIA_DIST_DIR,
},
// Temporary placeholder, default: `${server.base}`
assetPrefix: DEFAULT_ASSET_PREFIX,
filename: {},
charset: 'utf8',
Expand Down Expand Up @@ -213,6 +216,18 @@ export const withDefaultConfig = async (
merged.root ||= rootPath;
merged.source ||= {};

if (merged.server?.base) {
if (config.dev?.assetPrefix === undefined) {
merged.dev ||= {};
merged.dev.assetPrefix = merged.server.base;
}

if (config.output?.assetPrefix === undefined) {
merged.output ||= {};
merged.output.assetPrefix = merged.server.base;
}
}

if (!merged.source.tsconfigPath) {
const tsconfigPath = join(rootPath, TS_CONFIG_FILE);

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const DEFAULT_DATA_URL_SIZE = 4096;
export const DEFAULT_MOUNT_ID = 'root';
export const DEFAULT_DEV_HOST = '0.0.0.0';
export const DEFAULT_ASSET_PREFIX = '/';
export const DEFAULT_BASE_URL = '/';
export const DEFAULT_WEB_BROWSERSLIST: string[] = [
'chrome >= 87',
'edge >= 88',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/plugins/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const pluginDefine = (): RsbuildPlugin => ({
'process.env.ASSET_PREFIX': JSON.stringify(
getPublicPathFromChain(chain, false),
),
'process.env.BASE_URL': JSON.stringify(config.server.base),
};

chain
Expand Down
14 changes: 11 additions & 3 deletions packages/core/src/server/compilerDevMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type DevMiddlewareAPI,
getDevMiddleware,
} from './devMiddleware';
import { stripBase } from './helper';
import { SocketServer } from './socketServer';

type Options = {
Expand Down Expand Up @@ -95,7 +96,10 @@ export class CompilerDevMiddleware {
devMiddleware: CustomDevMiddleware,
publicPaths: string[],
): DevMiddlewareAPI {
const { devConfig, serverConfig } = this;
const {
devConfig,
serverConfig: { headers, base },
} = this;

const callbacks = {
onInvalid: (compilationId?: string) => {
Expand All @@ -112,7 +116,7 @@ export class CompilerDevMiddleware {
const clientPaths = getClientPaths(devConfig);

const middleware = devMiddleware({
headers: serverConfig.headers,
headers,
publicPath: '/',
stats: false,
callbacks,
Expand All @@ -126,7 +130,11 @@ export class CompilerDevMiddleware {
etag: 'weak',
});

const assetPrefixes = publicPaths.map(pathnameParse);
const assetPrefixes = publicPaths
.map(pathnameParse)
.map((prefix) =>
base && base !== '/' ? stripBase(prefix, base) : prefix,
);

const warp = async (
req: IncomingMessage,
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/server/getDevMiddlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
import type { UpgradeEvent } from './helper';
import {
faviconFallbackMiddleware,
getBaseMiddleware,
getHtmlCompletionMiddleware,
getHtmlFallbackMiddleware,
getRequestLoggerMiddleware,
Expand Down Expand Up @@ -116,6 +117,10 @@ const applyDefaultMiddlewares = async ({
}
}

if (server.base && server.base !== '/') {
middlewares.push(getBaseMiddleware({ base: server.base }));
}

const { default: launchEditorMiddleware } = await import(
'launch-editor-middleware'
);
Expand Down
Loading

0 comments on commit c681381

Please sign in to comment.