docs/docs/blog/mfsu-independent-usage.md
MFSU 支持独立在非 umijs 项目中使用,本文将会介绍如何将 MFSU 接入你的 webpack 项目。
如何接入 MFSU ?提供以下几个 示例项目 配置供参考:
Webpack 配置示例:<a href="https://github.com/umijs/umi/tree/master/examples/mfsu-independent" target="_blank">examples/mfsu-independent</a>
CRA v5 配置示例:<a href="https://github.com/umijs/cra-v5-with-mfsu-example" target="_blank">cra-v5-with-mfsu-example</a>
首先安装 mfsu 的依赖:
pnpm add -D @umijs/mfsu
配置 MFSU 一共需要简单的四步操作,请确保以下所有行为都只在开发环境生效。
第一步,初始化一个 MFSU 实例,这是 MFSU 的基础:
// webpack.config.js
const { MFSU } = require('@umijs/mfsu');
const webpack = require('webpack');
// [mfsu] 1. init instance
const mfsu = new MFSU({
implementor: webpack,
buildDepWithESBuild: true,
});
第二步,添加 MFSU 的 devServer 中间件到 webpack-dev-server 中,他将为你提供 MFSU 所需打包后的资源:
// webpack.config.js
module.exports = {
devServer: {
// [mfsu] 2. add mfsu middleware
setupMiddlewares(middlewares, devServer) {
middlewares.unshift(...mfsu.getMiddlewares());
return middlewares;
},
},
};
// webpack.config.js
module.exports = {
devServer: {
// [mfsu] 2. add mfsu middleware
onBeforeSetupMiddleware(devServer) {
for (const middleware of mfsu.getMiddlewares()) {
devServer.app.use(middleware);
}
},
},
};
第三步,你需要配置一种源码转换器,他的作用是用来收集、转换依赖导入路径,替换为 MFSU 的模块联邦地址(中间件所提供的)。
此处提供两种方案:babel plugins 或 esbuild handler ,一般情况下选择 babel plugins 即可。
向 babel-loader 添加 MFSU 的 babel plugins 即可。
// webpack.config.js
module.exports = {
module: {
rules: [
// handle javascript source loader
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [
// [mfsu] 3. add mfsu babel plugins
...mfsu.getBabelPlugins(),
],
},
},
},
],
},
};
另一种方案是使用内置提供的 esbuild-loader 来处理 js/ts 资源,仅用于开发环境 。
:::info
<strong>使用这种方案的好处是</strong>:在开发环境获得比 babel 更快的编译和启动速度
:::
// webpack.config.js
const { esbuildLoader } = require('@umijs/mfsu');
const esbuild = require('esbuild');
module.exports = {
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: {
loader: esbuildLoader,
options: {
handler: [
// [mfsu] 3. add mfsu esbuild loader handlers
...mfsu.getEsbuildLoaderHandler(),
],
target: 'esnext',
implementation: esbuild,
},
},
},
],
},
};
:::warning <strong>什么时候我不应该使用 esbuild 方案?</strong>
babel plugins 必须在开发环境使用css-in-js 的开发环境友好类名(一般由 babel plugin 提供支持)esbuild-loader 的成本大于配置 babel plugins 的成本
:::第四步,调用 MFSU 提供的方法改变你的 webpack 配置,在这里只有增量行为,你无需担心会影响到你原来的配置内容。
如下代码所示,mfsu.setWebpackConfig 是一个异步方法,为了调用他你需要将原来的 webpack 配置单独抽为一个对象 config 之后,再将调用此方法的返回值导出。
// webpack.config.js
const config = {
// origin webpack config
};
const depConfig = {
// webpack config for dependencies
};
// [mfsu] 4. inject mfsu webpack config
const getConfig = async () => {
await mfsu.setWebpackConfig({
config,
depConfig,
});
return config;
};
module.exports = getConfig();
到此为止,MFSU 完全配置完毕,下面可以开始启动项目使用。
进行完 4 步配置后,启动你的项目,你可以从项目根目录得到 .mfsu 文件夹,即 MFSU 缓存文件夹,请将其添加到 git 的忽略列表(这些缓存文件你不应该提交他们):
# .gitignore
.mfsu
符合预期时,你已经可以享受 MFSU 带来的好处,包括 esbuild 快速的打包和二次热启动的提速。
以下是其他你可能会用到的 MFSU 实例配置:
const mfsu = new MFSU({
cwd: process.cwd(),
});
其他 Options:
| option | default | description |
|---|---|---|
cwd | process.cwd() | 项目根目录 |
getCacheDependency | () => {} | 用返回值来对比,使 MFSU cache 无效的函数 |
tmpBase | ${process.cwd()}/.mfsu | MFSU 缓存存放目录 |
unMatchLibs | [] | 手动排除某些不需要被 MFSU 处理的依赖 |
runtimePublicPath | undefined | 同 umijs > runtimePublicPath |
implementor | undefined | webpack 实例,需要和项目内使用的唯一实例一致 |
buildDepWithESBuild | false | 是否使用 esbuild 打包依赖 |
onMFSUProgress | undefined | 获取 MFSU 编译进度的回调 |
使用环境标识避免所有 MFSU 在生产环境构建时的配置侵入:
const isDev = process.env.NODE_ENV === 'development'
const mfsu = isDev
? new MFSU({
implementor: webpack,
buildDepWithESBuild: true,
})
: undefined
// e.g.
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [
...(isDev ? [] : mfsu.getBabelPlugins())
]
}
}
}