single-spa结合vue项目初探

single-spa结合vue项目初探

本次案例以vue-element-admin为例,验证single-spa的可接入性。根据single-spa的官网介绍,推荐将项目的所有文件(包括图片和css)等文件全部打包入一个js文件。但是这样我们原来的分包等打包优化都会变得没有意义,那么为什么要全部打入一个包呢?

因为single-spa的接入是以入口js文件接入的,而不是入口html文件,这样一来就会导致一些资源加载路径的错误,从而导致无法正常显示,但也并不是完全不可以。下面将一步步一起尝试。

安装依赖

我们需要安装几个依赖来方便接入single-spa

npm install -save single-spa-vue
npm install -save systemjs-webpack-interop  // 根据需要引入

配置文件

首先修改vue-element-admin的一些文件,首先是main.js,这里只列举新增的代码块,其余保持不变,唯一需要变得是删除Vue实例化的部分(即 new Vue(…))。

import "./set-public-path";
import singleSpaVue from "single-spa-vue";

const vueLifecycles = singleSpaVue({
     
  Vue,
  appOptions: {
     
    render: h => h(App),
    router,
    store
  }
});

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

然后在main.js同级目录下添加set-public-path.js文件,这个文件的作用是可以简化文件的引用路径,这样在项目跑起来后就可以方便引入打包后的文件(只是在运行时简化),如果是先打包后引入的话就不需要这个文件。

import {
      setPublicPath } from "systemjs-webpack-interop";

setPublicPath("vueAdmin", 2);

修改vue.config.js

这里修改打包方式,这部分是我尝试过之后可用的打包方式,暂且以这个为例。

// 只保留如下 chainWebpack 配置,其余的删除
 chainWebpack: config => {
      // 保留原项目处理svg的loader
    config.devServer.set("inline", false);
    config.devServer.set("hot", true);
    config.module
      .rule("svg")
      .exclude.add(resolve("src/icons"))
      .end();
    config.module
      .rule("icons")
      .test(/\.svg$/)
      .include.add(resolve("src/icons"))
      .end()
      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({
     
        symbolId: "icon-[name]"
      })
      .end();
    // config.externals(['vue', 'vue-router']) 如果是在外部统一引入则开启这行
  },
  filenameHashing: false // 禁用hash文件名

然后执行命令打包,我这里是打包到dist目录下,这里显示++的都是打包后手动新增的文件

└─static
    ├─fonts
    ├─img
    ├─js
    └─static ++
        ├─fonts ++
        ├─img ++
        └─js ++

添加single-spa项目

新建一个文件夹执行npm init

然后修改pakage.json内容如下

{
     
  "name": "single-spa",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
     
    "serve": "serve -s -l 5000"
  },
  "devDependencies": {
     
    "serve": "^11.3.2"
  },
  "author": "",
  "license": "ISC"
}

新建index.html

文件中vueAdmin的路径为vue项目打包后的dist目录下起的服务


<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Coexisting Vue Microfrontendstitle>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="importmap-type" content="systemjs-importmap" />
    <script type="systemjs-importmap">
      {
      
        "imports": {
      
          "single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.7/system/single-spa.min.js",
          "vueAdmin": "http://10.118.37.41:8080/static/js/app.js"
        }
      }
    script>
    <link
      rel="preload"
      href="https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.7/system/single-spa.min.js"
      as="script"
      crossorigin="anonymous"
    />
    <script src="https://unpkg.com/[email protected]/dist/import-map-overrides.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/system.min.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/extras/amd.min.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/extras/named-exports.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/extras/named-register.min.js">script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.1.1/extras/use-default.min.js">script>
  head>
  <body>
    <script>
      (function () {
      
        System.import("vueAdmin").then((res) => {
      
          console.log(res);
        });
        Promise.all([System.import("single-spa")]).then(function (modules) {
      
          var singleSpa = modules[0];
          singleSpa.registerApplication(
            "vueAdmin",
            () => System.import("vueAdmin"),
            (location) => true
          );
          singleSpa.start();
        });
      })();
    script>
    
    <import-map-overrides-full
      show-when-local-storage="overrides-ui"
    >import-map-overrides-full>
  body>
html>

然后执行npm run serve就可以在浏览器中看到效果,并且是按需加载

结论:以js入口的方式并不是不可以分包加载,只不过需要我们修改打包出来的文件的文件夹层级

你可能感兴趣的:(微前端,node.js,javascript)