静态资源
Rslib 支持在代码中引用图片、字体、媒体和其他类型文件等静态资源。
静态资源格式
以下是 Rslib 默认支持的静态资源格式:
- 图片:png、jpg、jpeg、gif、svg、bmp、webp、ico、apng、avif、tif、tiff、jfif、pjpeg、pjp、cur、jxl。
- 字体:woff、woff2、eot、ttf、otf、ttc。
- 音频:mp3、wav、flac、aac、m4a、opus。
- 视频:mp4、webm、ogg、mov。
- 其他:webmanifest、pdf、txt、vtt。
除上述静态资源格式外,当 output.target 为 'node' 时,Rslib 还支持在 JavaScript 文件中引入 Node.js addons。
如果你需要引用其他格式的静态资源,请参考 扩展静态资源类型。
在 JavaScript 文件中引用
import 引用
在 JavaScript 文件中,可以直接通过 import 的方式引用相对路径下的静态资源:
// 引用 src/assets 目录下的 logo.png 图片
import logo from './assets/logo.png';
console.log(logo); // "/static/image/logo.png"
export default () => <img src={logo} />;
也可以使用路径别名来引用:
import logo from '@/assets/logo.png';
console.log(logo); // "/static/image/logo.png"
export default () => <img src={logo} />;
在 format 为 cjs 或 esm 时,Rslib 将产物视为会被其他打包工具再次消费的中间产物,默认会在代码转换时将源文件转化为一个 JavaScript 文件和一个根据 output.distPath 输出的静态资源文件,并保留引用静态资源的 import 或 require 语句。
下面是一个使用示例,假设源码如下:
import logo from './assets/logo.svg';
console.log(logo);
会根据配置文件中的 产物结构 配置,输出如下产物:
import logo_namespaceObject from './static/svg/logo.svg';
console.log(logo_namespaceObject);
import logo from './assets/logo.mjs';
console.log(logo);
import logo_namespaceObject from '../static/svg/logo.svg';
export { logo_namespaceObject as default };
new URL 引用
Note
使用 new URL() 引用静态资源时,仅支持生成 ESM 格式的产物,因此 format 必须设置为 'esm'(默认值)。
你可以通过 JavaScript 原生的 URL 和 import.meta.url 相配合,来引用静态资源:
src/index.ts
const logo = new URL('./assets/logo.svg', import.meta.url);
构建后,new URL() 中的路径会指向构建产物中的资源文件,并输出如下产物:
const logo = new URL('./static/svg/logo.svg', import.meta.url);
通过 new URL() 引用的 .js、.ts、.css 和 .scss 等文件也会被视为 URL assets,不会经过相关的内置 loader 处理,其原始内容将作为资源输出。
Note
当 bundle 为 false 时,默认入口为 glob 模式 src/**,会同时匹配 src 下的静态资源文件。对于已经通过 new URL() 引用的资源,需要在 source.entry 中排除这些文件。
rslib.config.ts
export default {
lib: [
{
bundle: false,
source: {
entry: {
index: ['src/**', '!src/assets/logo.svg'],
},
},
},
],
};
跳过 new URL() 处理
如果不希望将 new URL() 解析为 URL asset,可以根据作用范围选择以下方式。
关闭 URL parser
构建 ESM 产物时,Rslib 默认使用 URL parser 的 'new-url-relative' 模式处理 JavaScript 和 TypeScript 文件中的 new URL() 表达式。
如果希望保留原始的 new URL() 表达式,且不由 Rslib 输出对应资源,可以通过 tools.bundlerChain 将 URL parser 设置为 false:
rslib.config.ts
import { defineConfig } from '@rslib/core';
export default defineConfig({
tools: {
bundlerChain(chain) {
chain.module.rule('rslib:new-url').parser({
url: false,
});
},
},
});
关闭后,new URL() 表达式会原样保留,引用的文件不会由 Rslib 输出:
dist/index.js
const logo = new URL('./assets/logo.svg', import.meta.url);
产物仍会保留标准的 new URL(path, import.meta.url) 形式。如果引用的资源需要随产物一起发布,建议通过 output.copy 等方式将其复制到产物目录,并确保输出路径与 new URL() 中的相对路径一致。这样无论产物由后续的打包工具继续处理,还是直接在 Node.js 中运行,都能正确定位该资源。
忽略特定引用
如果只需要跳过某个 new URL() 表达式的处理,可以在第一个参数前添加 rspackIgnore 注释。此时,产物中会保留标准的 new URL(path, import.meta.url) 表达式:
src/index.ts
const logo = new URL(
/* rspackIgnore: true */ './assets/logo.svg',
import.meta.url,
);
在 CSS 文件中引用
在 CSS 文件中,可以引用相对路径下的静态资源:
src/index.css
.logo {
background-image: url('./assets/logo.png');
}
也支持使用路径别名来引用:
src/index.css
.logo {
background-image: url('@/assets/logo.png');
}
在 format 为 cjs 或 esm 时,Rslib 将产物视为会被其他打包工具再次消费的中间产物,默认会将 output.assetPrefix 设置为 "auto" 来使 CSS 产物中保留相对引用路径。
下面是一个使用示例,假设源码如下:
.logo {
background-image: url('./assets/logo.png');
}
会输出如下产物:
.logo {
background-image: url('./static/image/logo.png');
}
在 CSS 中忽略某些文件引用
如果需要在 CSS 文件中引用绝对路径下的静态资源:
@font-face {
font-family: DingTalk;
src: url('/image/font/foo.ttf');
}
默认情况下,Rslib 内置的 css-loader 会解析 url() 中的绝对路径并寻找指定的模块。如果你希望跳过绝对路径的解析,可以配置 tools.cssLoader 来过滤指定的路径,被过滤的路径将被原样保留在代码中。
export default {
tools: {
cssLoader: {
url: {
filter: (url) => {
if (/\/image\/font/.test(url)) {
return false;
}
return true;
},
},
},
},
};
静态资源内联
在 format 为 cjs 或 esm 时,Rslib 将产物视为会被其他打包工具再次消费的中间产物,默认会将 output.dataUriLimit 设置为 0 以不内联任何静态资源。
导入为字符串
Info
字符串导入仅在 bundle 设置为 true 时生效。
通过导入属性
Rslib 支持通过 type: 'text' 导入属性将文件原始内容作为字符串导入到 JavaScript 中。
import svgText from './static/logo.svg' with { type: 'text' };
import imageText from './static/image.png' with { type: 'text' };
import jsonText from './data.json' with { type: 'text' };
import componentText from './component.tsx' with { type: 'text' };
import styleText from './style.css' with { type: 'text' };
console.log(svgText); // 输出 SVG 文件的原始内容
type: 'text' 导入属性支持将资源的原始内容作为字符串导入,不会经过默认的资源、脚本或样式处理流程。
导入属性只影响当前导入,普通导入仍会保持默认行为:
import { foo } from './foo.js';
import fooText from './foo.js' with { type: 'text' };
console.log(foo); // foo.js 导出的内容
console.log(fooText); // foo.js 的原始内容
动态导入也可以通过第二个参数传入导入属性:
const { default: fooText } = await import('./foo.js', {
with: { type: 'text' },
});
console.log(fooText); // foo.js 的原始内容
Tip
推荐优先使用 type: 'text' 导入属性,而不是 ?raw 查询参数。
TypeScript 支持
使用 TypeScript 7.1 及以上版本时,在 src/env.d.ts 中添加以下声明,即可为 type: 'text' 导入提供 string 类型提示:
src/env.d.ts
/// <reference types="@rslib/core/types" />
declare module '*' with { type: 'text' } {
const content: string;
export default content;
}
使用较早的 TypeScript 版本时,请改用 ?raw,@rslib/core/types 已提供对应的类型声明。
通过查询参数
Rslib 也支持通过 ?raw 查询参数将文件内容作为字符串导入:
import rawSvg from './static/logo.svg?raw';
import rawImage from './static/image.png?raw';
import rawJson from './data.json?raw';
import rawComponent from './component.tsx?raw';
import rawStyle from './style.css?raw';
console.log(rawSvg); // 输出 SVG 文件的原始内容
构建产物
当静态资源被引用后,会自动被输出到构建产物的目录下,你可以:
rslib.config.ts
export default {
output: {
filename: {
svg: '[name].[contenthash:10].svg',
font: '[name].[contenthash:10][ext]',
image: '[name].[contenthash:10][ext]',
media: '[name].[contenthash:10][ext]',
assets: '[name].[contenthash:10][ext]',
},
},
};
rslib.config.ts
export default {
output: {
distPath: {
svg: 'resource/svg',
font: 'resource/font',
image: 'resource/image',
media: 'resource/media',
assets: 'resource/assets',
},
},
};
类型声明
当你在 TypeScript 代码中引用静态资源时,TypeScript 可能会提示该模块缺少类型定义:
TS2307: Cannot find module './logo.png' or its corresponding type declarations.
此时你可以使用以下任一方法添加类型声明:
- 方法一:如果项目里安装了
@rslib/core 包,你可以在 tsconfig.json 中添加 @rslib/core 提供的 预设类型:
tsconfig.json
{
"compilerOptions": {
"types": ["@rslib/core/types"]
}
}
src/env.d.ts
// 以 png 图片为例
declare module '*.png' {
const url: string;
export default url;
}
添加类型声明后,如果依然存在上述错误提示,请尝试重启当前 IDE,或者调整 env.d.ts 所在的目录,使 TypeScript 能够正确识别类型定义。
扩展静态资源类型
如果 Rslib 内置的静态资源类型不能满足你的需求,可以通过以下方式扩展额外的静态资源类型。
使用 source.assetsInclude
通过 source.assetsInclude 配置项,你可以指定需要被视为静态资源的额外文件类型。
rslib.config.ts
export default {
source: {
assetsInclude: /\.gltf$/,
},
};
添加以上配置后,你就可以在代码里引用 *.gltf 文件了,比如:
import myFile from './static/model.gltf';
console.log(myFile); // "/static/assets/model.gltf"
可以通过 tools.rspack 来修改内置的 Rspack 配置,并添加自定义的静态资源处理规则。
比如,把 *.gltf 文件当做静态资源输出到产物目录,可以添加以下配置:
rslib.config.ts
export default {
tools: {
rspack(config, { addRules }) {
addRules([
{
test: /\.gltf$/,
// 将资源转换为单独的文件,并且保留 import 语句
type: 'asset/resource',
generator: {
importMode: 'preserve',
},
},
]);
},
},
};
关于资源模块的更多介绍,请参考 Rspack - 资源模块。