We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
由于公司老项目基建和业务模式原因,h5移动端有多个项目一起组成,如点击首页跳到page1项目,点击我的跳转到page2项目,而且项目之间跳转不可以通过this.$router.push()进行跳转,只可以暴力的通过window.location.href进行跳转,那么项目之间跳转的交互以及通信就很难接受了。
this.$router.push()
window.location.href
通过调研发现一款基于single-spa进行二次开发的微前端框架qiankun,通过一系列尝试和踩坑,应用于我们h5移动端项目中,这里记录一下基本配置和遇到问题的一些解决方法
single-spa
qiankun
首先我们需要通过vue脚手生成架一个主应用consult-wx-main,以及两个老的vue移动端项目
consult-wx-main
主应用接入qiankun
npm i qiankun
修改vue.config.js
vue.config.js
devServer: { host: "localhost", port: "8080", open: true, disableHostCheck: true, //这个超级重要 headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, DELETE' }, }
需要注意的是这里disableHostCheck必须设置微true
disableHostCheck
然后我们在src目录下添加文件夹micro,里面存放qiankun所需的函数和配置
micro
// src/micro/index.js import { registerMicroApps, addGlobalUncaughtErrorHandler, start, } from "qiankun" import apps from "./apps" registerMicroApps(apps, { // qiankun 生命周期钩子 - 微应用加载前 beforeLoad: () => { // 加载微应用前,加载进度条 return Promise.resolve() }, // qiankun 生命周期钩子 - 微应用挂载后 afterMount: () => { return Promise.resolve(); } }) addGlobalUncaughtErrorHandler((event) => { const { message: msg } = event if (msg && msg.includes("died in status LOADING_SOURCE_CODE")) { alert('微应用加载失败') } }) export default () => { start() } // src/micro/apps.js const apps = [ { name: "page1", entry: "//localhost:10202", container: "#frame", activeRule: "/page1", props: { } }, { name: "page2", entry: "//localhost:10201", container: "#frame", activeRule: "/page2", props: { } }, ]; export default apps;
我们可以看到apps.js就是我们要加载子应用的配置
apps.js
接下来我们修改下main.js
main.js
// main.js import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' import routes from './routes' import startQiankun from "./micro" Vue.use(VueRouter) Vue.config.productionTip = false const router = new VueRouter({ routes, mode: 'history' }) startQiankun() new Vue({ router, render: h => h(App), }).$mount('#main-app')
同样的public/index.html中的id=app也要对应修改为main-app
public/index.html
id=app
main-app
最后,我们修改App.vue,提供路由区域给我们子应用进行加载
App.vue
// App.vue <template> <section class="frame-wrapper"> <!-- 主应用渲染区,用于挂载主应用路由触发的组件 --> <router-view v-show="$route.name" /> <!-- 子应用渲染区,用于挂载子应用节点 --> <section v-show="!$route.name" id="frame"></section> </section> </template> <script> export default { name: "App", }; </script> <style> .frame-wrapper { flex-grow: 1; height: 100%; width: 100%; position: relative; padding-bottom: 72px; } </style>
子应用的设置比较简单,首先修改vue.config.js
// vue.config.js devServer: { host: '0.0.0.0', port: '10201', disableHostCheck: true, //很重要 headers: { 'Access-Control-Allow-Origin': '*', }, open: false, }, configureWebpack: { output: { // 微应用的包名,这里与主应用中注册的微应用名称一致 library: "page2", // 将你的 library 暴露为所有的模块定义下都可运行的方式 libraryTarget: 'umd', // 按需加载相关,设置为 webpackJsonp_VueMicroApp 即可 jsonpFunction: `webpackJsonp_page2`, // 输出重构 打包编译后的 文件名称 【模块名称.版本号.时间戳】 filename: `js/[name].[hash:8].${Timestamp}.js`, chunkFilename: `js/[name].[hash:8].${Timestamp}.js` } }
其中 devServe的端口必须和主应用apps.js中设置的一致,而且output中的library也需要和apps.js中设置的一致
devServe
output
library
然后我们需要在main.js导出qiankun所需要的函数
import "./public-path"; let instance: any = null; function render() { instance = new Vue({ store, router, render: h => h(App) }).$mount('#app') } // 独立运行时,直接挂载应用 if (!window.__POWERED_BY_QIANKUN__) { render(); } /** * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 */ export async function bootstrap() { console.log("VueMicroApp bootstraped"); } /** * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 */ export async function mount(props: any) { console.log("VueMicroApp mount", props); render(props); } /** * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 */ export async function unmount() { console.log("VueMicroApp unmount"); instance.$destroy(); instance = null; } // public-path.js if (window.__POWERED_BY_QIANKUN__) { // 动态设置 webpack publicPath,防止资源加载出错 // eslint-disable-next-line no-undef __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; }
配置路由
export default new Router({ routes, base: window.__POWERED_BY_QIANKUN__ ? "/page2" : "/", mode: 'history' })
到现在为止,基础配置就全部结束了
接入qiankun之后发现子应用的一些第三方sdk出现了跨域问题,如
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
解决方法是将js下载下来,然后在main.js中import就好了
import
对应子应用老项目来说,接口是通过根路径/进行访问的,但是接入qiankun之后,接口路径变为了主应用的/,导致接口报404。这里可以采用两种方法,接口采用绝对路径(可能会发生跨域),还有一种就是主应用进行接口劫持转发,项目中采用的是第二种方法
/
// vue.config.js proxy: { '/consult': { target: 'https://wx.cnhis.zb1.co', changeOrigin: true, ws: true }, '/chat': { target: 'https://wx.cnhis.zb1.co', changeOrigin: true }, '/wx': { target: 'https://wx.cnhis.zb1.co', changeOrigin: true }, }
qiankun给我们提供了一套主子应用通信的方式
qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信,该实例有三个方法,分别是:
initGlobalState
MicroAppStateActions
setGlobalState:设置 globalState - 设置新的值时,内部将执行 浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的 观察者 函数。 onGlobalStateChange:注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。 offGlobalStateChange:取消 观察者 函数 - 该实例不再响应 globalState 变化。
setGlobalState
globalState
onGlobalStateChange
offGlobalStateChange
如果我们子应用之间想进行路由跳转的话,是比较麻烦的,因为配置qiankun的时候固定死了vue-router的base。有两种方法可以实现子应用间的跳转,第一种是重写this.$router.push方法,不走base的那套逻辑
vue-router
this.$router.push
base
另外一种就是现在采用的,将主应用this.$router.push方法传递给子应用,对于需要子应用间跳转的需求,调用主应用的this.$router.push方法就好了
The text was updated successfully, but these errors were encountered:
No branches or pull requests
基于 qiankun 的h5移动端微前端改造踩坑日记
前言
由于公司老项目基建和业务模式原因,h5移动端有多个项目一起组成,如点击首页跳到page1项目,点击我的跳转到page2项目,而且项目之间跳转不可以通过
this.$router.push()
进行跳转,只可以暴力的通过window.location.href
进行跳转,那么项目之间跳转的交互以及通信就很难接受了。通过调研发现一款基于
single-spa
进行二次开发的微前端框架qiankun
,通过一系列尝试和踩坑,应用于我们h5移动端项目中,这里记录一下基本配置和遇到问题的一些解决方法项目升级
首先我们需要通过vue脚手生成架一个主应用
consult-wx-main
,以及两个老的vue移动端项目主应用设置
主应用接入
qiankun
修改
vue.config.js
需要注意的是这里
disableHostCheck
必须设置微true然后我们在src目录下添加文件夹
micro
,里面存放qiankun
所需的函数和配置我们可以看到
apps.js
就是我们要加载子应用的配置接下来我们修改下
main.js
同样的
public/index.html
中的id=app
也要对应修改为main-app
最后,我们修改
App.vue
,提供路由区域给我们子应用进行加载子应用设置
子应用的设置比较简单,首先修改
vue.config.js
其中
devServe
的端口必须和主应用apps.js中设置的一致,而且output
中的library
也需要和apps.js中设置的一致然后我们需要在
main.js
导出qiankun
所需要的函数配置路由
到现在为止,基础配置就全部结束了
踩坑方案
第三方sdk跨域问题
接入
qiankun
之后发现子应用的一些第三方sdk出现了跨域问题,如解决方法是将js下载下来,然后在
main.js
中import
就好了子应用接口路径问题
对应子应用老项目来说,接口是通过根路径
/
进行访问的,但是接入qiankun
之后,接口路径变为了主应用的/
,导致接口报404。这里可以采用两种方法,接口采用绝对路径(可能会发生跨域),还有一种就是主应用进行接口劫持转发,项目中采用的是第二种方法主子应用间通信
qiankun
给我们提供了一套主子应用通信的方式qiankun
内部提供了initGlobalState
方法用于注册MicroAppStateActions
实例用于通信,该实例有三个方法,分别是:setGlobalState
:设置globalState
- 设置新的值时,内部将执行 浅检查,如果检查到globalState
发生改变则触发通知,通知到所有的 观察者 函数。onGlobalStateChange
:注册 观察者 函数 - 响应globalState
变化,在globalState
发生改变时触发该 观察者 函数。offGlobalStateChange
:取消 观察者 函数 - 该实例不再响应globalState
变化。子应用间路由跳转问题
如果我们子应用之间想进行路由跳转的话,是比较麻烦的,因为配置
qiankun
的时候固定死了vue-router
的base。有两种方法可以实现子应用间的跳转,第一种是重写this.$router.push
方法,不走base
的那套逻辑另外一种就是现在采用的,将主应用
this.$router.push
方法传递给子应用,对于需要子应用间跳转的需求,调用主应用的this.$router.push
方法就好了The text was updated successfully, but these errors were encountered: