Skip to content

Commit

Permalink
feat: add dev.inlineStyles config
Browse files Browse the repository at this point in the history
  • Loading branch information
Thulof committed Jul 23, 2024
1 parent 695b38c commit d32efac
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 11 deletions.
43 changes: 42 additions & 1 deletion e2e/cases/inline-chunk/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import { build, gotoPage } from '@e2e/helper';
import { build, dev, gotoPage } from '@e2e/helper';
import { expect, test } from '@playwright/test';
import type { RspackChain } from '@rsbuild/core';

Expand Down Expand Up @@ -155,3 +155,44 @@ test('inline styles by filename and file size', async () => {
).length,
).toEqual(0);
});

test('styles are not inline by default in development mode', async ({
page,
}) => {
const rsbuild = await dev({
cwd: __dirname,
rsbuildConfig: {
tools: toolsConfig,
},
});

await gotoPage(page, rsbuild);

// index.css in page
await expect(
page.evaluate(
`document.querySelectorAll('link[href*="index.css"]').length`,
),
).resolves.toEqual(1);
});

test('using RegExp to inline styles in development mode', async ({ page }) => {
const rsbuild = await dev({
cwd: __dirname,
rsbuildConfig: {
dev: {
inlineStyles: true,
},
tools: toolsConfig,
},
});

await gotoPage(page, rsbuild);

// no index.css in page
await expect(
page.evaluate(
`document.querySelectorAll('link[href*="index.css"]').length`,
),
).resolves.toEqual(0);
});
1 change: 1 addition & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const getDefaultDevConfig = (): NormalizedDevConfig => ({
host: '',
overlay: true,
},
inlineStyles: false,
});

