这两天 公司往后有个新项目 是这么这么个需求:
主项目 需要能引入各种项目整合 于是了解到了微前端
第一天先是深入挖掘 qiankun 这个框架 玩了一天结果无法满足我们公司的一些场景 果断放弃
第二天了解到了 京东的全新框架
但是很不幸 子项目的路由比较复杂 我们的需求是 主项目的某个区域 直接加载子项目的某个vue 组件显示
就好比直接在vue项目中 components
创建了一个 组件 然后在App.vue 引入这样
于是研究了半天 对子项目进行了改造 (后面会说具体实现!!!)
最终效果如下:
先看下原理图(左部分)
在附上一张子项目打包后的文件
将每个入口通过nginx 代理web请求
只需要在通过microApp 标签正常定义即可
接下来开始说具体实现:
首先创建两个项目
- micro-main (主项目)
- micro-children (子项目)
(这边直接省略创建项目的过程 使用的是vue 脚手架 最新的vue2)
micro-main
主应用需要安装依赖
npm i @micro-zoe/micro-app --save
创建完后初始化micro-app 编辑main.js
贴身代码 方便复制
// =============引入micro依赖==============
import microApp from '@micro-zoe/micro-app'
microApp.start()
Vue.config.productionTip = false
const app =new Vue({
router,
render: h => h(App)
}).$mount('#app')
// 卸载应用
window.unmount = () => {
app.$destroy()
}
// ==========================================
然后在编辑 vue.config.js
加上 这两行 (当然这个不是重点 主要是为了解决打包后页面空白的问题)
publicPath: './',
assetsDir: 'static'
ok 主应用就这样 接下来 打开子应用项目
micro-children
先看下子项目改造后的结构
第一步 比如我需要两个子组件
- 侧边栏
- 顶部栏
然后分别写这两个组件 放在components文件夹
如上图
第二步
复制main.js 并命名为 header.js
sidebar.js
废话不多说
我这边贴上我的代码
/*header.js 顶部栏*/
import Vue from 'vue'
// 引入刚才的顶部栏组件
import App from '@/components/Header.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.config.productionTip = false
const app =new Vue({
router,
render: h => h(App)
}).$mount('#app')
// 卸载应用
window.unmount = () => {
app.$destroy()
}
侧边栏 sidebar.js
同理
/*sidebar.js 侧边栏*/
import Vue from 'vue'
// 引入刚才的侧边栏组件
import App from './components/SideBar.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.config.productionTip = false
const app =new Vue({
router,
render: h => h(App)
}).$mount('#app')
// 卸载应用
window.unmount = () => {
app.$destroy()
}
这边提一嘴 官方的配置 我就直接贴图 想了解的可以直接去看官网
- 开启umd模式,优化内存和性能
重点是 vue.config.js
这个文件
const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 必须加上
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
},
},
publicPath: './',
assetsDir: 'static',
pages: {
// 原有的index入口 可有可无
// index: {
// entry: './src/main.js',
// template: 'public/index.html',
// filename: 'index.html',
// title: '首页',
// },
//
// 声明侧边栏入口文件
sidebar: {
entry: './src/sidebar.js',
template: 'public/index.html',
filename: 'sidebar.html',
title: '侧边栏',
},
// 声明顶部栏入口文件
header: {
entry: './src/header.js',
template: 'public/index.html',
filename: 'header.html',
title: '头部',
},
},
})
至此改造完成
对 子项目 进行打包
npm run build
等待片刻 打包成功!!!
浏览器打开网页看看效果
这个时候 可以开始配置nginx
我直接 将打包后的文件放在我的这个目录下
\
打开nginx 的配置文件 nginx.conf
配置代理 和 跨域
nginx)
location /likefr {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
root html/;
try_files $uri.html $uri $uri/ =404;
}
- try_files 不了解的小伙伴可以上百度查查
最后记得刷新nginx 的配置
nginx -s reload
验证下是否生效
浏览器 请求
ip + nginx代理路径 + 之前我们的子项目打包后的路由名
成功访问
接着回到我们的主项目
在你的vue中 加入 初始化micro-app标签
侧边栏
<micro-app name='sidebar' url='http://192.168.5.208/likefr/sidebar.html' disable-memory-router @datachange="sidebarHandler"></micro-app>
顶部栏
<micro-app name='header' url='http://192.168.5.208/likefr/header.html' disable-memory-router @datachange="headerHandler"></micro-app>
最终效果
2024-08-05T05:58:54.png
附上主项目完整代码
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
created() {
this.$router.push('/')
}
}
</script>
<style>
*, body {
margin: 0;
padding: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
width: 100vw;
height: 100vh;
}
</style>
HomeView.vue
<template>
<div class="home">
<el-container>
<el-header>
<micro-app name='header' url='http://192.168.5.208/likefr/header.html' disable-memory-router @datachange="headerHandler"></micro-app>
</el-header>
<el-container>
<el-main>
<!-- <router-view/>-->
<el-button @click="navbar">
发送消息给顶部栏
</el-button>
<el-button @click="sidebar">
发送消息给顶侧边栏
</el-button>
</el-main>
<el-aside width="200px">
<micro-app name='sidebar' url='http://192.168.5.208/likefr/sidebar.html' disable-memory-router @datachange="sidebarHandler"></micro-app>
</el-aside>
</el-container>
<el-footer>
<el-tabs type="border-card" style="height: 238px">
<el-tab-pane label="用户管理">用户管理</el-tab-pane>
<el-tab-pane label="配置管理">配置管理</el-tab-pane>
<el-tab-pane label="角色管理">角色管理</el-tab-pane>
<el-tab-pane label="定时任务补偿">定时任务补偿</el-tab-pane>
</el-tabs>
</el-footer>
</el-container>
</div>
</template>
<script>
import microApp from "@micro-zoe/micro-app";
export default {
name: 'HomeView',
data() {
return {
count: 0
}
},
methods: {
navbar() {
this.count++
// 发送数据给子应用 my-app,setData第二个参数只接受对象类型
microApp.setData('header', {msg: '111111111111111' + this.count})
},
sidebar() {
this.count++
// 发送数据给子应用 my-app,setData第二个参数只接受对象类型
microApp.setData('sidebar', {msg: '222222222222222' + this.count})
},
// 处理收到的数据
headerHandler(e) {
this.$message.success('主应用收到顶栏数据' + JSON.stringify(e))
},
sidebarHandler(e) {
this.$message.success('主应用收到侧栏数据' + e)
}
}
}
</script>
<style>
.el-header {
padding: 0 !important;
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-footer {
padding: 0 !important;
background-color: #B3C0D1;
text-align: center;
height: 240px !important;
}
.el-aside {
background: #D3DCE6;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
width: 100%;
height: calc(100vh - 60PX - 240PX);
}
</style>
"感谢大家阅读本文,希望能对大家有所帮助,同时,也欢迎大家留下宝贵的意见和建议,如果你对本文有更好的想法 随时可以提出 我很乐意接收更好的创意!让我们共同进步,共同成长。祝大家学习进步,工作顺利"
参考文献