基于vue-typescript-admin-element的微前端中后台应用

本项目是对于vue-typescript-admin-element中后台框架的改造,利用微前端框架qiankun,将原本完整的单页应用进行独立子应用的分割。
基于vue-typescript-admin-element的微前端中后台应用_第1张图片

技术栈简介

vue-typescript-admin-element框架为业内广泛使用的中后台框架vue-admin-element的typescript版本。

qiankun是一个在single-spa微前端框架基础二次封装的更为易用的微前端框架。在single-spa基础上增加了js沙盒,html加载解析等。

主应用

所谓主应用,就是所有子应用的容器,用于渲染子应用的外框。
基于vue-typescript-admin-element的微前端中后台应用_第2张图片

main.ts

import Vue from 'vue'

import 'normalize.css'
import ElementUI from 'element-ui'
import SvgIcon from 'vue-svgicon'

import '@/styles/element-variables.scss'
import '@/styles/index.scss'

import App from '@/App.vue'
import store from '@/store'
import router from '@/router'
import '@/icons/components'
import '@/permission'

import QiankunVue from '@/plugins/qiankun-vue'

Vue.use(ElementUI)
Vue.use(SvgIcon, {
  tagName: 'svg-icon',
  defaultWidth: '1em',
  defaultHeight: '1em'
})
// 插件的加载
Vue.use(QiankunVue)

const qiankunVue = new QiankunVue([
  {
    name: 'dashboard',
    entry: '//localhost:5001',
    activeUrl: '/dashboard'
  },
  {
    name: 'example',
    entry: '//localhost:5002',
    activeUrl: '/example'
  }
])

Vue.config.productionTip = false

new Vue({
  router,
  store,
  qiankunVue,
  render: (h) => h(App)
}).$mount('#main')

本项目中,已经将qiankun封装成了一个vue的标准插件。在实例化时需要传入子项目的注册信息。

framework.vue
用于渲染子项目的容器



子应用

vue-dashboard和vue-example为两个子项目,其中主要的改变是vue.config.js和main.ts的改动。

vue.config.js

const path = require('path')
const { name } = require('./package')
const cors = require('cors')
const port = 5002

module.exports = {
  devServer: {
    port,
    /* headers: {
      'Access-Control-Allow-Origin': '*',
    }, */
    before(app, server) {
      app.use(cors())
    }
  },
  publicPath: process.env.NODE_ENV === 'production' ? '/vue-typescript-admin-template/' : `//localhost:${port}`, // TODO: Remember to change this to fit your need
  lintOnSave: process.env.NODE_ENV === 'development',
  pwa: {
    name: name
  },
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'scss',
      patterns: [
        path.resolve(__dirname, 'src/styles/_variables.scss'),
        path.resolve(__dirname, 'src/styles/_mixins.scss')
      ]
    }
  },
/*   configureWebpack: {
    output: {
      // 把子应用打包成 umd 库格式
      library: `${name}-[name]`,
      libraryTarget: 'umd',
      jsonpFunction: `webpackJsonp_${name}`,
    }
  }, */
  chainWebpack(config) {
    // Provide the app's title in webpack's name field, so that
    // it can be accessed in index.html to inject the correct title.
    config.set('name', name)
    config.plugin("html").tap(args => {
      args[0].minify = false;
      return args;
    });
    // 把子应用打包成 umd 库格式
    config.output
      .jsonpFunction(`webpackJsonp_${name}`)
      .library(`${name}-[name]`)
      .libraryTarget('umd')
  }
}

devServer:这个开发模式下的服务需要允许跨域请求。因为,在微前端项目中,子项目通常都是独立部署到一个独立域名服务下,父项目在拉取子项目资源时,均为跨域访问。虽然在生产环境中,你可以通过配置反向代理等方式来规避跨域,但在开发环境下直接开放跨域访问最为简便。

publicPath:需要配置全域名访问。因为,子项目在运行时,自身会进行很多异步资源加载,如css和异步组件加载等,如果配置相对路径,会导致,子项目加载资源时,访问的是父项目的域名,导致资源加载不到。

umd打包配置:子项目必须用umd打包的方式输出,否则qiankun框架无法正确解析。

main.ts

import Vue from 'vue'

import 'normalize.css'
import ElementUI from 'element-ui'
import SvgIcon from 'vue-svgicon'

import '@/styles/element-variables.scss'
import '@/styles/index.scss'

import App from '@/App.vue'
import store from '@/store'
import router from '@/router'
import '@/icons/components'
import '@/permission'

Vue.use(ElementUI)
Vue.use(SvgIcon, {
  tagName: 'svg-icon',
  defaultWidth: '1em',
  defaultHeight: '1em'
})

Vue.config.productionTip = false

let app: Vue | undefined = undefined

export async function bootstrap() {
  console.log('example应用初始化')
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props: any) {
  Vue.prototype.$isFramework = props.isFramework
  Vue.prototype.$mainApp = props.mainInstance
  if (!app) {
    app = new Vue({
      router,
      store,
      render: (h) => h(App)
    })
  }
  app.$mount('#app')
  props.callback(app)
}

/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载子应用的应用实例
 */
export async function unmount() {
  console.log('example应用卸载')
  // 销毁
  if (app) {
    app.$destroy()
    app = undefined
  }
}

mount函数:当子项目加载时会调用的此函数。因此,需要在此函数中进行vue的实例化。

unmount函数:档子项目切换时,需要将当前的项目进行销毁。

项目地址:https://github.com/Hades-li/vue-ts-admin-microApp

你可能感兴趣的:(vue.js,微前端,typescript,element-ui)