cassiehuang / study

学习笔记整理
2 stars 0 forks source link

Single-spa #60

Open cassiehuang opened 3 years ago

cassiehuang commented 3 years ago

systemjs

运行于浏览器端的模块加载器,将我们整个应用的所需要的js文件,都以imports的形式引入进来 使用方法一: System.import('./test.js'); 使用方法二:

  1. 写一个配置文件,给每个资源定义一个key { "imports": { "vue": './public/vue.js', "single-spa": './public/single-spa.js' } }
  2. 引入配置文件
  3. 引入文件 System.import(key)

single-spa实践

结构目录设计

---common ---projects ---root_html_file -----index.html 引入index.js, systemjs,single-spa, -----index.js -----registry --------public_dependents.json --------singleSpa_project.json

index.js

(async function() {
  var System_imports = [
    System.import('./single-spa.js'),
    System.import('./frame.js')
  ];
  Promise.all(System_imports).then((modules) => {
    var SingleSpa = modules[0];
    var Frame = modules[1];

    SingleSpa.registerApplication(
      'frame',
      Frame,
      () => true
    )
    SingleSpa.start();

    window.addEventListener('INIT_FRAME', function() {
      const arr = Object.keys(SINGLE_SPA_PROJECTS);
      arr.forEach((project) => {
        if (project !== 'frame') {
          SingleSpa.registerApplication(
            project,
            () => System.import(SINGLE_SPA_PROJECTS[project]),
            location => location.pathname.indexOf('/' + project) === 0
          )
        }
      })
    })
  })
})()
cassiehuang commented 3 years ago

projects/app1代码分析

1、vue.config.js

module.exports = {
  chainWebpack: config => {
    config.devServer.set('inline', false)
    config.devServer.set('hot', true)
    config.output.filename(`js/[name].js`)
    config.externals(['vue', 'vue-router', 'vuex', 'element-ui'])
  },
  filenameHashing: false,
  productionSourceMap: false
}

2、set-public-path.js import { setPublicPath } from ''systemjs-webpack-interop' setPublicPath('app1', 2) 是为了解决webpack构建时,资源设置publicPath,加载时会认为是当前页面的路径,实际上对于app1而言,路径应该是相对于app1的路径,通过这个设置,可以设置为正确的路径 在main.js开头引入 3、main.js

import './set-public-path'
import Vue from 'vue'
import App from './App.vue'
import I18n from './i18n'
import SingleSpaVue from 'single-spa-vue'

const vueLifecycles = new SingleSpaVue({
  Vue,
  appOptions: {
    el: '#single-spa-projects',
    i18n: I18n,
    store: Store,
    router: Router,
    render: h => h(App),
  }
})
// singleSpa生命周期有两种写法
// 应用初始
export const bootstrap = vueLifecycles.bootstrap
//应用挂载
export function mount(props) {
  return vueLifecycles.mount
}
//应用卸载
export const unmount = VueLifecycles.unmount
cassiehuang commented 3 years ago

微前端方案需要解决的问题

1、子应用如何定义和使用 2、 如何动态加载 3、如何隔离

解决子应用如何定义和使用(singleSpa)

1、registerApplication(name, app, activeRule) app支持实例也支持访问地址 2、start() 启动主项目 3、bootstrap, mount, unmount等子应用生命周期方法,bootstrap里面将子应用html加载到主项目dom下 4、子应用需要暴露声明周期方法

隔离

1、快照沙箱 就是在子应用加载、启动之后,记录一下当时的快照状态,在子应用unmount的时候,恢复为原来的全局状态 2、

qiankun解决了后两个问题

1、qiankun支持传入html地址或者前端资源地址,在执行 js 资源时通过 eval