const getDefaultServerConfig = (): NormalizedServerConfig => ({
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/plugins/inlineChunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,14 @@ export const pluginInlineChunk = (): RsbuildPlugin => ({
({ headTags, bodyTags }, { compiler, compilation, environment }) => {
const { htmlPaths, config } = environment;

if (isDev() || Object.keys(htmlPaths).length === 0) {
if (Object.keys(htmlPaths).length === 0) {
return { headTags, bodyTags };
}

const { inlineStyles, inlineScripts } = config.output;
const inlineStyles = isDev()
? config.dev.inlineStyles
: config.output.inlineStyles;
const { inlineScripts } = config.output;

const scriptTests: InlineChunkTest[] = [];
const styleTests: InlineChunkTest[] = [];
Expand Down
12 changes: 11 additions & 1 deletion packages/core/src/types/config/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
import type { WatchOptions } from 'chokidar';
import type { Rspack } from '../rspack';
import type { Stats } from '../stats';
import type { InlineChunkTest } from './shared';

export type ProgressBarConfig = {
id?: string;
Expand Down Expand Up @@ -108,12 +109,21 @@ export interface DevConfig {
* Enable lazy compilation.
*/
lazyCompilation?: boolean | Rspack.LazyCompilationOptions;
/**
* Whether to inline output style files (.css files) into html with `<style>` tags in development mode.
*/
inlineStyles?: boolean | InlineChunkTest;
}

export type NormalizedDevConfig = DevConfig &
Required<
Pick<
DevConfig,
'hmr' | 'client' | 'liveReload' | 'assetPrefix' | 'writeToDisk'
| 'hmr'
| 'client'
| 'liveReload'
| 'assetPrefix'
| 'writeToDisk'
| 'inlineStyles'
>
>;
1 change: 1 addition & 0 deletions packages/core/src/types/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,4 @@ export * from './server';
export * from './output';
export * from './security';
export * from './performance';
export * from './shared';
8 changes: 1 addition & 7 deletions packages/core/src/types/config/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
import type { CSSLoaderModulesOptions } from '../../types';
import type { RsbuildTarget } from '../rsbuild';
import type { Rspack, RspackConfig } from '../rspack';
import type { InlineChunkTest } from './shared';

export type DistPathConfig = {
/**
Expand Down Expand Up @@ -182,13 +183,6 @@ export type Minify =
cssOptions?: LightningCssMinimizerRspackPluginOptions;
};

export type InlineChunkTestFunction = (params: {
size: number;
name: string;
}) => boolean;

export type InlineChunkTest = RegExp | InlineChunkTestFunction;

export interface OutputConfig {
/**
* Specify build target to run in specified environment.
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/config/shared/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './inlineChunk';
6 changes: 6 additions & 0 deletions packages/core/src/types/config/shared/inlineChunk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type InlineChunkTestFunction = (params: {
size: number;
name: string;
}) => boolean;

export type InlineChunkTest = RegExp | InlineChunkTestFunction;
85 changes: 85 additions & 0 deletions website/docs/en/config/dev/inline-styles.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# dev.inlineStyles

- **Type:**

```ts
type InlineStyles =
| boolean
| RegExp
| ((params: { size: number; name: string }) => boolean);
```

- **Default:** `false`

Whether to inline style files (.css files) into HTML with `<style>` tags in development mode.

Note that, with this option on, the style files will no longer be linked from external, they will only exist inside the HTML file instead.

### Example

By default, we have following preview page:

```html
<html>
<head>
<link rel="stylesheet" href="/static/css/style.css" />
</head>
<body></body>
</html>
```

After turn on the `dev.inlineStyles` option:

```js
export default {
dev: {
inlineStyles: true,
},
};
```

The style file `/static/css/style.css` will be inlined in `index.html`:

```html
<html>
<head>
<style>
/* content of /static/css/style.css */
</style>
</head>
<body></body>
</html>
```

### Using RegExp

If you need to inline part of the CSS files, you can set `inlineStyles` to a regular expression that matches the URL of the CSS file that needs to be inlined.

For example, to inline `main.css` into HTML, you can add the following configuration:

```js
export default {
dev: {
inlineStyles: /[\\/]main\.\w+\.css$/,
},
};
```

### Using Function

You can also set `dev.inlineStyles` to a function that accepts the following parameters:

- `name`: The filename, such as `static/css/main.css`.
- `size`: The file size in bytes.

For example, if we want to inline assets that are smaller than 10kB, we can add the following configuration:

```js
export default {
dev: {
inlineStyles({ size }) {
return size < 10 * 1000;
},
},
};
```
85 changes: 85 additions & 0 deletions website/docs/zh/config/dev/inline-styles.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# dev.inlineStyles

- **类型:**

```ts
type InlineStyles =
| boolean
| RegExp
| ((params: { size: number; name: string }) => boolean);
```

- **默认值:** `false`

用来控制开发环境中是否用 `<style>` 标签将 style 文件(.css 文件)inline 到 HTML 中。

注意,如果开启了这个选项,那么 style 将不会通过外联方式引入,而只会以 inline 样式的形式存在于 HTML 文件中。

### 示例

默认情况下,预览页面有如下结构:

```html
<html>
<head>
<link rel="stylesheet" href="/static/css/style.css" />
</head>
<body></body>
</html>
```

开启 `dev.inlineStyles` 选项后:

```js
export default {
dev: {
inlineStyles: true,
},
};
```

`/static/css/style.css` 文件将被 inline 到 `index.html` 中:

```html
<html>
<head>
<style>
/* content of /static/css/style.css */
</style>
</head>
<body></body>
</html>
```

### 通过正则匹配

当你需要内联一部分 CSS 文件时,你可以将 `inlineStyles` 设置为一个正则表达式,匹配需要内联的 CSS 文件的 URL。

比如,将产物中的 `main.css` 内联到 HTML 中,你可以添加如下配置:

```js
export default {
dev: {
inlineStyles: /[\\/]main\.\w+\.css$/,
},
};
```

### 通过函数匹配

你也可以将 `dev.inlineStyles` 设置为一个函数,函数接收以下参数:

- `name`:文件名,比如 `static/css/main.css`
- `size`:文件大小,单位为 byte。

比如,我们希望内联小于 10kB 的资源,可以添加如下配置:

```js
export default {
dev: {
inlineStyles({ size }) {
return size < 10 * 1000;
},
},
};
```

0 comments on commit d32efac

Please sign in to comment.