微前端是前端 web 开发的趋势。微服务允许你将后端分解成更小的部分,受此启发,微前端允许你独立构建、测试和部署前端应用。根据你选择的微前端框架,你甚至可以让多个微前端应用——用 React、Angular、Vue 或其他工具编写的——在同一个大应用中无扰共存!之前在这里《认识微前端:一种用于前端 Web 开发的微服务》大概介绍了一下。
在本文中,将使用 single-spa 开发一个由微前端组成的应用程序,将使用 Travis CI 设置持续集成。每个 CI 管道将为微前端应用绑定 JavaScript,最后,我们将对其中一个微前端应用程序进行更新,看看它如何独立于其他微前端应用程序部署到生产环境中。
概述
在讨论步骤之前,先来快速了解一下演示应用程序的组成部分,这个应用程序由四个子应用程序组成:
一个容器应用程序,作为主要容器,协调微前端应用程序的安装和卸载
始终显示在页面上的微前端导航栏应用程序
一个微前端 account 应用程序,只有活跃时才显示
一个微前端 products 应用程序,也只显示当活跃
这四个应用程序都位于单独的代码仓库中,可在 GitHub 上找到。
就用户界面而言,最终的结果相当简单,但要清楚的是,用户界面并不是这里的重点。如果您是在自己的机器上学习,那么在本文结束时,您也将拥有开始使用自己的微前端应用程序所需的所有底层基础设施!
在项目开始之前,先创建一个目录来存放所有微前端应用,执行一下命令:
创建容器应用
按照以下步骤创建容器应用程序(也称为根配置),作为所有微前端的应用的入口:
cd crayon-micro-appsmkdir crayon-micro-rootcd crayon-micro-rootnpm init
复制代码
按照 CLI 步骤输入相应的信息,本文示例不使用Single-Spa推荐的root-config方式。接下来安装serve,执行下面命令:
安装完成之后,打开 package.json 增加启动脚本:
"serve": "serve -s -l 9010"
复制代码
在项目根目录新建文件 index.html,代码如下:
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>Crayon Vue Microfrontends</title> <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", "vue": "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js", "vue-router": "https://cdn.jsdelivr.net/npm/vue-router@3.0.7/dist/vue-router.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" /> <link rel="preload" href="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js" as="script" crossorigin="anonymous" /> <script src="https://unpkg.com/import-map-overrides@2.3.3/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> <import-map-overrides-full show-when-local-storage="overrides-ui" ></import-map-overrides-full> </body></html>
复制代码
创建微前端的 App
接下来将使用 CLI 工具 create-single-spa 来创建微前端的应用,具体安装介绍可以查看官方文档。
按照上面的步骤来创建导航栏微前端应用,命名为 crayon-micro-navbar。
mkdir crayon-micro-navbarcd crayon-micro-navbarcreate-single-spa
复制代码
按照 CLI 提示进行操作:
选择 single-spa application / parcel
选择 vue
输入组织名称 crayon
按照同样方式创建 crayon-micro-account 和 crayon-micro-products。
创建crayon-micro-account使用vue3,创建crayon-micro-products使用vue2。
完成之后,稍微调整一下启动信息,主要是配置端口、降低vue-cli-plugin-single-spa版本为^1.3.2,增加依赖"systemjs-webpack-interop": "^2.3.7",修改文件 package.json :
"serve": "vue-cli-service serve --port 9011",
复制代码
由于修改了依赖库的版本,需要重新执行 npm install。
先进入项目目录crayon-micro-navbar/src,增加文件 set-public-path.js,代码如下:
import { setPublicPath } from "systemjs-webpack-interop";
setPublicPath("crayon-navbar");
复制代码
将上述文件在 main.js 头部导入:
import "./set-public-path";
复制代码
接下来修改crayon-micro-navbar/account,如下:
import { setPublicPath } from "systemjs-webpack-interop";
setPublicPath("crayon-account");
复制代码
crayon-micro-navbar/products,如下:
import { setPublicPath } from "systemjs-webpack-interop";
setPublicPath("crayon-products");
复制代码
向容器应用注册微前端应用
每个应用程序都包含自己的启动脚本,这意味着在本地开发期间,每个应用程序都将在自己的开发服务器上本地运行。如上所见,导航栏应用程序在端口90011上,account应用程序在端口9012上,products应用程序在端口9013上。
打开文件 crayon-micro-root/index.html,注册三个应用:
<script type="systemjs-importmap">{ "imports": { "crayon-navbar": "http://localhost:9011/js/app.js", "crayon-account": "http://localhost:9012/js/app.js", "crayon-products": "http://localhost:9013/js/app.js", "single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.7/system/single-spa.min.js", "vue": "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js", "vue-router": "https://cdn.jsdelivr.net/npm/vue-router@3.0.7/dist/vue-router.min.js" }}</script>
复制代码
<script> (function () { Promise.all([ System.import("single-spa"), System.import("vue"), System.import("vue-router"), ]).then(function ([singleSpa, Vue, VueRouter]) { Vue.use(VueRouter);
singleSpa.registerApplication( "crayon-navbar", () => System.import("crayon-navbar"), (location) => true ); singleSpa.registerApplication( "crayon-account", () => System.import("crayon-account"), (location) => location.pathname.startsWith("/account") );
singleSpa.registerApplication( "crayon-products", () => System.import("crayon-products"), (location) => location.pathname.startsWith("/products") );
singleSpa.start(); }); })(); </script>
复制代码
本地运行
为了更好的查看效果,为每个微前端应用增加简单的 UI,在这里就不介绍了。打开四个终端,执行相应的 APP,打开浏览器输入:http://localhost:9010/,可以看到下面的效果:
总结
本文设计的代码仓库地址:https://github.com/QuintionTang/crayon-micro-apps,这只是完成了一个简单的实现,如需要在团队实际落地还需要规划一些开发规范和工具。
评论