从零配置qiankun微前端框架,会逐步完善更丰富的功能。
2024-06-04 | 基础配置,开发环境启动实现微前端效果 |
1、使用vue-cli构建三个vue2项目,分别为app-admin、app-shop、app-pay,其中app-admin是主应用基座,app-shop和app-pay是子应用。
2、主应用配置
2.1 安装qiankun依赖
npm install qiankun
2.2 src资源文件下创建qiankun文件夹,添加app.js、index.js、IndexView.vue三个文件,具体代码:
app.js
// 添加子应用的配置信息 // 子应用列表 const apps = [ { name: 'appshop',// 子应用的app name 推荐与子应用的package的name一致 entry: 'http://localhost:8082/' , // 子应用的入口地址,就是子应用运行起来的地址 container: '#container', // 挂载子应用内容的dom节点 activeRule: '/appshop', // 子应用的路由前缀 props: { // 主应用向子应用传递的参数 time: new Date().getTime() }, }, { name: 'apppay',// 子应用的app name 推荐与子应用的package的name一致 entry: 'http://localhost:8083/' , // 子应用的入口地址,就是子应用运行起来的地址 container: '#container', // 挂载子应用内容的dom节点 activeRule: '/apppay', // 子应用的路由前缀 props: { // 主应用向子应用传递的参数 time: new Date().getTime() }, } ] export default apps
index.js
import { addGlobalUncaughtErrorHandler, registerMicroApps, start } from "qiankun"; // 微应用信息 import apps from './app' /** * 注册微应用 * 第一个参数: 微应用的注册信息, * 第二个参数: 全局生命周期钩子 */ registerMicroApps(apps, { // qiankun 生命周期钩子, 微应用加载前 beforeLoad: (app) => { // 加载微应用前,加载进度条 console.log('before load ==== ', app.name) return Promise.resolve() }, afterMount: (app) => { console.log('after mount====', app.name) return Promise.resolve() } }) /** * 添加全局的未捕获异常处理器 */ addGlobalUncaughtErrorHandler((event) => { console.error(event) const { message: msg } = event; if(msg && msg.includes('died in status LOADING_SOURCE_CODE')) { console.error('微应用加载失败') } }) // 导出 qiankun 的start函数,启动函数 export default start
IndexView.vue
<template> <div> <!-- 渲染微应用的容器 --> <div id="container"></div> </div> </template>
2.3 在src下创建router文件夹,在router文件夹下创建index.js文件
index.js
import Vue from 'vue' import VueRouter from 'vue-router' import HomeView from '../views/HomeView' Vue.use(VueRouter) const routes = [ { path: '/', name: 'home', component: HomeView }, { path: '/appshop/*', name: 'appshop', component: () => import("../qiankun/IndexView.vue") }, { path: '/apppay/*', name: 'apppay', component: () => import("../qiankun/IndexView.vue") } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
2.4 在src下创建store文件夹,暂未使用
2.5 在src下创建views文件夹,新建HomeView.vue文件,用来作为主应用首页
<template> <div> <div>主应用展示的内容</div> </div> </template> <script> export default { name: 'HomeView', components: { }, created(){ console.log('初始化home') }, methods: { } } </script> <style scoped> </style>
2.6 App.vue文件调整
<template> <div id="app"> <div style="margin-bottom: 50px;"> <router-link to="/">主应用</router-link> <router-link to="/appshop/">appShop应用</router-link> <router-link to="/apppay/">apppay应用</router-link> </div> <router-view /> </div> </template> <script> export default { name: 'App' } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
2.7 main.js 文件调整
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' // 引入qiankun文件 import start from '@/qiankun' start() Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
2.8 vue.config.js 调整,如果没有此文件则创建即可。
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, devServer: { port: 8081 }, })
3 、子应用配置
子应用无需安装qiankun依赖
3.1 src下创建router文件夹,router文件夹下 创建index.js
index.js
import Vue from 'vue' import VueRouter from 'vue-router' import HomeView from '../views/HomeView' Vue.use(VueRouter) const routes = [ { path: '/', name: 'home', component: HomeView } ] const router = new VueRouter({ mode: 'history', base: window.__POWERED_BY_QIANKUN__ ? '/apppay/' : '/', routes }) export default router
3.2 src下创建store文件夹,暂未用到
3.3 src下创建views文件夹,views文件夹下创建HomeView.vue作为子应用的首页
HomeView.vue
<template> <div> <div>展示app-pay子项目</div> </div> </template> <script> export default { name: 'HomeView', components: { }, created(){ console.log('开始初始化子应用app-pay') }, methods: { } } </script> <style scoped> </style>
3.4 App.vue
<template> <div id="app"> <router-view /> </div> </template> <script> export default { name: 'App' } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
3.5 main.js 文件修改
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' // 引入public-path文件 import "./public-path"; Vue.config.productionTip = false // 定义一个Vue实例 // let router = null let instance = null // 渲染方法 function render(props = {}) { const { container } = props instance = new Vue({ router, store, render: (h) => h(App) }).$mount(container ? container.querySelector('#app'): '#app', true) } // 独立运行时 if(!window.__POWERED_BY_QIANKUN__) { render() } //暴露主应用生命周期钩子 /** * bootstrap : 在微应用初始化的时候调用一次,之后的生命周期里不再调用 */ export async function bootstrap() { console.log('这里是app-app应用 bootstraped'); } /** * mount : 在应用每次进入时调用 */ export async function mount(props) { // props是主应用传递的值 console.log('这里是app-app应用', props); render(props); } /** * unmount :应用每次 切出/卸载 均会调用 */ export async function unmount() { console.log("这里是app-app应用 unmount") instance.$destroy(); instance.$el.innerHTML = ''; instance = null; }
3.6 src文件夹下添加public-path.js文件
if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; }
3.7 package.json添加配置
"globals": { "__webpack_public_path__": true }
文件整体内容如下:
{
"name": "apppay",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.8.3",
"vue": "^2.6.14",
"vue-router": "^3.6.5"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {},
"globals": {
"__webpack_public_path__": true
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
3.8 vue.config.js文件修改,如果没有则创建
const { defineConfig } = require('@vue/cli-service') const path = require('path') module.exports = defineConfig({ transpileDependencies: true, devServer: { port: 8083, headers: { 'Access-Control-Allow-Origin':'*' } }, publicPath: 'http://localhost:8083/', // webpack配置 configureWebpack: { output: { library: 'apppay', libraryTarget: 'umd', // chunkLoadingGlobal: `webpackJsonp_${name}` }, resolve: { alias: { '@@': path.resolve(__dirname, 'src/assets/img'), 'views': path.resolve(__dirname, 'src/views'), '_c': path.resolve(__dirname, 'src/components') } } } })
4.9 另一个子应用也如此修改。
5、启动三个服务,访问及操作效果
npm run serve