上手京东微前端框架micro-app(保姆级教学)

最近公司准备做一下项目整体架构的优化,采用微前端的架构,将项目拆分为一个基座主服务和N个子服务。
根据市场的反馈准备入手京东的微前端框架micro-app,所以让我调研了一下,目前体验还不错。

微前端

首先介绍一下什么是微前端。
微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。
它主要解决了两个问题:

  • 1、随着项目迭代应用越来越庞大,难以维护。
  • 2、跨团队或跨部门协作开发项目导致效率低下的问题。
    上手京东微前端框架micro-app(保姆级教学)_第1张图片

micro-app和其它微前端框架的区别

micro-app之前,业内已经有一些开源的微前端框架,比较流行的有2个:single-spaqiankun

single-spa是通过监听url change事件,在路由变化时匹配到渲染的子应用并进行渲染,这个思路也是目前实现微前端的主流方式。同时single-spa要求子应用修改渲染逻辑并暴露出三个方法:bootstrapmountunmount,分别对应初始化、渲染和卸载,这也导致子应用需要对入口文件进行修改。因为qiankun是基于single-spa进行封装的,所以这些特点也被qiankui继承下来,并且需要对webpack配置进行一些修改。

micro-app并没有沿袭single-spa的思路,而是借鉴了WebComponent的思想,通过CustomElement结合自定义的ShadowDom,将微前端封装成一个类WebComponent组件,从而实现微前端的组件化渲染。并且由于自定义ShadowDom的隔离特性,micro-app不需要像single-spaqiankun一样要求子应用修改渲染逻辑并暴露出方法,也不需要修改webpack配置,是目前市面上接入微前端成本最低的方案。

上手京东微前端框架micro-app(保姆级教学)_第2张图片
所以综上所述micro-app的优势如下:

  1. 使用简单
    将所有功能都封装到一个类WebComponent组件内,从而实现在基座应用中嵌入一行代码即可渲染一个微前端应用。
    同时micro-app还提供了js沙箱、样式隔离、元素隔离、预加载、数据通信、静态资源补全等一系列完善的功能。
  2. 零依赖
    micro-app没有任何依赖,这赋予它小巧的体积和更高的拓展行。
  3. 兼容所有框架
    为了保证各个业务之间独立开发、独立部署的能力,micro-app做了诸多兼容,在任何技术框架中都可以正常运行。

上手实战

了解完以上内容之后,就可以着手实战一下了,实测非常简单。

因为micro-app对主服务和子服务的技术栈没有任何要求,所以,我们新建三个项目,my-app(React)my-app1(React)my-app2(Vue)

my-app是整体项目的主服务,也就是基座,my-app1my-app2都是平级的子服务。

因为是写demo,所以ReactVue项目都基于其框架提供的脚手架create-react-appvue-cli来构建,不基于脚手架的话用webpack自己构建也没有任何问题。

首先我们先建立一个干净的空文件夹,名字为micro-app-demo,通过VSCode进入这个目录。

主服务my-app的构建

通过脚手架create-react-app创建一个React项目,并启动

npx create-react-app my-app
cd my-app
npm start

上手京东微前端框架micro-app(保姆级教学)_第3张图片
启动成功,可以看到主服务地址http://localhost:3000
然后安装一下micro-app

npm i @micro-zoe/micro-app --save

下载完成之后,进入项目的入口文件,create-react-app创建的项目默认的入口文件是index.js

import microApp from '@micro-zoe/micro-app';

microApp.start();

index.js完整代码。

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import microApp from '@micro-zoe/micro-app';

microApp.start();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

然后主服务的配置就可以先暂停了,等子服务创建了再引入。

子服务my-app1的构建

第一个子服务my-app1也通过create-react-app构建并启动。

npx create-react-app my-app1
cd my-app1
npm start

因为默认的3000端口已经被主服务my-app用了,所以会启动子服务my-app1会提示是否要换另一端口启动。
在这里插入图片描述
输入y。
然后就可以看到它启动成功了。
上手京东微前端框架micro-app(保姆级教学)_第4张图片
可以看到子服务1的地址是http://localhost:3001

然后重点来了,理论上,通过micro-app构建微前端项目,在服务间不通信的前提下,子服务只需要配置跨域就可以,其他都不需要弄,可以说是完全零侵入、低成本的方案。

通过create-react-app构建的项目默认就进行了跨域的相关配置。
如果不放心,或者想更改webpack的配置,可以打开控制台,输入

npm run eject

package.json中也可以看到这个指令。
输入完之后就一直yes就行了。
可能你会遇到这种报错。
上手京东微前端框架micro-app(保姆级教学)_第5张图片
因为我们在构建完项目之后进行了一些代码的更改,所以提示你要先保存这些更改,才可以eject

git指令大家应该都熟悉

git add .
git commit -m 'your commit'

然后再npm run eject就没问题了。

my-app1的项目目录内就多了一个config文件夹,打开其中的webpackDevServer.config.js,这就是脚手架帮我们封装的基础版的webpack的一些配置项,39-43行可以看到关于跨域的处理。

上手京东微前端框架micro-app(保姆级教学)_第6张图片
所以你不需要做额外处理。
然后为了在视觉上方便区分这几个服务,我们在主页面内都加一个h1标签。

