Skip to content

Commit

Permalink
feat: define import.meta.env.BASE_URL (#3632)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan authored Oct 3, 2024
1 parent dbab19e commit 2fedf37
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 71 deletions.
54 changes: 54 additions & 0 deletions e2e/cases/server/base-url-env-var/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { build, dev, rspackOnlyTest } from '@e2e/helper';
import { expect } from '@playwright/test';

rspackOnlyTest(
'should define BASE_URL env var correctly in dev',
async ({ page }) => {
const rsbuild = await dev({
cwd: __dirname,
page,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
base: '/base',
},
},
});

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

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

await rsbuild.close();
},
);

rspackOnlyTest(
'should define BASE_URL env var correctly in build',
async ({ page }) => {
const rsbuild = await build({
cwd: __dirname,
page,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
base: '/base',
},
},
});

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

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

await rsbuild.close();
},
);
10 changes: 10 additions & 0 deletions e2e/cases/server/base-url-env-var/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<html>
<head></head>

<body>
<div id="public-base-path-process"><%= process.env.BASE_URL %></div>
<div id="public-base-path-meta"><%= import.meta.env.BASE_URL %></div>
<div id="root"></div>
</body>
</html>
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ test('server.base when dev', async ({ page }) => {
cwd: __dirname,
page,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
printUrls: true,
base: '/base',
Expand All @@ -23,9 +20,6 @@ test('server.base when dev', async ({ page }) => {

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) =>
Expand Down Expand Up @@ -61,11 +55,7 @@ test('server.base when build & preview', async ({ page }) => {
const rsbuild = await build({
cwd: __dirname,
page,
runServer: true,
rsbuildConfig: {
html: {
template: './src/index.html',
},
server: {
printUrls: true,
base: '/base',
Expand All @@ -78,9 +68,6 @@ test('server.base when build & preview', async ({ page }) => {

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) =>
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions e2e/cases/server/base-url/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);
13 changes: 0 additions & 13 deletions e2e/cases/server/base/src/index.html

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly 1`] = `
},
DefinePlugin {
"definitions": {
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down Expand Up @@ -661,6 +662,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when produ
},
DefinePlugin {
"definitions": {
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
Expand Down Expand Up @@ -969,6 +971,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe
RsbuildCorePlugin {},
DefinePlugin {
"definitions": {
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
Expand Down Expand Up @@ -1260,6 +1263,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe
RsbuildCorePlugin {},
DefinePlugin {
"definitions": {
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ exports[`webpackConfig > should allow to append and prepend plugins 1`] = `
},
DefinePlugin {
"definitions": {
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""none"",
"import.meta.env.PROD": false,
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/plugins/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ export const pluginDefine = (): RsbuildPlugin => ({
setup(api) {
api.modifyBundlerChain((chain, { CHAIN_ID, bundler, environment }) => {
const { config } = environment;

const baseUrl = JSON.stringify(config.server.base);
const builtinVars: Define = {
'import.meta.env.MODE': JSON.stringify(config.mode),
'import.meta.env.DEV': config.mode === 'development',
'import.meta.env.PROD': config.mode === 'production',
'import.meta.env.BASE_URL': baseUrl,
'process.env.ASSET_PREFIX': JSON.stringify(
getPublicPathFromChain(chain, false),
),
'process.env.BASE_URL': JSON.stringify(config.server.base),
'process.env.BASE_URL': baseUrl,
};

chain
Expand Down
1 change: 1 addition & 0 deletions packages/core/tests/__snapshots__/builder.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ exports[`should use rspack as default bundler > apply rspack correctly 1`] = `
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down
4 changes: 4 additions & 0 deletions packages/core/tests/__snapshots__/default.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly 1`] = `
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down Expand Up @@ -780,6 +781,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when prod
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""production"",
"import.meta.env.PROD": true,
Expand Down Expand Up @@ -1117,6 +1119,7 @@ exports[`applyDefaultPlugins > should apply default plugins correctly when targe
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down Expand Up @@ -1518,6 +1521,7 @@ exports[`tools.rspack > should match snapshot 1`] = `
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down
1 change: 1 addition & 0 deletions packages/core/tests/__snapshots__/define.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exports[`plugin-define > should register define plugin correctly 1`] = `
"_args": [
{
"NAME": ""Jack"",
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""none"",
"import.meta.env.PROD": false,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/tests/__snapshots__/environments.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,7 @@ exports[`environment config > tools.rspack / bundlerChain can be configured in e
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down Expand Up @@ -2016,6 +2017,7 @@ exports[`environment config > tools.rspack / bundlerChain can be configured in e
DefinePlugin {
"_args": [
{
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": true,
"import.meta.env.MODE": ""development"",
"import.meta.env.PROD": false,
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-vue/tests/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ DefinePlugin {
"__VUE_OPTIONS_API__": true,
"__VUE_PROD_DEVTOOLS__": false,
"__VUE_PROD_HYDRATION_MISMATCH_DETAILS__": false,
"import.meta.env.BASE_URL": "\\"/\\"",
"import.meta.env.DEV": false,
"import.meta.env.MODE": ""none"",
"import.meta.env.PROD": false,
Expand Down
55 changes: 33 additions & 22 deletions website/docs/en/guide/advanced/env-vars.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@ You can also use the following environment variables:
- `import.meta.env.DEV`: If [mode](/config/mode) is `'development'`, the value is `true`; otherwise, it is `false`.
- `import.meta.env.PROD`: If [mode](/config/mode) is `'production'`, the value is `true`; otherwise, it is `false`.

### import.meta.env.BASE_URL

You can use `import.meta.env.BASE_URL` in the client code to access the server's [base path](/guide/basic/server#base-path), which is determined by the [server.base](/config/server/base) configuration, which is helpful for referencing [public folder](/guide/basic/static-assets#public-folder) assets in the code.

For example, we set the base path of the server to `/foo` through [server.base](/config/server/base) configuration:

```ts
export default {
server: {
base: '/foo',
},
};
```

Then, the access URL to the `favicon.ico` file in the public directory is `http://localhost:3000/foo/favicon.ico`. You can use `import.meta.env.BASE_URL` to concatenate the URL in JS files:

```js title="index.js"
const image = new Image();
// Equivalent to "/foo/favicon.ico"
image.src = `${import.meta.env.BASE_URL}/favicon.ico`;
```
In the HTML template, you can also use `import.meta.env.BASE_URL` to concatenate the URL:
```html title="index.html"
<!-- Equivalent to "/foo/favicon.ico" -->
<link rel="icon" href="<%= import.meta.env.BASE_URL %>/favicon.ico" />
```
Additionally, you can use the following environment variables:
- `process.env.BASE_URL`: Equivalent to `import.meta.env.BASE_URL`.
### process.env.NODE_ENV
By default, Rsbuild will automatically set the `process.env.NODE_ENV` environment variable to `'development'` in development mode and `'production'` in production mode.
Expand Down Expand Up @@ -107,28 +140,6 @@ In production mode, the above code will be compiled to:
const Image = <img src={`https://example.com/static/icon.png`} />;
```
### process.env.BASE_URL

You can use `process.env.BASE_URL` in client code to access the server's [base path](/guide/basic/server#base-path).

This is helpful for us to reference [public folder](/guide/basic/static-assets#public-folder) assets in HTML templates.

For example, we set the base path of the server to `/foo` through [server.base](/config/server/base) configuration:

```ts
export default {
server: {
base: '/foo',
},
};
```

Then, the access path to the `favicon.ico` file in the public directory is `http://localhost:3000/foo/favicon.ico`. We can reference `./public/favicon.ico` file in the HTML template like this:

```html title="index.html"
<link rel="icon" href="<%= process.env.BASE_URL %>/favicon.ico" />
```

## `.env` File
When a `.env` file exists in the project root directory, Rsbuild CLI will automatically use [dotenv](https://npmjs.com/package/dotenv) to load these environment variables and add them to the current Node.js process.
Expand Down
55 changes: 33 additions & 22 deletions website/docs/zh/guide/advanced/env-vars.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@ if (false) {
- `import.meta.env.DEV`:当 [mode](/config/mode)`'development'` 时,值为 `true`,否则为 `false`
- `import.meta.env.PROD`:当 [mode](/config/mode)`'production'` 时,值为 `true`,否则为 `false`

### import.meta.env.BASE_URL

你可以在 client 代码中使用 `import.meta.env.BASE_URL` 来访问服务端的[基础路径](/guide/basic/server#服务端基础路径),它由 [server.base](/config/server/base) 配置项决定,这有助于在代码中引用 [public 目录](/guide/basic/static-assets#public-目录) 下的资源。

比如,我们通过 [server.base](/config/server/base) 配置,将服务端的基础路径设置为 `/foo`

```ts
export default {
server: {
base: '/foo',
},
};
```

此时,public 目录下 `favicon.ico` 文件的访问 URL 为 `http://localhost:3000/foo/favicon.ico`,在 JS 文件中可以使用 `import.meta.env.BASE_URL` 来拼接 URL:

```js title="index.js"
const image = new Image();
// 等价于 "/foo/favicon.ico"
image.src = `${import.meta.env.BASE_URL}/favicon.ico`;
```
HTML 模板中,也可以使用 `import.meta.env.BASE_URL` 来拼接 URL
```html title="index.html"
<!-- 等价于 "/foo/favicon.ico" -->
<link rel="icon" href="<%= import.meta.env.BASE_URL %>/favicon.ico" />
```
此外,你还可以使用以下环境变量:
- `process.env.BASE_URL`:等同于 `import.meta.env.BASE_URL`
### process.env.NODE_ENV
默认情况下,Rsbuild 会自动设置 `process.env.NODE_ENV` 环境变量,在开发模式为 `'development'`,生产模式为 `'production'`
Expand Down Expand Up @@ -107,28 +140,6 @@ const Image = <img src={`/static/icon.png`} />;
const Image = <img src={`https://example.com/static/icon.png`} />;
```
### process.env.BASE_URL

你可以在 client 代码中使用 `process.env.BASE_URL` 来访问服务端的[基础路径](/guide/basic/server#服务端基础路径)

这对于我们在 HTML 模版中引用 [public 目录](/guide/basic/static-assets#public-目录) 资源很有帮助。

比如,我们通过 [server.base](/config/server/base) 配置,将服务端的基础路径设置为 `/foo`

```ts
export default {
server: {
base: '/foo',
},
};
```

此时,public 目录下 `favicon.ico` 文件的访问路径为 `http://localhost:3000/foo/favicon.ico`,我们可以采用如下方式在 HTML 模板中引用 `./public/favicon.ico` 文件:

```html title="index.html"
<link rel="icon" href="<%= process.env.BASE_URL %>/favicon.ico" />
```

## `.env` 文件
当项目根目录存在 `.env` 文件时,Rsbuild CLI 会自动使用 [dotenv](https://npmjs.com/package/dotenv) 来加载这些环境变量,并添加到当前 Node.js 进程中。
Expand Down

0 comments on commit 2fedf37

Please sign in to comment.