什么是qiankun
qiankun是蚂蚁开源的基于single-spa的一款微前端框架,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
- 技术栈无关 主框架不限制接入应用的技术栈,微应用具备完全自主权
- 独立开发、独立部署 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
- 增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略- 独立运行时 每个微应用之间状态隔离,运行时状态不共享
qiankun解决了什么问题
qiankun比起single-spa的优势在于
- 基于single-spa上层封装,保留single-spa能力的同时增加了丰富的API。
- 内置🧳JS沙箱保证为应用之间不会产生冲突。
- 📦样式隔离避免了不同应用之间的样式污染问题。
- 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
怎么使用qiankun
主应用
主应用与技术栈无关,可以使用任何框架,我们选用Vue,初始化一个Vue项目
安装
终端输入命令行
npm install -S qiankun 复制代码
注册微应用
在main.js中注册所有的微应用
const apps = [ { name: 'qiankun-app1', // 应用名称 entry: '//localhost:8000', // 入口 container: '#vue', // 挂载点 activeRule: '/vue', // 匹配路径 }, { name: 'qiankun-app2', entry: '//localhost:3000', container: '#react', activeRule: '/react', }, ] registerMicroApps(apps) start(); new Vue({ router, render: h => h(App) }).$mount('#app') 复制代码
然后修改App.vue,删除无用代码,为了美观使用Element-UI的导航栏组件
<div> <el-menu :router="true" mode="horizontal"> <el-menu-item index="/">Home</el-menu-item> <el-menu-item index="/vue">Vue</el-menu-item> <el-menu-item index="/react">React</el-menu-item> </el-menu> <router-view></router-view> <div id="vue"></div> <div id="react"></div> </div> 复制代码
需要安装vue-router插件,注意要使用history模式
const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) 复制代码
主应用的改造已经基本完成
微应用
vue
对于Vue框架微应用的改造主要有两点,配置跨域和暴露要求的方法
首先新建一个vue.config.js,并添加以下代码用来配置跨域(生产环境下需要对Nginx配置跨域),而且对默认webpack配置的output做出修改,library就是之前注册微应用的名称
module.exports = { devServer: { port: 8000, headers: { 'Access-Control-Allow-Origin': '*' } }, configureWebpack: { output: { library: 'qiankun-app1', libraryTarget: 'umd', } } } 复制代码
然后对main.js进行改造,如果有需要,微应用可以脱离主应用独立运行,通过window.__POWERED_BY_QIANKUN__
来判断运行环境
let instance = null function render(props) { props instance = new Vue({ router, render: h => h(App) }).$mount('#app'); // 这里是挂载到自己的html中 基座会拿到这个挂载后的html 将其插入进去 } if (window.__POWERED_BY_QIANKUN__) { // 动态添加publicPath __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; // eslint-disable-line } if (!window.__POWERED_BY_QIANKUN__) { // 默认独立运行 render(); } // 子组件的协议就ok了 export async function bootstrap(props) { props } export async function mount(props) { render(props) } export async function unmount(props) { props instance.$destroy() } 复制代码
最后还有一点,要将微应用的路由添加base,基于当前微应用的主路由,在这里就是/vue
const router = new VueRouter({ mode: 'history', base: '/vue', routes }) 复制代码
react
react项目的改造方式思路一直,但做法不太一样,react的webpack配置作为一个黑盒存在,我们要改变默认配置需要将配置暴露出来,那样会再增加很多没有必要的代码,我们还可以通过react-app-rewired
来修改默认配置
首先使用npm或者yarn添加依赖,然后将package.json中的执行脚本替换
然后在根目录添加一个配置文件config-overrides.js,配置的内容跟vue应用的一致
module.exports = { webpack:(config)=>{ config.output.library = 'qiankun-app2'; config.output.libraryTarget = 'umd'; config.output.publicPath = 'http://localhost:3000/'; return config; }, devServer:(configFunction)=>{ return function (proxy,allowedHost){ const config = configFunction(proxy,allowedHost); config.headers = { "Access-Control-Allow-Origin":'*' } return config } } } 复制代码
然后到index.js中改造项目,同样是需要导出三个生命周期
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')); } 复制代码
使用react-router-dom添加几个路由,这里同样的要设置basename
function App() { return ( <BrowserRouter basename="/react"> <Link to="/">首页</Link> <Link to="/about">关于</Link> <Route path="/" exact render={() => ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> )}></Route> <Route path="/about" render={() => <h1>about页面</h1>}></Route> </BrowserRouter> ); } export default App; 复制代码
分别将项目运行起来,去浏览器里看一下效果