前言
webpack5新功能 - Module Federation - 模块联邦
Motivation
所谓概念,就是看了中文想看英文,看了英文想看中文,看了n遍,仍旧不知道在说啥的一段话。
Multiple separate builds should form a single application. These separate builds should not have dependencies between each other, so they can be developed and deployed individually.
This is often known as Micro-Frontends, but is not limited to that.
多个独立的构建可以组成一个应用程序,这些独立的构建之间不应该存在依赖关系,因此可以单独开发和部署它们。
这通常被称作微前端,但并不仅限于此。
先搞清楚几个概念
- webpack构建 一个独立项目通过webpack打包编译而产生资源包
-
remote 一个暴露模块供其它
webpack构建
消费的webpck构建
-
host 一个消费其它remote模块的
webpack构建
所以就是一堆独立的构建,如果你想让别人用你的模块,就暴露出来,你也可以用别人暴露出来的模块。彼此之间没有依赖。
案例
1. remote
先创建一个应用,vue3.0脚手架搭的一个工程。
module federation是webpack5的新功能,所以依赖的webpck版本得升到5(@vue/cli-service的依赖里面有webpack)
...
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0-rc.1",
"@vue/cli-plugin-eslint": "~5.0.0-rc.1",
"@vue/cli-service": "~5.0.0-rc.1",
...
- name 应用名,全局唯一,不可冲突。
- exposes 远程应用暴露出的模块名。
-- vue.config.js
const webpack = require('webpack')
const { ModuleFederationPlugin } = webpack.container
module.exports = {
configureWebpack: {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: "remoteEntry.js",
exposes: {
"./date": "./src/utils/date.js"
}
})
]
}
}
启动项目,打开network可以看到生成的remoteEntry.js
2. host
- exposes 声明需要引用的远程应用。
-- vue.config.js
const webpack = require('webpack')
const { ModuleFederationPlugin } = webpack.container
module.exports = {
configureWebpack: {
plugins: [
new ModuleFederationPlugin({
name: 'app2',
remotes: {
"app1": "app1@http://localhost:8081/remoteEntry.js"
}
})
]
}
}
...
import {formatDate} from 'app1/date'
...
console.log(formatDate('1994-12-15'))
...
这个时候直接启动项目,控制台会有报错,看network也没有加载remoteEntry.js
这边就涉及到一个概念
我们区分本地模块和远程模块。本地模块即为普通模块,是当前构建的一部分。远程模块不属于当前构建,并在运行时从所谓的容器加载。
加载远程模块被认为是异步操作。当使用远程模块时,这些异步操作将被放置在远程模块和入口之间的下一个 chunk 的加载操作中。如果没有 chunk 加载操作,就不能使用远程模块。
chunk 的加载操作通常是通过调用 import() 实现的,但也支持像 require.ensure 或 require([...]) 之类的旧语法。
我们需要异步加载远程模块
-- main.js
import ('./bootstrap')
-- bootstrap.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
这时候network里面可以看到已经加载了remoteEntry.js,但是控制台仍有报错
打包后,通过http-server启动却是成功的,可以看到控制台输出了日期
npm run build
cd dist
http-serve -p8081
怀疑是vue-cli的npm run serve做了啥导致不支持模块联邦
下一章,我们不用vue-cli,直接用webpack来搭一个应用作为remote
Z. 参考
模块联邦
Module Federation
module-federation-examples
精读《Webpack5 新特性 - 模块联邦》
微前端实践--webpack5模块联邦
Module federation allows a JavaScript application to dynamically run code from another bundle/build, on both client and server.
Webpack5 新特性模块联邦介绍和应用
2021年12月8日始
2021年12月13日发布第一稿
2021年12月14日更新