乾坤 vs 无界
背景:
- 需要拆解巨石项目
- 新模块需要独立部署、运行
- 新模块需要在巨石项目中集成
- 许多业务功能重复,需要提纯、共享
- 兼容IE11
不是无界不好,是我处理不了IE中iframe弹窗的问题,我反而最喜欢的是无界的方案,接入成本真的太低了,用起来很爽,如果不用考虑IE,我觉得无界是一个非常不错的选择。
接入乾坤
子应用
// public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
// main.js
import './public-path'
...
let instance = null
const render = (props = {}) => {
// mf的代码先别管
const { container, moduleFederations } = props
setModuleFederationList({ mfs: moduleFederations })
instance = new Vue({
render: hx => hx(App),
router,
}).$mount(container ? container.querySelector('#children-01') : '#children-01')
}
// 独立运行
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
// 生命周期
export async function bootstrap() {
console.log('[vue] vue app bootstraped')
}
export async function mount(props) {
console.log('[vue] props from main framework', props)
render(props)
}
export async function unmount() {
console.log('[vue] vue app unmount')
instance.$destroy()
instance.$el.innerHTML = ''
instance = null
}
// webpack.config.js (webpack 5)
...
output: {
// 出口文件
path: process.cwd() + '/dist',
publicPath: isDev ? '/' : '/v/xxx/',
filename: 'js/[name].[hash:8].js',
clean: true,
library: `micro-xxx`,
libraryTarget: 'umd',
chunkLoadingGlobal: `webpackJsonp_${name}`,//这个是webpack5 更新的属性 之前是jsonpFunction
},
...
基座应用
我单独封装了一层,可以按照文档直接用
npm install qiankun -D
// register-micro-app.js
import { loadMicroApp } from 'qiankun'
const isDev = process.env.NODE_ENV === 'development'
const microApps = {
'micro-app-xxx': {
name: 'micro-xxx',
entry: isDev
? '//localhost:8889'
: `${window.location.protocol}//${window.location.host}/v/xxx/`,
container: '#xxx',
activeRule: '/v/micro/xxx',
configuration: {
// sandbox: { strictStyleIsolation: true },
sandbox: false,
},
},
}
/**
* @returns microApp:Object
* mount(): Promise<null>;
* unmount(): Promise<null>;
* update(customProps: object): Promise<any>;
* getStatus(): | "NOT_LOADED" | "LOADING_SOURCE_CODE" | "NOT_BOOTSTRAPPED" | "BOOTSTRAPPING" | "NOT_MOUNTED" | "MOUNTING" | "MOUNTED" | "UPDATING" | "UNMOUNTING" | "UNLOADING" | "SKIP_BECAUSE_BROKEN" | "LOAD_ERROR";
* loadPromise: Promise<null>;
* bootstrapPromise: Promise<null>;
* mountPromise: Promise<null>;
* unmountPromise: Promise<null>;
*/
const registerMicroApp = ({ name, moduleFederations }) => {
return loadMicroApp({ ...microApps[name], props: { moduleFederations } })
}
export default registerMicroApp
// demo.vue
...
<div class="micro-content" id="cooperation" />
...
import registerMicroApp from '@/register-micro-app'
...
// 在合适的位置上使用
this.microApp = registerMicroApp({
name: 'micro-app-cooperation-space',
// 这里暂时不用管
moduleFederations: {
'koala/demo2': showDemoModal,
},
})
以上,基本上可以看到子应用在基座应用中显示了
坑
官方文档给出的
先看看,能解决一大部分问题
element-ui 与 ant-design-vue 样式冲突
需要注意ant-design-vue的版本不同,dist/antd.less可能不一样
// design 与 view等老项目样式冲突,这里将原要引入的ant-design-vue/dist/antd.less借助reset进行一个套壳,限定范围
*[class*='ant-'] {
@import 'ant-design-vue/lib/style/index.less';
@import 'ant-design-vue/lib/style/components.less';
html,
body {
padding: 0;
margin: 0;
font-family: Arial, 'PingFangSC-Regular', 'microsoft yahei', '微软雅黑', 'Hiragino Sans GB',
sans-serif;
-moz-osx-font-smoothing: '-moz-osx-font-smoothing';
-webkit-font-smoothing: antialiased;
background-color: #f6f7fa;
}
...
}
**!!!以下问题,只针对我的项目,可能不具备通用性
IE兼容 es6语法兼容问题
# IE11报“SCRIPT445: 对象不支持此操作”,怎么破?
//main.js
...
import 'regenerator-runtime/runtime'
import 'js/lib/base64-polyfill'
...
ie [qiankun]: Target container with #cooperation not existed while micro-cooperation mounting!
这个问题,官方有方案,但是我按照文档没有成功,最后使用loadMicroApp替代registerMicroApps解决
Uncaught Error: only one instance of babel-polyfill is allowed
项目中引入Vue CDN,在webpack中external,子应用、基座应用都是如此,会报这个错,将子应用index.html/entry.html 中的script标签增加ignore 属性即可
报错忘记了。。。😅
只找到这个问题链接 里面说明了问题的方案 总结: js引入顺序问题,子应用打包后,css文件在最后,js倒数第二,会有问题
新版本的
html-webpack-plugin默认会将编译的 js 产物放到 head 标签尾部,并添加defer属性,这会导致 qiankun 在应用加载方面产生问题(qiankun 的生命周期 js entry 需要放在页面 js 资源的末尾,即顺序排在最后),尤其当 html 文件底部自己有额外引入 js 文件的情况,一定会出问题。在
html-webpack-plugin配置中添加参数inject: 'body'搞定。 如果你的编译产物已经是在</body>结束标签前,那么无需处理。
// 子应用
// webpack.config.js
plugins: [
new HtmlWebpackPlugin({
// 自动插入到dist目录中
title: 'micro01',
template: './index.html',
inject: 'body',//这里,能够将子应用打包的js放到body中
isDev,
}),
....
]
额。。。先记录到这,希望能够帮到大家
其实还有很多,解决之后都忘记了,上面的也是我搜索记录查出来的,如果后面想起来,继续更新。说实话有点后悔,边改边记录就对了,主要是IE恶心,还有webpack5 我是升级上来的,也解决了不少问题。
下一篇将接入Module Federation