前端微服务化解决方案6 - 构建与部署
微前端打包构建
微前端项目的打包,是有一些需要注意的点 以 webpack 为例:
amd 模块
在之前的文章,我们有提到我们的加载器,是基于 System.js 来做的. 所以我们微前端的模块最终打包,是要符合模块规范的. 我们使用的是amd模块
规范来构建我们的模块.
指定基础路径
因为模块打包后,调用模块出口文件的,是模块加载器. 为了清晰的管理每个模块,并且正确的加载到我们每一个模块的资源, 我们给模块的资源都指定一个publicPath
.
下面给出一个简单的 webpack 配置,这些配置我只是列出一些必要选项. 并不是一个完整的 webpack 配置,后续我会提供完整的微前端的 Demo,提供大家参考 这些配置都是基于
create-react-app
的配置做的修改. 只要明白了配置的意图,明白我们打包出来的最终是一个什么样的包, 不管打包工具以后怎么变,技术栈怎么变,最后都是可以对接到微前端中来.
这里给出 project.json
的内容,便于后面的配置文件的阅读
// project.json
{
"name": "name", //模块名称
"path": "/project", //模块url前缀
"prefix": "/module-prefix/", //模块文件路径前缀
"main": "/module-prefix/main.js", //模块渲染出口文件
"store": "/module-prefix/store.js",//模块对外接口
"base": true // 是否为baseapp
}
// 引入项目配置文件,也是前面说的 模块加载器必要文件之一
const projectConfig = require('./project.json')
let config = {
entry: {
main: paths.appIndexJs, //出口文件,模块加载器必要文件之一
store: paths.store // 对外api的reducer文件,模块加载器必要文件之一
},
output: {
path: paths.appBuild,
filename: '[name].js?n=[chunkhash:8]',
chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
publicPath: projectConfig.prefix, //在output中指定模块配置好的 publicPath
libraryTarget: 'amd', //对外输出 amd模块,便于 system.js加载
library: projectConfig.name, //模块的名称
},
},
module: {
rules: [
{
oneOf: [
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
// loader: 'happypack/loader?id=url',
loaders: [{
loader: require.resolve('url-loader'),
options: {
limit: 5000,
name: 'static/media/[name].[hash:8].[ext]',
publicPath: projectConfig.prefix, //我们需要在静态文件的loader加上publicPath
},
}]
},
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: 'happypack/loader?id=babel',
options: {
name: 'static/js/[name].[hash:8].[ext]',
publicPath: projectConfig.prefix, //在静态文件的loader加上publicPath
},
},
{
loader: require.resolve('file-loader'),
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
publicPath: projectConfig.prefix, //在静态文件的loader加上publicPath
},
},
],
},
],
},
}
部署
前端单页面的部署,不管怎么自动化,工具怎么变. 都是把打包好的静态文件,放到服务器的正确位置下. 微前端的部署,是一个应用聚合的过程,我们如何把一个个模块最后接入到一个完整的项目中的呢?
微前端应用完整目录
一般会放在一个 nginx 配置好的静态目录里,或者是其他 web 容器的一个静态目录. 看到这个目录结构,你应该能理解为什么要额外的配置 publicPath
了吧.
├── index.html // 首先浏览器会加载这个index.html,html里面会引入一个bootstrap.js的文件
├── bootstrap.js // 这个bootstrap.js是之前说的模块加载器打包过后的代码,
│ // 模块加载器会先加载 `project.config.js`,得到所有模块的配置.
│ // 然后才开始加载每个项目中的main.js文件,注册应用,注入store.js
│
├── project.config.js // 这个文件存到是该项目的所有模块的配置,是代码自动生成的
│ // 之前有提到过项目配置自动化,是这个项目中唯一动态的文件.
│ // 目的是让模块的配置文件更新,或者新增新模块的时候,模块会自动挂载到项目中来
│ // 他会遍历每一个模块的project.json文件,取出内容,合并到一起
│
├── projectA // 模块A目录
│ ├── asset-manifest.json
│ ├── favicon.ico
│ ├── main.js // 渲染用的出口文件
│ ├── manifest.json
│ ├── project.json // 模块的配置文件
│ ├── static
│ │ ├── js
│ │ │ ├── 0.86ae3ec3.chunk.js
│ │ └── media
│ │ └── logo.db0697c1.png
│ └── store.js //对外输出的store.js 文件
└── projectB // 模块B (重要文件的位置,与模块A是一致的)
├── asset-manifest.json
├── main.js
├── manifest.json
├── project.json
├── static
│ ├── js
│ │ ├── 0.86ae3ec3.chunk.js
│ └── media
│ └── logo.db0697c1.png
└── store.js
配置自动化
我们每个模块都有上面所描述的配置文件,当我们的项目多个模块的时候,我们需要把所有模块的配置文件聚合起来. 我这里也有写一个脚本.
使用方法:
npm install micro-auto-config -g
# 在项目根目录,用pm2启动该脚本,便可启动这个项目的配置自动化
pm2 start micro-auto-config --name 你的项目名称-auto-config
这样之后 project.config.js
就会自动生成,以及模块变动之后也会重新生成.
未完待续 …