Rsbuild 支持在代码中引用图片、字体、音频、视频等类型的静态资源。
静态资源是指 Web 应用中不会发生变化的文件。常见的静态资源包括图片、字体、视频、样式表和 JavaScript 文件。这些资源通常存储在服务器或 CDN 上,当用户访问 Web 应用时会被传送到用户的浏览器。由于它们不会发生变化,静态资源可以被浏览器缓存,从而提高 Web 应用的性能。
以下是 Rsbuild 默认支持的静态资源格式:
如果你需要引用其他格式的静态资源,请参考 扩展静态资源类型。
SVG 图片是一种特殊情况,Rsbuild 提供了 SVG 转 React 组件的能力,对 SVG 进行单独处理,详见 SVGR 插件。
在 JS 文件中,可以直接通过 import
的方式引用相对路径下的静态资源:
// 引用 static 目录下的 logo.png 图片
import logo from './static/logo.png';
console.log(logo); // "/static/logo.[hash].png"
export default () => <img src={logo} />;
也可以使用路径别名来引用:
import logo from '@/static/logo.png';
console.log(logo); // "/static/logo.[hash].png"
export default () => <img src={logo} />;
Rsbuild 支持使用 JavaScript 原生的 URL 和 import.meta.url 相配合,来引用静态资源。
const logo = new URL('./static/logo.png', import.meta.url).href;
console.log(logo); // "/static/logo.[hash].png"
export default () => <img src={logo} />;
如果你使用 new URL()
引用 .js
或 .ts
文件,它们将被视为 URL assets,不会经过 Rsbuild 内置的 swc-loader
处理。
// foo.ts 文件将保持原始内容被输出到产物目录下
const fooTs = new URL('./foo.ts', import.meta.url).href;
console.log(fooTs); // "/static/foo.[hash].ts"
同理,当使用 new URL()
引用 .css
或 .scss
文件时,它们将被视为 URL assets,不会经过 Rsbuild 内置的 CSS loaders 处理。
// foo.css 文件将保持原始内容被输出到产物目录下
const fooCss = new URL('./foo.css', import.meta.url).href;
console.log(fooCss); // "/static/foo.[hash].css"
在 CSS 文件中,可以引用相对路径下的静态资源:
.logo {
background-image: url('../static/logo.png');
}
也支持使用路径别名来引用:
.logo {
background-image: url('@/static/logo.png');
}
如果需要在 CSS 文件中引用绝对路径下的静态资源:
@font-face {
font-family: DingTalk;
src: url('/image/font/foo.ttf');
}
默认情况下,Rsbuild 内置的 css-loader
会解析 url()
中的绝对路径并寻找指定的模块。如果你希望跳过绝对路径的解析,可以配置 tools.cssLoader
来过滤指定的路径,被过滤的路径将被原样保留在代码中。
export default {
tools: {
cssLoader: {
url: {
filter: (url) => {
if (/\/image\/font/.test(url)) {
return false;
}
return true;
},
},
},
},
};
引用静态资源的结果取决于文件体积:
import largeImage from './static/largeImage.png';
import smallImage from './static/smallImage.png';
console.log(largeImage); // "/static/largeImage.[hash].png"
console.log(smallImage); // "data:image/png;base64,iVBORw0KGgo..."
添加 ?url
query 参数,可以确保资源始终作为单独的文件加载,并返回一个 URL:
import image from './static/image.png?url';
console.log(image); // "/static/image.[hash].png"
添加 ?inline
query 参数,可以强制将资源内联到代码中,无论文件体积如何:
import image from './static/image.png?inline';
console.log(image); // "data:image/png;base64,iVBORw0KGgo..."
关于资源内联的更详细介绍,请参考 静态资源内联 章节。
Rsbuild 支持通过 ?raw
查询参数引用静态资源的原始内容,并将其作为字符串导入到 JavaScript 中。
import rawSvg from './static/logo.svg?raw';
console.log(rawSvg); // 输出 SVG 文件的原始内容
Rsbuild 还支持通过 ?raw
查询参数引用 JavaScript、TypeScript 和 JSX 等文件的原始内容。
import rawJs from './script1.js?raw';
import rawTs from './script2.ts?raw';
import rawJsx from './script3.jsx?raw';
import rawTsx from './script4.tsx?raw';
console.log(rawJs); // JS 文件的原始内容
console.log(rawTs); // TS 文件的原始内容
console.log(rawJsx); // JSX 文件的原始内容
console.log(rawTsx); // TSX 文件的原始内容
你也可以使用 ?raw
查询参数来引用 CSS 文件的原始内容,详见 CSS。
Rsbuild >= 1.3.0 支持 ?raw
查询参数,>= 1.4.0 支持引用 JS 和 TS 文件的原始内容。
当静态资源被引用后,会自动被输出到构建产物的目录下,你可以:
请阅读 构建产物 来了解更多细节。
引用静态资源后返回的 URL 中会自动包含路径前缀:
dev.assetPrefix
或 output.assetPrefix
未配置时,将自动使用 server.base 的值作为默认前缀。比如将 output.assetPrefix
设置为 https://example.com
:
export default {
output: {
assetPrefix: 'https://example.com',
},
};
import logo from './static/logo.png';
console.log(logo); // "https://example.com/static/logo.[hash].png"
项目根目录下的 public 目录可以用于放置一些静态资源,这些资源不会被 Rsbuild 构建,并且可以直接通过 URL 引用。
/
)。比如,你可以在 public 目录下放置 robots.txt
、manifest.json
或 favicon.ico
等文件。
你可以通过 URL 来引用 public 目录下的文件。
例如,在 HTML 模板中,./public/favicon.ico
文件可以被引用为 /favicon.ico
,BASE_URL 对应服务端的基础路径。
<link rel="icon" href="<%= process.env.BASE_URL %>/favicon.ico" />
下面是一些使用 public 目录的注意事项:
<!-- 错误 -->
<link rel="icon" href="../public/favicon.ico" />
<!-- 正确 -->
<link rel="icon" href="/favicon.ico" />
/src/assets
目录下。// 错误
import logo from '../public/logo.png';
// 正确
import logo from './assets/logo.png';
dist
)下,请注意不要和产物文件出现名称冲突。当 public 下的文件和产物重名时,构建产物具有更高的优先级,会覆盖 public 下的同名文件。这个功能可以通过将 server.publicDir.copyOnBuild 设置为 false
来禁用。Rsbuild 提供了 server.publicDir 选项,可以用于自定义 public 目录的名称和行为,也可以用于禁用 public 目录。
export default {
server: {
publicDir: false,
},
};
当你在 TypeScript 代码中引用静态资源时,TypeScript 可能会提示该模块缺少类型定义:
TS2307: Cannot find module './logo.png' or its corresponding type declarations.
此时你需要为静态资源添加类型声明文件,请在项目中创建 src/env.d.ts
文件,并添加相应的类型声明。
@rsbuild/core
包,你可以直接引用 @rsbuild/core
提供的 预设类型:/// <reference types="@rsbuild/core/types" />
// 以 png 图片为例
declare module '*.png' {
const content: string;
export default content;
}
添加类型声明后,如果依然存在上述错误提示,请尝试重启当前 IDE,或者调整 env.d.ts
所在的目录,使 TypeScript 能够正确识别类型定义。
如果 Rsbuild 内置的静态资源类型不能满足你的需求,可以通过以下方式扩展额外的静态资源类型。
source.assetsInclude
通过 source.assetsInclude 配置项,你可以指定需要被视为静态资源的额外文件类型。
export default {
source: {
assetsInclude: /\.pdf$/,
},
};
添加以上配置后,你就可以在代码里引用 *.pdf
文件了,比如:
import myFile from './static/myFile.pdf';
console.log(myFile); // "/static/myFile.[hash].pdf"
tools.rspack
可以通过 tools.rspack 来修改内置的 Rspack 配置,并添加自定义的静态资源处理规则。
比如,把 *.pdf
文件当做静态资源输出到产物目录,可以添加以下配置:
export default {
tools: {
rspack(config, { addRules }) {
addRules([
{
test: /\.pdf$/,
// 将资源转换为单独的文件,并且导出产物地址
type: 'asset/resource',
},
]);
},
},
};
关于 asset modules 的更多介绍,请参考 Rspack - Asset modules。
扩展的静态资源类型会受到以下配置项的影响:
在某些场景下,你可能需要跳过 Rsbuild 内置的静态资源处理规则,并添加一些自定义规则。
以 PNG 图片为例,你需要:
exclude
排除 .png
文件。export default {
tools: {
bundlerChain(chain, { CHAIN_ID }) {
chain.module
// 通过 `CHAIN_ID.RULE.IMAGE` 来定位到内置的图片规则
.rule(CHAIN_ID.RULE.IMAGE)
.exclude.add(/\.png$/);
},
rspack(config, { addRules }) {
addRules([
{
test: /\.png$/,
// 添加一个自定义的 loader 来处理 png 图片
loader: 'custom-png-loader',
},
]);
},
},
};
在使用图片资源时,你可以根据下方表格中图片的优缺点以及适用场景,来选择合适的图片格式。
格式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
PNG | 无损压缩,不会丢失图片细节,不失真,支持半透明 | 不适合色表复杂的图片 | 适合颜色数量少,边界层次分明的图片,适合用在 logo、icon、透明图等场景 |
JPG | 颜色丰富 | 有损压缩,会导致图片失真,不支持透明度 | 适合颜色数量多,颜色带有渐变、过度复杂的图片,适合用在人像照片、风景图等场景 |
WebP | 同时支持有损压缩与无损压缩,支持透明度,体积比 PNG 和 JPG 小很多 | iOS 兼容性不好 | 几乎任何场景的像素图片,支持 WebP 的宿主环境,都应该首选 WebP 图片格式 |
SVG | 无损格式,不失真,支持透明度 | 不适合复杂图形 | 适合矢量图,适合用于 icon |