
本系列大纲
- 微前端模块联邦实践系列(1) - 微前端入门
- 微前端模块联邦实践系列(2) - 微前端与模块联邦
- 微前端模块联邦实践系列(3) - 第一个案例
- 微前端模块联邦实践系列(4) - subApp之间共享libraries
- 微前端模块联邦实践系列(5) - Path to Production
- 微前端模块联邦实践系列(6) - 集成React & Vue
- 微前端模块联邦实践系列(7) - 路由管理
- 微前端模块联邦实践系列(8) - 消息通信
Webapck module federation作为Run-time Integration的一种实现方式,由于每个子项目在运行时动态加载,那么每个子项目也必须满足单独开发、单独部署的原则。
因此本文中,主要讲解如何进行各个项目的CI/CD。
注:本文中各个项目目前是组织在一个文件夹下的,只是为了方便管理,如果是不同团队维护,完全是可以分开作为三个不同的项目来管理的。
本文使用的是Vercel这个专注于前端开发与部署的云平台,使用的是free plan,只是每个月有固定限额,国内可能要FQ才能使用。如果无法科学上网,可以使用国内的某些云代替,比如阿里云、腾讯云等等,另外如果实在没有可以薅的羊毛,本文最后也提供一种在本地部署的方式。
持续集成工具采用的是 github workflow,用于在代码push之后,进行持续集成与部署。
deploy workflow (posts/albums/container)
整个app的持续集成与部署主要分为以下步骤
- posts (albums) 生产环境的打包配置文件
// apps/posts/config/webpack.prod.js (albums类似)
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ModuleFederationPlugin } = require('webpack').container
const packageJson = require('../package.json')
module.exports = {
mode: 'production',
output: {
filename: '[name].[contenthash].js',
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
}),
new ModuleFederationPlugin({
name: 'posts',
filename: 'remoteEntry.js',
exposes: {
'./PostsIndex': './src/bootstrap',
},
shared: packageJson.dependencies,
}),
],
}
生产环境中,主要将mode从development变成了production,这样webpack在打包时,会采用一系列生产环境的预设方式来进行打包,主要包括代码压缩、混淆,优化chunk文件的拆分和按需加载等等。
目前运行build之后,会在当前目录生成dist文件夹,如果你的代码组织方式和我不一样,出现了路径访问不对的情况,可以尝试修改webpack -> output -> publicPath来达到相同目的,这里不再深入讲解。
- container的生产环境配置
container的webpack配置与上述的基本相同,只是需要动态地去配置两个子app的domain
// apps/container/config/webpack.prod.js
new ModuleFederationPlugin({
name: 'container',
remotes: {
postsApp: `posts@${process.env.MFE_POSTS_DOMAIN}remoteEntry.js`,
albumsApp: `albums@${process.env.MFE_ALBUMS_DOMAIN}remoteEntry.js`,
},
shared: packageJson.dependencies,
})
两个domain从环境变量里面来,在子app部署之后,会生成对应的域名。
- 添加打包命令
// apps/posts/package.json (albums/container类似)
"scripts": {
"serve": "webpack serve --config config/webpack.dev.js",
"build": "webpack --config config/webpack.prod.js"
}
- 编写workflow
## .github/workflows/deploy-posts.yaml (albums/container类似)
name: Deploy Posts App
env:
VERCEL_ORG_ID: ${{ secrets.MFE_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.MFE_POSTS_PROJ_ID }}
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'apps/posts/src/**'
jobs:
Deploy-Production:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./apps/posts
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: vercel pull --yes --environment=production --token=${{ secrets.MFE_ACCESS_TOKEN }}
- name: Build Posts Project Artifacts
run: vercel build --prod --token=${{ secrets.MFE_ACCESS_TOKEN }}
- name: Deploy Posts Project Artifacts to Vercel
run: vercel deploy --prebuilt --prod --token=${{ secrets.MFE_ACCESS_TOKEN }}
编写完成之后,以后再推送代码到main分支之后,就会自动触发build以及deploy to vercel的操作。这里有几点是说明一下
- 代码中需要的secrets需要在项目的settings中配置,记住是项目的settings中,不是个人账户的settings
- 如果你也可以使用vercel,那么你还需要几个ID:
org_id,proj_id以及access_token,如何获取可以参照这里- vercel.com/guides/how-…
- 如何使用vercel CLI进行部署,可以参照这里:vercel.com/guides/how-…
一切部署完成后,在vercel的控制台会看到3个不同的app
workflows
Local deploy
如果你没有免费的羊毛可以薅,那么可以尝试本地部署,方法类似。这里我采用 http-server 在不同的端口起了3个web服务,使用 pm2 进行apps管理。
编写local-deploy.sh
#!/bin/bash
# startup posts app
cd apps/posts
npm install
npm run build
cd dist
pm2 start http-server --name "posts" -- -p 4201 -d ./ --cors
sleep 2
cd ../../
# startup albums app
cd albums
npm install
npm run build
cd dist
pm2 start http-server --name "albums" -- -p 4202 -d ./ --cors
sleep 2
cd ../../
# startup container app
cd container
npm install
MFE_POSTS_DOMAIN=http://localhost:4201/ MFE_ALBUMS_DOMAIN=http://localhost:4202/ npm run build
cd dist
pm2 start http-server --name "container" -- -p 4200 -d ./
cd ../../../
pm2 status
配置package.json的scripts
"scripts": {
"deploy:local": "chmod +x ./local-deploy.sh && ./local-deploy.sh",
"deploy:stop:all": "pm2 stop all",
"deploy:delete:all": "pm2 delete all",
"deploy:restart:all": "pm2 restart all"
}
运行npm run deploy:local之后
最后在localhost:4200可以访问到最后的网页