初探微前端

296 阅读4分钟

引言 

最近微前端很火,各大厂基本都在储备相应的技术栈,并有些已经应用到生产环境。 

前端人员都知道,现在的前端越来越复杂,技术栈也越来越多,系统平台也是逐日增加。 

从业人员也能感受到,前端趋势是构建一个功能丰富且强大的浏览器应用程序。 

微前端是把各独立团队构建的网站或web应用聚合在一起的技术手段。

 微前端核心价值 

  • 与技术栈无关 

 不受技术影响,每个团队都能自由选择和升级其自己的技术栈,而无需与其他团队进行协调。 

  • 隔离团队代码 

各团队代码仓库独立,技术独立,开发独立,部署独立 

  • 独立运行时 

每个微应用之间状态隔离,运行时状态不共享 

  • 增量升级 

对一个已经存在到系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略  

其他解决方案 

微前端是组合多个应用,其他技术手段也可以达到同样的目的。 

比如iframe,或者nginx配置等。 

iframe之重,问题之多,相信大家都有所体验,最重要等是当刷新页面时,iframe的状态会丢失。

 nginx配置,对于大部分前端人员来说还是有一定难度,而且每次更改配置都需要重启,很影响体验。 

Single-spa 

Single-spa 是一个将多个单页面应用聚合为一个整体应用的 javascript 微前端框架 

具体用法请参考Single-spa 官网zh-hans.single-spa.js.org/ 

 qiankun 

qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。 

它是蚂蚁金融科技基于微前端架构,经过线上应用检验后,抽取核心模块进行开源的框架。

它更简单,它能把巨大应用拆解成若干松耦合微应用,独立开发,独立运行。 

 初试 qiankun 

创建vue项目 

1、使用vue/cli创建项目 

vue create vue-project 

2、修改main.js 

import Vue from 'vue'
import App from './App.vue'

let app = null;
function render() {
  app = new Vue({
    render: h => h(App),
  }).$mount('#app');
}
// 区分是否在微应用中
if (window.__POWERED_BY_QIANKUN__) {
  // qiankun 将会在微应用 bootstrap 之前注入一个运行时的 publicPath 变量
  window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
} else {
  不在微应用中,启动自己
  render();
}

export async function bootstrap() {
  console.log('react app bootstrap');
}

export async function mount(props) {
  console.log(props);
  render(props)
}

export async function unmount() {
  app.$destroy();
  app = null;
}
  • window.POWERED_BY_QIANKUN

可以区分应用是否在微应用中 

  • bootstrap 导出生命周期 

只会在初始化时调用一次,通常可以设置一些全局变量的初始化 

  • mount 导出生命周期 

应用每次进入都会调用 mount 方法,通常在这里触发应用的渲染方法

  • unmount 导出生命周期 

应用每次 切出/卸载 会调用的方法,通常在这里会卸载微应用的应用实例 

3、修改App.vue

<template>
  <div id="app">
      <div class="hello">
        <div class="logo"></div>
      </div>
  </div>
</template>

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

<style>
.logo {
  width: 400px;
  height: 400px;
  background: url(https://cn.vuejs.org/images/logo.png) no-repeat;
  margin: 0 auto;
}
</style>

4、修改webpack配置

// vue.config.js
module.exports = {
    devServer: {
        port: 8888,
        headers: {
            'Access-Control-Allow-Origin': '*'
        }
    },
    configureWebpack: {
        output: {
            library: 'vueApp',
            libraryTarget: 'umd'
        }
    }
}

5、启动项目

npm run serve

创建react项目 

1、使用create-react-app

create-react-app react-project

2、修改index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

function render() {
  ReactDOM.render(<App />, document.getElementById('root'))
}
if (window.__POWERED_BY_QIANKUN__) {
  window.__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('react app bootstrap');
}

export async function mount(props) {
  console.log(props);
  render()
}

export async function unmount() {
  ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}

导出的生命周期bootstrap mount unmount上面都解释过了。

3、安装react-app-rewired,修改webpack配置

npm install react-app-rewired

4、修改package.json的scripts

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
}

5、添加config-overrides.js修改webpack配置

module.exports = {
    webpack: (config) => {
        config.output.library = 'reactApp';
        config.output.libraryTarget = 'umd';
        config.output.publicPath = 'http://localhost:3000/';
        return config;
    },
    devServer: (configFunction) => {
        return (proxy, allowedHost) => {
            const config = configFunction(proxy, allowedHost);
            config.headers = {
                'Access-Control-Allow-Origin': '*'
            }
            return config;
        }
    }
}

6、启动项目

npm run start

创建基座

1、使用vue/cli创建项目

vue create base

2、安装qiankun

npm i qiankun

3、修改main.js

import Vue from 'vue';
import App from './App.vue';
import HelloWorld from './components/HelloWorld.vue';
import VueRouter from 'vue-router';
import { registerMicroApps, start } from 'qiankun';
Vue.use(VueRouter);

registerMicroApps([
  {
    name: 'vue app',
    entry: '//localhost:8888',
    container: '#vue',
    activeRule: '/vue',
  },
  {
    name: 'react app',
    entry: '//localhost:3000',
    container: '#react',
    activeRule: '/react',
  },
]);
start();

const router = new VueRouter({
  mode: 'history',
  routes: [
    {path: '/hello', component: HelloWorld}
  ]
});

new Vue({
  render: h => h(App),
  router
}).$mount('#app');
  • registerMicroApps 注册微应用 
  • name 微应用名称,唯一值 
  • entry 微应用等entry地址 
  • container 微应用的容器节点的选择器或者 Element 实例 
  • activeRule 微应用的激活规则,可以理解为路由path 注册微应用的基础配置信息
  • start 启动qiankun

当浏览器 url 发生变化时,会自动检查每一个微应用注册的 activeRule 规则,符合规则的应用将会被自动激活。

4、修改App.vue文件

<template>
  <div id="qiankunbase">
    <div class="router">
      <!-- 自己的路由 -->
      <router-link to="/hello">HelloWorld</router-link>
      <!-- vue项目 -->
      <router-link to="/vue">Vue project</router-link>
      <!-- react项目 -->
      <router-link to="/react">React project</router-link>
    </div>
    <div class="view">
      <!-- 自己路由切换 -->
      <router-view></router-view>
      <!-- 挂载vue项目 -->
      <div id="vue"></div>
      <!-- 挂载react项目 -->
      <div id="react"></div>
    </div>
  </div>
</template>

<script>

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

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

5、启动服务

npm run serve

效果图

结语

本片只是对微前端的一个初步介绍,也是对qiankun框架的初探。

在以后对大型应用进行重构,可以采用微前端方式进行增量式升级。

更多精彩请关注公众号闹闹前端