这两天 公司往后有个新项目 是这么这么个需求:

主项目 需要能引入各种项目整合 于是了解到了微前端

第一天先是深入挖掘 qiankun 这个框架 玩了一天结果无法满足我们公司的一些场景 果断放弃

第二天了解到了 京东的全新框架

转自官网

但是很不幸 子项目的路由比较复杂 我们的需求是 主项目的某个区域 直接加载子项目的某个vue 组件显示
就好比直接在vue项目中 components创建了一个 组件 然后在App.vue 引入这样

于是研究了半天 对子项目进行了改造 (后面会说具体实现!!!)
最终效果如下:
2024-08-05T05:55:31.png

先看下原理图(左部分)

2024-08-05T05:55:41.png

在附上一张子项目打包后的文件

2024-08-05T05:55:50.png

将每个入口通过nginx 代理web请求

只需要在通过microApp 标签正常定义即可

2024-08-05T05:55:52.png

接下来开始说具体实现:

首先创建两个项目
  • micro-main (主项目)
  • micro-children (子项目)

(这边直接省略创建项目的过程 使用的是vue 脚手架 最新的vue2)

micro-main

主应用需要安装依赖

npm i @micro-zoe/micro-app --save

创建完后初始化micro-app 编辑main.js

2024-08-05T05:56:23.png
贴身代码 方便复制

// =============引入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

2024-08-05T05:56:33.png

加上 这两行 (当然这个不是重点 主要是为了解决打包后页面空白的问题)

  publicPath: './',
  assetsDir: 'static'
ok 主应用就这样 接下来 打开子应用项目

micro-children

先看下子项目改造后的结构

2024-08-05T05:56:40.png

第一步 比如我需要两个子组件

  • 侧边栏
  • 顶部栏
    然后分别写这两个组件 放在 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模式,优化内存和性能

2024-08-05T05:56:52.png


重点是 vue.config.js 这个文件
2024-08-05T05:56:58.png

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
等待片刻 打包成功!!!

2024-08-05T05:57:06.png

浏览器打开网页看看效果

2024-08-05T05:57:10.png

这个时候 可以开始配置nginx

我直接 将打包后的文件放在我的这个目录下
\
2024-08-05T05:57:16.png
打开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代理路径 + 之前我们的子项目打包后的路由名

2024-08-05T05:58:45.png
成功访问

接着回到我们的主项目

在你的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>

"感谢大家阅读本文,希望能对大家有所帮助,同时,也欢迎大家留下宝贵的意见和建议,如果你对本文有更好的想法 随时可以提出 我很乐意接收更好的创意!让我们共同进步,共同成长。祝大家学习进步,工作顺利"

参考文献

Nginx配置跨域请求 Access-Control-Allow-Origin *
MicroApp 常见问题
个人博客

最后修改:2024 年 08 月 27 日
如果觉得我的文章对你有用,请随意赞赏