0.1.3 • Published 4 years ago

asm-service v0.1.3

Weekly downloads
7
License
ISC
Repository
-
Last release
4 years ago

基于 single-spa 的微前端框架

解决了 single-spa 没有解决的微前端项目资源加载的问题,到资源加载失败时,提供重新加载资源的方法。

asm-service将每个项目的 html 作为 entry 得到这个项目的 js,css 资源,然后将 js,css 插入到 document 中

安装

npm i asm-service --save

基本用法

import AsmService from 'asm-service'

new AsmService([
  {
    name: 'xxx', // 项目名
    projectIndex: 'http://xxxx.com', // 项目访问入口
    base: false, // 是否需要一直在页面中显示
    path: '#/body', // 项目显示条件。可以是数组
    routeMode: 'hash', // 路由模式
  },
]).start()

子项目配置

字段类型是否必填可选值默认值描述
nameString--项目名
projectIndexString--项目访问入口
baseBooleantrue,falsefalse是否需要一直在页面中显示
pathString,Array-[]项目的显示条件,当 base 为 true 时,path 的值会被忽略
routeModeStringhash,historyhash路由模式。 routeMode 和 path 配合使用来确认项目的显示与否
domIDString-''项目要挂载的 dom 节点的 id 属性
customPropsObject-{}各个生命周期要传递到项目的自定义属性

AsmService 实例

start 方法

start 方法用于 启动 AsmService, start 方法可以接受一个对象作为参数,它返回一个 promise

AsmService.start(opts)

opts 对象的属性

属性名类型是否必填可选值默认值描述
fetchFunction-window.fetch@hydesign/grape 通过 fetch 函数来获取项目访问入口对应的 html 文档,fetch 函数必须返回一个 promise
repeatNumNumber-1当使用 fetch 获取项目的 html 失败之后,重新获取的次数
repeatIntervalNumber-2000当使用 fetch 获取项目的 html 失败之后,再次获取间隔的毫秒数

setImportMap 方法

当需要将各个项目的公共库从项目代码中抽离出来统一管理,setImportMap 方法会很有用处。setImportMap 与 webpack externals 配合使用可以抽离出项目中不想打包的库,在项目运行时使用到这个库的时候再动态加载,setImportMap 的用法见下文

apps

如果想要得到 AsmService 中所有的 app 的信息你可以通过 apps 属性得到,apps 的值不能从外部修改

AsmService.apps

app 的状态

  • NOT_LOAD: 还没有开始加载 app 的资源
  • LOADING: 正在加载 app 的资源
  • LOAD_ERROR: app 的资源加载失败
  • LOADED: app 的资源加载成功
  • REGISTERED: app 注册成功
  • REGISTER_ERROR: app 注册失败

高级用法

除了可以通过实例化 AsmService 对象时传入一系列 app,然后调用 start 的方式去注册 app,也可以调用 AsmService 的 loadApp 方法去注册 app。

import AsmService from 'asm-service'

new AsmService().start()

AsmService.loadApp({
  name: 'xxx', // 项目名
  projectIndex: 'http://xxxx.com', // 项目访问入口
  base: false, // 是否需要一直在页面中显示
  path: '#/body', // 项目显示条件。可以是数组
  routeMode: 'hash', // 路由模式
})

可以在AsmService启动之后的任何时候调用AsmService.loadApp

调用AsmService.loadApp注册 app 时,它会做如下判断:

  1. 这个 app 是否已经加入到 AsmService.apps 中,如果没有,将这个 app 加入 apps 中,并且加载 app 的资源,最后注册 app。
  2. 这个 app 的资源是否加载失败或者 app 是否注册失败,如果失败了,则重新加载资源,然后注册 app
  3. 这个 app 已经注册成功,这个方法什么都不会做

如果 app 已经加入到 AsmService.apps 中, 调用 AsmService.loadApp 会使用 AsmService.apps 队列中的 app 的 projectIndex 去加载资源。

设置子项目的生命周期函数

import vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'
const vueLifecycles = singleSpaVue({
  Vue: vue,
  appOptions: {
    el: '#main',
    render: (h) => h(App),
    router,
  },
})

export const bootstrap = vueLifecycles.bootstrap
export const mount = vueLifecycles.mount
export const unmount = vueLifecycles.unmount

给子项目的入口 js 加标识

经过打包工具(如:webpack)打包之后一个项目在 index.html 中插入的 js 脚本可能不只一个,所以为了确保@hydesign/grape能够正确的从项目中解析到入口 js,给入口 js 文件加上一个 entry 属性,如果所有的 js 脚本都没有 entry 属性,AsmService会将 index.html 的中最后一个脚本当作入口 js

const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
plugins:[
    ...
    new ScriptExtHtmlWebpackPlugin({
      custom: {
        test: /app.*\.js$/,
        attribute: 'entry',
        value: true
      }
    })
  ]

将子项目打包成 umd 格式

output: {
    ...
    libraryTarget: 'umd',
    library: xxx,
}

setImportMap 方法与 webpack external 配合

AsmServicewebpack的 externals 配合使用,能够抽离出项目中不想打包的库,并且在项目运行当使用到这个库的时候在动态加载。

 externals(['vue',{'vue-router':'vueRouter'},{'element-ui':'elementUI'},'axios', {'asm-client':'asmClient'}])
import AsmService from 'asm-service'

new AsmService(appsConf)
  .setImportMap({
    vue: 'https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js',
    vueRouter:
      'https://cdn.jsdelivr.net/npm/vue-router@3.0.7/dist/vue-router.min.js',
    elementUI: 'https://cdn.jsdelivr.net/npm/element-ui@2.12.0/lib/index.js',
    Vuex: 'https://cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
    axios: 'https://cdn.jsdelivr.net/npm/axios@0.19.0/dist/axios.min.js',
  })
  .start()
0.1.2

4 years ago

0.1.3

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago