The front end of the first test micro-services (singleSpa)

1. Basic Concepts

Micro achieve a front-end architecture, it can be divided into four parts (reference: https: //alili.tech/archive/11052bf4/)

Loader: that is, the front end of the core micro-architecture, the main application for scheduling sub decide when to show which sub-application, it can be understood as a power source.

Wrapper: With loader, existing applications can be packaged so that they can use the loader, which corresponds to the power adapter.

Main applications: typically contains entries on all child use common parts - which is equivalent electrical base

Sub-applications: number of applications displayed in the main content area of ​​application - which is equivalent to the appliance you want to use

Therefore, such a concept is: Power (loader) → power adapter (wrapper) → ️ appliance base (host application) → ️ collector (sub-applications) ️

Overall this is a process: the user access to index.html, the browser runs loader js file, go to the loader configuration file, and then register each sub-application configuration file is, first load the main application (menus, etc. ), then the route is determined by the dynamic remote loading sub-application.

2. Preliminaries

2.1 SystemJs

SystemJS provide a common way to import modules, supporting traditional modules and modules for ES6.

SystemJs There are two versions, 6.x version is used in the browser, version 0.21 is used in the browser and node environment, the use of the two different ways. (Reference: https://github.com/systemjs/systemjs )

In the micro-services mainly act as loader.

2.2 singleSpa

single-spa applications is a set of a plurality javascript together in the front-end application framework. The main act as wrappers. (Reference: https://single-spa.js.org/docs/getting-started-overview.html )

3. Micro Services Practice

3.1 to create applications

First, create a master application iframe, the main application can simply access the service from a static resource can be.

With npm init initialization, create a index.html, write a simple hello world, install dependencies npm i serve --s.

Increase the startup command in package.json the scripts in "serve": "serve -s -l 7000". After running you can see hello world.

 

Then create three sub-applications, I use vue-cli2.0, respectively, to create navbar applications (used to write routing), program1 (application 1), program2 (application 2).

navbar applications only put two links just fine, as:

  

 And routing program2 program1 sub-applications are combined with the corresponding item name prefix, have increased about a sub-route as a route to switching applications, as follows:

 

 

3.2 transformation sub-applications

First, the sub-packaging applications, the respective sub-applications need to rely npm i single-spa-vue systemjs-webpack-interop, main.js modify the file entry is as follows:

 

 

Which is a single-spa-vue vue project for the wrapper, systemjs-webpack-interop npm is a community-maintained library, which can help you make webpack and systemjs work together. 

In addition to output in webpack also need to increase configuration settings

 

 

 3.3 Modify the main application file

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <meta name="importmap-type" content="systemjs-importmap">
    <script type="systemjs-importmap">
        {
          "imports": {
            "navbar": "http://localhost:8080/app.js",
            "program1": "http://localhost:8081/app.js",
            "program2": "http://localhost:8082/app.js",
            "single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.7/system/single-spa.min.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://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('single-spa')
            .then((res)=>{
                var singleSpa=res;
            
                singleSpa.registerApplication('navbar',()=>System.import('navbar'),location=>true);

                singleSpa.registerApplication('program1',()=>System.import('program1'),(location)=>{
                    return location.hash.startsWith(`#/program1`);
                });

                singleSpa.registerApplication('program2',()=>System.import('program2'),(location)=>{
                    return location.hash.startsWith(`#/program2`);
                });

                singleSpa.start();
            })
        })()
    </script>
</body>
</html>
registerApplication函数包含四个参数,
appName: 注册的应用名称;
applicationOrLoadingFn:应用入口文件(必须是一个函数,返回一个函数或者一个promise);
activityFn:控制应用是否激活的函数(必须是一个纯函数,接受window.location作为参数,返回一个boolean);
customProps:在包装器生命周期函数中传递给子应用的props(应该是一个对象,可选)。
 
补充:有些小伙伴说运行demo会报错,这里说明下,因为后面把公共依赖抽离出去了,所以这里可能需要加上公共依赖。

 

 

 
 
start函数必须在子应用加载完后才能调用。在调用之前,子应用已经加载了只是未被渲染。
 
3.4 运行项目
分别运行navbar,program1,progarm2项目,然后运行iframe项目。iframe项目运行在7000端口,其他子应用分别运行在8080,8081,8082端口。从7000端口去请求其他端口的入口文件会跨域,所以在子应用中增加跨域设置。
在子应用的webpack.dev.config.js中找到devSever配置项,增加headers:{"Access-Control-Allow-Origin":"*"}配置
然后重新运行项目即可。
 

 4.项目整合

以上只是在开发环境中使用,接下来尝试不分别启动服务,只启用一个服务来跑项目。大体思路是使用express搭建一个服务,将子应用全部打包到项目上作为静态资源访问,入口html使用ejs模板来实现项目配置,而不再写死。

4.1 使用express生成器生成项目

4.2 修改子应用打包配置

 

 

 这样子应用就全部打包到express应用中作为静态资源使用了。

4.3 增加应用配置文件

将iframe的index.html的内容复制到express的入口ejs中。增加配置文件apps.config.json和apps.config.js。

 

 

 apps.config.js作用就是根据apps.config.json在静态资源文件夹下生成一份新的配置文件,将配置文件中的资源名称通过正则匹配成完整的资源路径。并且监听文件变化来更新静态资源文件夹下的配置文件。

生成的配置文件

 

 

4.4根据这个生成的配置文件去修改ejs,将项目注册过程循环出来,而不再是写死的。 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <meta name="importmap-type" content="systemjs-importmap">
    <script type="systemjs-importmap">
        {
          "imports": {
            <%for(var i=0;i<apps.length;i++){%>
              "<%= apps[i].name %>":"<%= apps[i].server %><%=apps[i].resourceEntryUrl %>",
            <%}%>
            "single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.7/system/single-spa.min.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://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(){
            Promise.all([
                System.import('single-spa'),
                System.import('./apps.config.json')
            ])
            .then((res)=>{
                var singleSpa=res[0];
                var configs=res[1].default;
            
                configs.apps.forEach( project => {
                  if(project.resource.length>0){
                    Promise.all(project.resource.map(i=>{
                      return System.import(project.server+i)
                    })).then(function(){
                      singleSpa.registerApplication(project.name,()=>System.import(project.name),(location)=>{
                          return project.base?true:location.hash.startsWith(`#/${project.name}`);
                      });
                    })
                  }else{
                    singleSpa.registerApplication(project.name,()=>System.import(project.name),(location)=>{
                        return project.base?true:location.hash.startsWith(`#/${project.name}`);
                    });
                  }
                });

                singleSpa.start();
            })
        })()
    </script>
</body>
</html>

实际渲染出来是

 

 

 4.5 优化打包配置

因为三个子项目都用到了相同的一部分依赖,可以考虑将公用的依赖不打包进去,改为在主项目主引入来提高打包效率

修改子应用的webpack.base.config.js,增加配置项

 

 在主应用中引入依赖

 

 4.5 增加react应用

同样是使用webpack打包,不同是包装器不一样。其他基本上是一样的思路即可。

 

 最终demo

 转自https://www.cnblogs.com/scdisplay/p/11648701.html

Guess you like

Origin www.cnblogs.com/zhishaofei/p/12060154.html