my-app1/src/App.js

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>子服务1 my-app1</h1>
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

上手京东微前端框架micro-app(保姆级教学)_第7张图片

子服务my-app2的构建

子服务my-app2vue-cli构建一个Vue项目。

前提你要先全局安装过vue-cli,如果没有先运行以下指令安装vue-cli

npm install -g @vue/cli

然后确定本地有vue-cli的前提下运行以下指令。

vue create my-app2
cd my-app2
npm run serve

create的时候选一个默认配置的就可以,我选的vue2的默认配置。

上手京东微前端框架micro-app(保姆级教学)_第8张图片
可以看到子服务my-app2启动成功了,地址是http://localhost:8080

同样在主页面加入一个h1标签。

my-app2/src/App.vue

<template>
  <div id="app">
    <h1>子服务2 my-app2</h1>
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

上手京东微前端框架micro-app(保姆级教学)_第9张图片
通过vue-cli构建的Vue项目默认是没有进行跨域配置的,所以我们需要手动打开my-app2根目录下的vue.config.js文件,抄写一下my-app1中做的跨域处理,即以下代码:

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': '*',
      'Access-Control-Allow-Headers': '*',
    },
  },
})

更改vue.config.js的配置后需要重新启动项目才能生效,所以记得讲my-app2这个子服务,停止再启动。

建立三个服务的关系

回到主服务my-app中。

你可以将my-app1my-app2这两个子服务想象成你封装的两个组件,可以任意的在任何地方进行调用。

只需要通过micro-app提供的组件来配置就可以,比如下方这种方式。

<micro-app 
  	name='app1' 
    url='http://localhost:3000/' 
    baseroute='/my-page'
  >
</micro-app

常规使用,只需要写三个属性,name子服务的应用名称(必传),url子服务的应用地址(必传),baseroute主服务分配给子服务的基础路由,(可选)。

我们在src目录下新建四个文件,三个作为页面,一个配置路由规则,给子服务们分配一下路由。
上手京东微前端框架micro-app(保姆级教学)_第10张图片
my-app/src/Page.jsx

import React from "react";

const Page = () => {
    return (
        <div>
            <h1>主服务 Page</h1>
        </div>
    )
};

export default Page;

my-app/src/Page1.jsx

import React from "react";

const Page1 = () => {
    return (
        <div>
            <micro-app
                name="my-app1"
                url="http://localhost:3001"
                baseroute="my-app1"
            ></micro-app>
        </div>
    )
};

export default Page1;

my-app/src/Page2.jsx

import React from "react";

const Page2 = () => {
    return (
        <div>
            <micro-app
                name="my-app2"
                url="http://localhost:8080"
                baseroute="my-app2"
            ></micro-app>
        </div>
    )
};

export default Page2;

my-app/src/route.js

因为create-react-app脚手架默认没有安装react-router,所以在主服务my-app里安一下。

npm install react-router-dom --save
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Page from './Page';
import Page1 from './Page1';
import Page2 from './Page2';

export default function AppRoute() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path='/' element={<Page />}>

                </Route>
                <Route path='/my-app1' element={<Page1 />}>

                </Route>
                <Route path='/my-app2' element={<Page2 />}>

                </Route>
            </Routes>
        </BrowserRouter>
    )
}

my-app/src/App.js

import './App.css';
import AppRoute from './route';

function App() {
  return (
    <div className="App">
      <AppRoute />
    </div>
  );
}

export default App;

走到这里,理论上你就可以看效果了。

http://localhost:3000会访问主服务的默认页面,承载在Page.jsx内。

上手京东微前端框架micro-app(保姆级教学)_第11张图片
http://localhost:3000/my-app1会访问子服务1 my-app1的默认页面,承载在Page1.jsx内。

上手京东微前端框架micro-app(保姆级教学)_第12张图片
http://localhost:3000/my-app2会访问子服务2 my-app2的默认页面,承载在Page2.jsx内。

上手京东微前端框架micro-app(保姆级教学)_第13张图片
通过域名我们也可以看到,这三个页面都在主服务http://localhost:3000下可以访问的,是不是很神奇。

我有一个主服务,然后可以调用N个其他域名启动的子服务,集成在一起。

子服务理论上也可以独立运行,通过域名访问也可以看到这一点。

上手京东微前端框架micro-app(保姆级教学)_第14张图片
上手京东微前端框架micro-app(保姆级教学)_第15张图片
我分别访问http://localhost:3001http://localhost:8080这些子服务没有受到任何影响。

这就是micro-app这个微前端框架的强大之处。

总结

通过实践,我们可以发现micro-app这个微前端框架的,代码侵入性极低,我们只在主服务里写了几行关于微前端配置的代码,子服务在不进行通信的前提下,只需要配置跨域即可。

如此低成本就能将N个独立的子服务集成到一起,对于原服务也不会有任何影响。

甚至不限制任何技术栈,我们的主服务是React,子服务1是React,子服务2是Vue,也可以很轻松的进行集成。

你可能感兴趣的:(微前端,JavaScript,面试,前端框架,前端,微服务,react,vue.js)