vue3 + vite + js 使用qiankun微服务创建demo记录总结

993 阅读4分钟

记录一次vue3 + qiankun微服务

需要创建两个应用

没有的用户可以去下载vue-cli的脚手架,直接使用命令下载最新版, 下载完成可以使用vue -V 来进行版本的查看,本次文章不过多赘述工具准备

npm install --global vue-cli

使用 vue create xx 命令 创建工具也可以, 使用vite创建也可以 本次主基座项目使用的是vue3 + vite 创建项目,子应用使用vue3 + vue-cli创建的项目

主基座准备工作: 项目需要安装对应的babel,router4, 其他暂时不需要 子应用准备工作: 项目需要安装对应的babel,router4, 其他暂时不需要

主基座项目:

1.app.vue 这一步主要是为了有跳转的导航,和子应用展示的位置

<div id="nav">

  <!-- 定义导航栏,且激活地址 -->
  <router-link to="/">Home</router-link> |
  <router-link to="/w1">web1</router-link> |
  <router-link to="/w2">web2</router-link>

  <!-- 新增id为box的元素,将web1中的内容插入到box中 子容器 -->
  <div id="box"></div> // 这个元素主要是用于子应用的展示,必须添加,后续需要根据id名称来进行展示

  <!-- container(父容器) -->
  <router-view />
</div>

2.router,创建一个router文件夹并且创建一个index.js来进行router的引入

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../view/Home.vue'
const routes = [
    {
        path: '',
        name: 'home',
        component: Home
    }
]
const router = createRouter({
    history: createWebHashHistory(),
    routes
})
export default router

注意点: 主应用需要使用hash模式来创建路由, 需要创建一个view的文件夹, 然后创建一个home.vue文件用于初始化展示

3.main.js main.js文件主要是用于引入qiankun注册子应用,绑定关系

import { createApp } from 'vue'
import { registerMicroApps, start } from 'qiankun'
import App from './App.vue'
import router from './router/index.js'
import './assets/main.css'
registerMicroApps([
    {
        name: 'web1', //唯一的名字, 子应用的项目名称需要跟这个保持一致
        entry: '//localhost:8083', // 子应用的浏览地址
        container: '#box', // 这个是在app.vue中写的子应用展示的元素id
        activeRule: '#/w1', //入口是hash模式下下的路由地址
        props: {
            appContent: 'use qiankun'
        }
    }
])
start()
createApp(App).use(router).mount('#app')

注意点: 大多时候写完之后发现也不报错,也没有提示,但是也不显示子应用页面,大概率是没有写activeRule的hash模式,如果/w1 这样写的话会无法找到子应用

子应用项目:

子应用项目根据qiankun修改地方较少

1.router 创建方式和父组件保持一致即可, 创建的文件也可直接参照基座应用

import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = createRouter({
  base: window.__POWERED_BY_QIANKUN__ ? '/web1' : '/',
  history: createWebHashHistory(),
  routes
})

export default router

注意点:

1.因为要使用到qiankun微服务,所以需要单独创建一个公共js文件用于保存父基座qiankun服务传过来的标识保存到window上用于区分是父基座项目启动还是单独启动项目.这个属性的value值类型是Boolean

if (window.__POWERED_BY_QIANKUN__) {
    // eslint-disable-next-line no-undef
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}

大部分是和父组件一致的创建组件引入和使用, 但是需要保持都是用hash模式创建路由,这个是重点,base属性使用的文件

2.main.js

import { createApp } from 'vue'
import App from './App.vue'
import './public-path'
import router from './router/index.js'

let instance = null
function render(props = {}) {
    console.log('render')
    const { container } = props
    instance = createApp(App).use(router).mount(container ? container.querySelector('#web1') : '#web1')
}
console.log('ins', window.__POWERED_BY_QIANKUN__)
if (!window.__POWERED_BY_QIANKUN__) { // 用于区分是否是父基座调用
    render()
}
//--------- 生命周期函数------------//
export async function bootstrap() {
    console.log('[vue] vue app bootstraped')
}
export async function mount(props) {
    console.log('[vue] props from main framework', props)
    render(props)
}
export async function unmount() {
    instance.$destroy()
    instance.$el.innerHTML = ''
    instance = null
}

注意点: 重要的是必须要把qiankun的钩子🪝函数写好, 因为父基座项目需要调用的入口是mount函数, 如果没有这个函数,会报错提示找不到项目入口.

推荐看官网问题合集, 问题很多也很全
qiankun.umijs.org/zh/faq

  1. vue.config.js 或者vite.config.js 或者其他ts的config配置
const { defineConfig } = require('@vue/cli-service')
// const { name } = require('./package.json');
module.exports = defineConfig({
  devServer: {
    port: 8083,
    headers: {
      'Access-Control-Allow-Origin': '*'
    }
  },
  configureWebpack: {
    output: {
      library: 'web1',
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      globalObject: 'window'
    },
  },
  transpileDependencies: true
})

主要是做一个固定端口号的改动,和一个修改一个请求头,可以使任意请求浏览器请求不跨域,和一个打包时候的格式, 4. package.json

主要是进行一个name的修改,变成和主基座应用中qiankun注册的name一致即可

  1. index.html

这个也需要同步进行修改成和主基座应用qiankun一样的name, 请勿忘记!!

至此, 全部记录点已经完成, 启动父子项目点击路由即可展示效果

题外话:

进行微服务的拆分关键点是子菜单没有和其他菜单的耦合,相对比较单一,功能性也没有关联,是一个独立的模块.子应用也可单独拆分成项目,使用的技术栈和组件库也可独立.