Browser API
@rspack/browser
是专为浏览器环境打造的 Rspack 版本,无需依赖 WebContainers 或特定平台。其 API 与 @rspack/core
的 JavaScript API 保持一致,并在此基础上,额外提供了适配浏览器环境的特性和接口。
欢迎前往 Rspack Playground 体验在浏览器中运行 Rspack 的效果。
WARNING
目前 @rspack/browser
仍处于实验阶段,我们将持续完善在线打包能力,后续可能会引入不兼容变更。
基本示例
以下示例展示了 @rspack/browser
的基本用法。除了需要使用额外的 API 读写项目文件和产物外,其他 API 与 @rspack/core
的 JavaScript API 保持一致。
import { rspack, builtinMemFs } from '@rspack/browser';
// Write files to memfs
builtinMemFs.volume.fromJSON({
// ...project files
});
rspack({}, (err, stats) => {
if (err || stats.hasErrors()) {
// ...
}
// Get output from memfs after bundling
const files = builtinMemFs.volume.toJSON();
});
响应头设置
@rspack/browser
内部使用了 SharedArrayBuffer 来实现多线程的共享内存,因此你需要为开发服务器或线上部署环境设置响应头。
如果你正在使用 Rspack 作为项目的打包器,可以通过 devServer.headers 设置:
rspack.config.mjs
export default {
//...
devServer: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
};
如果你正在使用 Rsbuild 作为项目的打包器,可以通过 server.headers 设置:
rsbuild.config.ts
export default {
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
};
对于线上环境,请参考你的项目部署平台的相关文档。
内存文件系统
由于浏览器无法直接访问本地文件系统,@rspack/browser
提供了基于 memfs 的内存文件系统对象 builtinMemFs
,用于在浏览器环境下读写文件。Node.js 和 Rust 层对文件系统的读写均会重定向到该内存文件系统,包括项目配置、源代码、node_modules
依赖及产物。
以下是基本用法示例,完整 API 可参考 memfs 文档:
import { builtinMemFs } from '@rspack/browser';
// Write files to memfs
builtinMemFs.volume.fromJSON({
// ...project files
});
// Read files from memfs
const files = builtinMemFs.volume.toJSON();
浏览器专用插件
为更好地满足浏览器环境下的打包需求,@rspack/browser
提供了若干专用插件。
BrowserHttpImportEsmPlugin
在本地开发环境中,开发者通常通过包管理器将项目依赖下载并存储在根目录的 node_modules
目录中。在使用 @rspack/browser
时,你可以将依赖项预先写入内存文件系统的 node_modules
目录。然而,当项目依赖的模块存在不确定性时(例如允许用户自由选择第三方依赖),预先写入所有依赖就变得不切实际。
import { builtinMemFs } from '@rspack/browser';
builtinMemFs.volume.fromJSON({
'/node_modules/react/index.js': '...',
});
@rspack/browser
提供了 BrowserHttpImportEsmPlugin
插件。该插件在解析模块时,会将第三方依赖的模块名重写为 ESM CDN 的 URL。例如,import React from "react"
会被重写为 import React from "https://esm.sh/react"
。结合 Rspack 的 buildHttp 功能,即可在打包时通过 HTTP 动态加载依赖。
rspack.config.mjs
import { BrowserHttpImportEsmPlugin } from '@rspack/browser';
export default {
plugins: [new BrowserHttpImportEsmPlugin({ domain: 'https://esm.sh' })],
experiments: {
buildHttp: {
allowedUris: ['https://'],
},
},
};
如下所示,BrowserHttpImportEsmPlugin
支持通过选项指定 ESM CDN 的域名,或者指定某些依赖的特定版本或 URL。
interface BrowserHttpImportPluginOptions {
/**
* ESM CDN 域名
*/
domain: string | ((request: string, packageName: string) => string);
/**
* 为特定的依赖指定 URL
*/
dependencyUrl?:
| Record<string, string | undefined>
| ((packageName: string) => string | undefined);
/**
* 为依赖指定版本。
* 如果未指定,默认为 "latest"。
*/
dependencyVersions?: Record<string, string | undefined>;
}
BrowserRequirePlugin
在 Rspack 中,某些场景需要动态加载和执行 JavaScript 代码,如 Loader 或 HtmlRspackPlugin 的模板函数。由于这些代码可能来自不可信的第三方用户,直接在浏览器环境中执行会带来潜在的安全风险。为了保障安全性,@rspack/browser
在遇到此类场景时会默认抛出错误,阻止不安全代码的执行。
WARNING
Rspack 在打包过程中不会执行项目的用户代码。为了安全起见,建议在 iframe 中运行最终的打包产物。
BrowserRequirePlugin
插件开放了此类能力:
rspack.config.mjs
import { BrowserRequirePlugin } from '@rspack/browser';
export default {
plugins: [
new BrowserRequirePlugin({ execute: BrowserRequirePlugin.unsafeExecute }),
],
};
你需要提供一个 execute
函数,用于动态执行和加载 CommonJS 模块,并修改 runtime.module.exports
来设置该模块导出的内容。@rspack/browser
提供了一个不安全的实现 BrowserRequirePlugin.unsafeExecute
,其内部直接使用 new Function
执行代码。你也可以根据实际需求,基于该 API 封装更安全的实现,例如:
function safeExecute(code: string, runtime: CommonJsRuntime) {
const safeCode = sanitizeCode(code);
BrowserRequirePlugin.unsafeExecute(safeCode, runtime);
}
function uselessExecute(_code: string, runtime: CommonJsRuntime) {
runtime.module.exports.hello = 'rspack';
}
BrowserRequirePlugin
的选项如下:
/**
* 加载 CommonJS 模块的运行时上下文
*/
interface CommonJsRuntime {
module: any;
exports: any;
require: BrowserRequire;
}
interface BrowserRequirePluginOptions {
/**
* 执行动态代码的函数
*/
execute: (code: string, runtime: CommonJsRuntime) => void;
}
如何选择是否使用此插件?
如果你的项目无需动态加载和执行 JavaScript 代码,则无需使用此插件。
若项目不会分发不可信代码,或即使分发也不会造成安全问题,可直接使用 BrowserRequirePlugin.unsafeExecute
。例如 Rspack Playground 就不涉及用户隐私或账户安全。
已知问题