single-spa的简单介绍与遇到的问题小结

·  阅读 2506

其实本来应该写个介绍的,但是我看到其他的文章写得很完善了,所以就来写写我在其中遇到的一些问题就好了。

安装single-spa请看沉末的这篇文章

背景

简单介绍下背景吧~

为什么要用single-spa呢,是因为公司的项目需要拆项目了,这个时候就需要知道微前端的概念了,那么什么是微前端呢。

微前端服务

微前端架构是一种类似于微服务的架构,由ThoughtWorks 2016年提出,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。

由此带来的变化是,这些前端应用可以独立运行、独立开发、独立部署。

在项目中是运用single-spa去搭建微前端框架的,在搭建框架之前,我们需要知道两个知识点,什么是single-spaimportmap

single-spa

single-spa是一个用于前端微服务化的JavaScript前端解决方案。

特点:

  • (兼容各种技术栈)在同一个页面中使用多种技术框架(React, Vue, AngularJS, Angular, Ember等任意技术框架),并且不需要刷新页面.
  • (无需重构现有代码)使用新的技术框架编写代码,现有项目中的代码无需重构.
  • (更优的性能)每个独立模块的代码可做到按需加载,不浪费额外资源. 每个独立模块可独立运行.

importmap

我们先来看两段代码

import moment from 'moment';
import 'http://momentjs.com/downloads/moment.js';
复制代码

在一个文件中我们写入如上代码,显然第一行是无法正常运行的,第二行是可以正常运行的,但如果我们想要第一行正常运行的话,importmap就可以粉墨登场啦。只需要在html文件书写如下:

<script type="importmap">
    {
        "imports": {
            "moment": "https://momentjs.com/downloads/moment.js",
        }
    }
</script>
复制代码

就可以了。

但是现在浏览器并不支持,想要让它支持的话,需要引入system.js


<script type="systemjs-importmap">
    {
        "imports": {
            "moment": "https://momentjs.com/downloads/moment.js",
        }
    }
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>

复制代码

而在single-spa的使用过程中,我们需要用importmap在根项目中引入所有的模块文件和子项目,从而在其余项目中可以进行模块的引用,就像上面说的那样,可以把moment想象成一个子项目。

single-spa用于将项目打包为可引用的模块。

大家可以看看这个项目,是作者写的关于single-spa的一个例子。

root-config是它的根项目,可以在这里开启该项目。

其他的就不多加介绍了,具体可以看原作者@Joel Denning发的视频,需要🔬上网。

遇到的问题

怎么打开importmap的插件

在浏览器的console中输入

localStorage.setItem('devtools', true);

这个小可爱就出现了。

子项目打包

在微服务的组件引用中,由于运用cdn引入,因此文件需要打包成单一的js文件,而vue-cli3-service(文件路径位于node_modules/_@vue_cli-service@4.3.1@@vue/cli-service/lib/config, 并没有找到github地址)内置了一些webpack配置,在子项目的打包过程中需要把某些配置关掉,并且将其打包成支持system.js的文件,我们需要做如下事情:

  • 将项目打包成可引入的文件
  • 去除代码分割的配置 (代码分割会生成chunk-vendors文件)
  • 去除mini-css-extract-plugin(该插件会将组件中的css抽离出来)

代码如下

> vue.config.js

process.env.VUE_CLI_CSS_SHADOW_MODE = true; // 去除将css从js分出去的配置

module.exports = {
    chainWebpack: config => {
        config.optimization.delete('splitChunks') // 关闭代码分割
        config.output
            .filename('app.js')
            .library('@[library]/[sub-project]')
            .libraryTarget('amd') // 打包方式
            .end()
    }
    ...
}
复制代码

但是上面都是屁话。。。。这些事情其实只要一个插件就可以解决了,原作者写了vue-cli-plugin-single-spa这个插件,直接安装即可。

npm install vue-cli-plugin-single-spa -D

❗️❗️还有一点非常重要,子项目不能采用按需加载加载对应的路由(const [component] = () => import([router]);),应该直接引入(import [component] from [router]),否则会被打包成不同的chunk,无法正常被root-config引入。

子项目的文件路径404了

经过如上的过程打包之后,打包后的文件为/dist/js/app.js,在原作者写的插件中,改写文件路径如下:

就可以了。

假如还是404,可能项目被打包到了不同的路径,需要打开子项目的tab在浏览器中查看文件地址。

element-ui 图标显示不出

需要注意的是vue-cli-plugin-single-spa这个插件并没有处理文字等静态资源,因此尽管npm run build没有显示静态资源被打包成单独的文件,事实上其还是被打包成了静态文件了。解决这个问题最好的方法是把element-ui转化为cdn引入的而不是通过node_module引入的。

渲染错项目

明明指向的是项目A,但是却渲染成了项目B。

插件中配置的文件路径错了,可能A项目是8080端口配置成了8081端口,在多项目开发的时候尤其容易出现该问题。

怎么实现两栏布局右边可切换项目

之前的我天真得以为可以将子项目变成一个router的组件直接引入,但事实上是实现不了的。由于项目的耦合程度过大,依赖于各个插件,是无法将其打包成一个组件的。所以其实质上是两个并排的DOM节点。但是我们可以实现一个假的效果。

在菜单栏的router中设置,

{
    path: '/',
    component: Home,
    name: 'home',
    redirect: '/sub-project',
    children: [{
      path: 'sub-project/*',
      name: 'sub-project',
    }]
  },
复制代码

为什么要加星号呢,是为了解决另一个问题,不加通配符的话会导致navbar无法正常匹配,如果sub-project具有一些router转换的话。

为了在子项目中能匹配相应的router,需要设置

base: 'sub-project'

接着在菜单栏中设置浮动,右边margin相应的宽度就可以了。

更多

从0实现一个single-spa的前端微服务
single-spa
vue-microfrontends 用微前端的方式搭建类单页应用

以上就是我遇到的问题,喜欢可以给一个小小的赞,谢谢~

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改