微前端
视频笔记:www.bilibili.com/video/BV1Dt…
参考链接: juejin.cn/post/695944…
为什么要使用微前端
- 项目大打包慢
- 多人协作冲突
- 团队技术栈不同
- 每个团队可以独立开发、独立部署
- 项目中还需要老的应用代码,需要使用新的技术栈
将一个应用划分成若干个子应用,将子应用打包成一个个的lib。当路径切换时加载不同的子应用。这样每个子应用都是独立的,技术栈也不用做限制。从而解决了前端协同开发问题。
应用通信
- 基于URL来进行数据传输,但是传输消息能力弱
- 基于CustomEvent实现通信
- 基于Props主子应用通信
- 使用权限变量、redux进行通信
公共依赖
- CDN – extends
- webpack联邦模块
为什么不是iframe?
- 如果不考虑体验问题,iframe几乎是最完美的微前端解决方案。
- iframe最大的特性就是提供了浏览器原生的硬隔离方案,无论是样式隔离、JS隔离这些问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
-
url不同步,浏览器刷新iframe url状态丢失,后退前进按钮无法使用。
single-SPA
- 问题:父子应用,平级应用样式、js冲突
- 实现了路由截止、路由加载
- 接入协议:子应用必须提供bootstrap、mount、unmount方法
子应用
-
新建子应用
vue create child-vue 注意: 使用history路由 复制代码 -
安装single-spa-vue
npm install singe-spa-vue 复制代码 -
修改src目录下的main.js文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 1. 首先引入single-spa-vue
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false
// 2. 新建一个对象,而不是实例化Vue
const appOptions = {
el: '#vue', //挂载父应用中的id为vue的标签中
router,
render: h => h(App)
}
// 3. singleSpaVue包裹
const vueLifeCycle = singleSpaVue({
Vue,
appOptions
})
// 5. 父应用引用我, 不加这个,默认跳转父应用的理由
if(window.singleSpaNavigate){
__webpack_public_path__ = 'http://localhost:10002/'
}
// 6. 子应用独立运行,当前不是作为子应用的情况
if(!window.singleSpaNavigate){
delete appOptions.el
new Vue(appOptions).$mount('#app')
}
//4. 协议接入,父应用会调用这些方法
export const bootstrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount
复制代码
-
将子应用打包成一个lib
首先需要在根目录下创建一个vue.config.js文件
module.exports = {
configureWebpack: {
output: {
library: 'singleVue',
library: 'umd' // 最后将数学挂载到window上
},
devServer: {
port: 10000
}
}
}
复制代码
父应用
-
创建父应用
vue create parent-vue
注意:使用history路由
-
安装single-spa
npm install single-spa
-
修改src目录下的app.vue文件
<template>
<div id="app">
<div id="nav">
<router-link to="/vue">加载Vue应用</router-link> |
</div>
<!--子应用挂载的位置-->
<div id="vue"></div>
</div>
</template>
复制代码
- 修改src目录下的main.js文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 1. 引入注册子应用方法和启动方法
import { registerApplication, start} from 'single-spa'
Vue.config.productionTip = false
async function loadScript(url){
return new Promise((resolve, reject)=>{
let script = document.createElement('script')
script.src = url
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script)
})
}
// 2.注册子应用
registerApplication('myVueApp',
async ()=>{
await loadScript('http://localhost:10002/js/chunk-vendors.js')
await loadScript('http://localhost:10002/js/app.js')
return window.singleVue
},
location => location.pathname.startsWith('/vue'),
)
// 3. 启动
start();
new Vue({
router,
render: h => h(App)
}).$mount('#app')
复制代码
single-spa的缺点
- 不能动态加载js
- 样式不隔离
- 全局变量没有js沙箱机制
子应用之间的样式隔离
主应用和子应用之间的样式隔离
- 约定项目前缀
- css-modules 打包时生成不冲突的选择器名
- Shadow DOM 样子dom 真正意义上的隔离(developer.mozilla.org/zh-CN/docs/…
- css-in-js
JS的隔离
A应用给window加属性window.a, B应用也可以访问window
单应用切换,沙箱 创建一个干净的环境,切换时可以删除属性和恢复属性
js沙箱
- 快照沙箱 1年前拍一张,再拍一张,作对比,将区别保存起来
blog.csdn.net/qq_33226029…
多个子应用不能使用这种方式 - 代理沙箱 es6 proxy
- 把不同的应用用不同的代理实现
- qiankuan源码实现js隔离的方式
qiankun
- 技术栈无关,任意技术栈的应用均可使用/接入,不论是React/Vue/Angular/Jquery还是其他框架;
- HTML Entry接入方式,让你接入微应用像使用iframe一样简单;
- 样式隔离, 确保微应用之间样式互相不干扰;
- JS沙箱, 确保微应用之间[全局变量/事件]不冲突;
- 资源预加载, 在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度;
- umi插件, 提供了@umijs/plugin-qiankun供umi应用一键切换成微前端系统。
项目实施
新建基座qiankuan-base
- 安装qiankuan
npm install qiankuan
2. 修改src目录下的main.js文件
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.config.productionTip = false
// 1. 引入qiankun
import {registerMicroApps, start} from 'qiankun'
// 2. 创建路由数组
const apps = [
{
name : 'vueApp', //应用的名字
entry: 'http://localhost:20000', //子应用支持跨域
container: '#vue', //挂载容器
activeRule: '/vue', //激活的路径
props: {a: 1}
},
{
name : 'reactApp',
entry: 'http://localhost:30000', //子应用支持跨域
container: '#react',
activeRule: '/react',
}
]
// 3. 注册子应用路由
registerMicroApps(apps) //注册应用
// 4. 启动
start({
prefetch: false //取消预加载
}) //启动
new Vue({
router,
render: h => h(App)
}).$mount('#app')
复制代码
新建子应用qiankuan-vue
新建子应用qiankuan-react
- 安装react-app-rewired
npm install react-app-rewired
- 修改根目录下的package.json文件
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
复制代码
- 在根目录新建config-overrides.js文件
module.exports = {
webpack: (config) => {
config.output.library = 'reactApp';
config.output.libraryTarget = 'umd'
config.output.publicPath = "http://localhost:30000"
return config
},
devServer: (configFunction) => {
return function(proxy, allowedHost){
const config = configFunction(proxy, allowedHost);
config.headers = {
'Access-Control-Allow-Origin': '*'
}
return config;
}
}
}
复制代码
- 修改src目录下的index.js文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
function render(){
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
}
if(!window.__POWERED_BY_QIANKUN__){
render()
}
export async function bootstrap(){}
export async function mount(){
render()
}
export async function unmount(){
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
复制代码
- 启动qiankun-react子应用
npm run start
从零实现一个微前端框架
初始化开发环境
- 新建一个文件夹my-single-spa
- 初始化: 执行命令npm init -y
会生成一个package.json文件
{
"name": "my-single-spa",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
复制代码
- 安装打包工具rollup
- npm install rollup
- rollup相对于webpack的好处是:打包出来的代码比较简洁
- 安装rollup-plugin-serve
- npm install rollup-plugin-serve
- 该工具可以启动应用
- 根目录下新建配置文件rollup.config.js
import serve from 'rollup-plugin-serve'
//rollup可以帮我们打包 es6模块化语法
export default {
input : './src/single-spa.js', //指定入口文件
output: {
file: './lib/umd/single-spa.js', //指定出口文件
format: 'umd', //指定挂载到window
name: 'singleSpa',
sourcemap: true
},
plugins: [
serve({ //服务
openPage: '/index.html', //默认打开的页面
contentBase: '',
port: 3000
})
]
}
复制代码
- 根目录下新建入口文件夹src
- 根目录下新建index.html文件
- 修改根目录下的配置文件package.json
"scripts": {
"dev": "rollup -c -w"
},
复制代码
以上完成rollup环境的搭建
应用加载状态-生命周期
喜欢就支持一下吧
相关推荐








![iOS-[渲染原理]-一一网](https://www.proyy.com/skycj/data/images/2022-03-25/b4ded4049bd62599ecaa6f2e8f3993dd.jpg)














![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)