vue-cli、ts + single-spa + systemJs 实现微前端

微前端架构是一种相似于微服务的架构,它将微服务的理念应用于浏览器端,即将Web应用从单一的单体应用转变为由多个小型前端应用聚合为一的应用。 现阶段实现微前端的方式大体有如下六种:javascript

  1. 使用 HTTP 服务器的路由来重定向多个应用
  2. 在不一样的框架之上设计通信、加载机制,诸如 MooaSingle-SPA
  3. 经过组合多个独立应用、组件来构建一个单体应用
  4. iFrame。使用 iFrame 及自定义消息传递机制
  5. 使用纯 Web Components 构建应用
  6. 结合 Web Components 构建

这次实践,采用的是Single-SPA的加载机制,具体以下。css

项目架构

总体架构html

内项目 做用
portal 最上层路由分发框架
menu 导航栏
cooper 主体项目
projects 有自定义西项目
.gitignore git提交忽略配置
readme.md 说明文档

框架之上的通信机制

portal: 路由分发机制源头,systemJs 和 single-spa 的使用。前端

portal项目启动为服务时,port设置成为了8233。vue

systemJs: 是一个 通用模块加载器,支持AMD、CommonJS、ES6等各类格式的JS模块加载,也是Angular2官推的加载器。因此该微前端实例,支持跨技术(react、angular)模块加载。java

single-spa: 是一个可让使用多个javascript语言框架的构建的应用集成在一块儿的框架。react

<script type="systemjs-importmap">{...}</script>
复制代码

用来导入能够须要引入的第三方模块,和插件。这里的config.js、single-spa.min.js、styles.css都是以HTTP形式引入,是为了不后续的路由问题,由于该html将做为模板直接复用。webpack

使用systemjs引入的方式git

System.import('@portal/config')
复制代码

引入single-spa模块web

registerApplication(名称,引入路径,是否引入)
singleSpa.start()启用
复制代码

用来判断某一模块是否引入

menu: 页面跳转

由于整个项目都是用vue写的,因此路由跳转这块用的是vue-router。

举例:

<router-link to="/index" />
复制代码

cooper: 页面响应 ***子项目由于使用vue-cli写的,因此 必定要引入vue-cli-plugin-single-spa插件,不然子项目的single-spa钩子没法正常exports。

vue项目中,先建立router.ts 举例:

import index from 'views/index/index.vue'

export default [{
    path: '/index',
    name: 'index',
    component: index
}, ...]
复制代码

在app.vue 中

<router-view />
复制代码

那为何不一样项目之间路由会相应呢?

全部独立项目都是以single-spa的形式打包输出,并引入到portal架构下的,经systemjs引入以后,至关与是在portal下运行的一个项目,http衔接到了localhost:8233下。所以,在独立项目中引用图片、css文件是,也须要已http形式引入。避免合并到portal下后,路劲找不到的问题。

单一应用入口文件配置

cooper/projects/menu: 入口文件配置

由于要打包成single-spa的形式,因此入口文件会有所不一样。

入口文件main.ts

import Vue from 'vue'
import singleSpaVue from 'single-spa-vue'
import App from './App.vue'
import store from './store'
import router from './router'

const vueLifecircle = singleSpaVue({
    Vue,
    appOption: {
        el: '#vue',
        render: r => r(App),
        store,
        router
    }
})
复制代码

App.vue

<template>
    <div id="vue">
        <keep-alive>
            <router-view />
        </keep-alive>
    </div>
</template>
...
复制代码

webpack配置明细

项目single-spa形式输出配置

以menu为例的独立项目打包配置vue.config.js

const path = require('path')
module.exports = {
    chainWebpack: config => {
        config.entryPoints.clear()
        config.entry('menu').add('./src/main.ts').end()
        config.output.filename('menu.js').library('menu').libraryTarget('amd').end()
        config.devServer.port(8001).headers({
            "Access-Control-Allow-Origin": "*"
        })
    },
    outputDir: path.resolve(__dirname, 'dist/')
}
复制代码

输出的入口文件是menu.js,以AMD形式打包,缘由:single-spa是AMD形式,因此也是在portal项目中会引用amd.js的缘由。

portal项目打包配置

webppapck.config.config.js

module.export = {
    entry: './src/config',
    output: {
        filename: 'config.js',
        library: 'config',
        libraryTarget: 'amd',
        path: path.resolve(__dirname, 'build')
    },
    ...
    plugins: [
        CopyWebpackPlugin([
            {form: path.resolve(__dirname, 'src/index.html')},
            {from: path.resolve(__dirname, 'src/style.css')},
            {from: path.resolve(__dirname, 'common-deps-static')}
        ])
    ]
}
复制代码

打包后项目运行

只须要启动一个服务指向portal,其余子项目均放在portal目录下,以静态js文件形式引入。

子项目状态共享

能够把全部子项目的公共依赖所有提取,统一放到Portal层,已静态文件形式引入。一样,也能够把Vue、VueRouter、Vuex率先在portal层System.import(),而且注册为可用。详细细节后续会再整理一篇文档做为讲解。

相关文章
相关标签/搜索