preface

The Qiankun microservice integrates multiple systems of different technology stacks (React,Vue,Angular,jQuery) into one system, and each system can be independently deployed and run, which is suitable for large teams and large front-end projects.

Functions:

  • React + Vue
  • Background Management System (Ant Design Pro) multi-tab page caching practice in qiankun environment
  • Dependency sharing – the parent app shares the public packages react,react-dom,moment,antd, etc
  • Resource common – common utility util, components, configuration synchronized across multiple projects

Online preview based on Qiankun Microservice:

Click preview

Get the project source code

The project architecture

project Technology stack port Access to the address
Main project (the main – the react) Ant Design Pro 5000 qiankun.fancystore.cn
Component (1) app1 – react to Ant Design Pro 5001 app1.fancystore.cn
Component 2 (app2 – react) Ant Design Pro 5002 app2.fancystore.cn
Subproject 3 (app3 – vue) Vue Element Template 5003 app3.fancystore.cn
Qiankun-Common TypeScript Github.com/czero1995/q…

Project reform

1. Main application (base)

1.1 installation qiankun

   npm install @umi/qiankun --save   
   or
   yarn add @umi/qiankun --save    
Copy the code

1.2 Registering sub-applications

// In config/config.ts add qiankun: {master: {apps: [{name:'app1', entry: process.env.NODE_ENV === 'production' ? '//app1.fancystore.cn' : '//localhost:5001', }, { name:'app2', entry: process.env.NODE_ENV === 'production' ? '//app2.fancystore.cn:' : '//localhost:5002', }, { name:'app3', entry: process.env.NODE_ENV === 'production' ? '//app3.fancystore.cn:' : '//localhost:5003', }, ], sandbox: True, // Whether to enable sandbox prefetch: true, // Whether to enable prefetch feature}}Copy the code

1.3 Modifying the Root Node

    // src/pages/document.ejs
    id=root-master
Copy the code

1.4 Creating a Sub-Application To load and layout MicroAppLayout

// src/layouts/MicroAppLayout import BasicLayout from '@ant-design/pro-layout'; import { KeepAlive, Provider } from 'react-keep-alive'; import { MicroAppWithMemoHistory } from 'umi'; import allRoutes from '.. /.. /config/routes'; function MicroAppLayout(props) { let targetMicro = '' const transRoutes = (routes, pathname) => { routes.map(item => { if (item.routes) { return transRoutes(item.routes, pathname) } if (item.path === pathname) { targetMicro = item.microName } }) return targetMicro } return <Provider> <KeepAlive name={props.location.pathname}> { targetMicro ? <MicroAppWithMemoHistory name={transRoutes(allRoutes[0].routes, props.location.pathname)} url={props.location.pathname} /> : <BasicLayout></BasicLayout> } </KeepAlive> </Provider> } export default MicroAppLayout;Copy the code

1.5 Create app.ts in the SRC directory. If it is a sub-application, use MicroAppLayout to load it

    // src/app.ts
    import LoadingComponent from '@/components/PageLoading';
    import { dynamic } from 'umi';
    const transRoutes = (routes) => {
      routes.forEach(item => {
        if(item.routes){
          return transRoutes(item.routes)
        }
        if(item.microName){
          item.component = dynamic({
            loader: (a) => import(/* webpackChunkName: 'layouts__MicroAppLayout' */ '@/layouts/MicroAppLayout'),
            loading: LoadingComponent,
          })
        }
      })
    }

    export function patchRoutes({ routes }) {
      transRoutes(routes[0].routes)
    }
Copy the code

2. React(Ant Desin Pro)

2.1 installation qiankun

    npm install @umi/qiankun --save   
    or
    yarn add @umi/qiankun --save
   
Copy the code

2.2 Sub-project registration qiankun, join in config/config.ts

    qiankun: {
        slave: {}
    }
Copy the code

2.3 Modifying the root object SRC /pages/document.ejs

    id=root-slave
Copy the code

2.4 Create app.ts in the SRC directory and export the lifecycle hooks. The sub-project will need to distinguish between the qiankun environment and the current environment using SRC /layouts/BlankLayout. Use a default template (SRC /layouts/BasicLayout) that can be embedded in the Qiankun environment or deployed independently

Const isQiankun = window.__powered_by_qiankun__ export const qiankun = { console.log('app1 bootstrap', props); }, // Render before triggering async mount(props) {console.log('app1 mount', props); }, // Async unmount(props) is triggered after the application is unmounted {console.log('app1 unmount', props); }}; export async function patchRoutes({routes}) { if(isQiankun){ routes[0]['component'] = require('@/layouts/BlankLayout').default } }Copy the code

3. Child application Vue(Vue-element-template)

3.1 Add in configureWebpack under vue.config.js

Library: '${name}-[name] ', libraryTarget: 'umd', jsonpFunction: `webpackJsonp_${name}`, }Copy the code

3.2 Add devServer in vue.config.js:

headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*"}Copy the code

3.3 Exposed life cycle of Qiankun in Main.js:

    let install = null;
    function render(props) {
      install = new Vue({
        router,
        store,
        render: h => h(App)
      }).$mount('#app3')
    }
    if (window.__POWERED_BY_QIANKUN__) {
      __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
    } else {
      render();
    }
    export async function bootstrap(props) {
    }
    export async function mount(props) {
      render(props);
    }
    export async function unmount(props) {
      install.$destroy();
      install = null
    }
Copy the code

Project summary

  1. There are two ways for the main application to load sub-applications: routing bindings and using
    components. If you want to support Ant Design Pro multiple tabs, you need to use
    because dynamic display inserts tabs, Binding dead-end causes qiankun to fail to load the corresponding page.

  2. Ant Design Pro TAB, click the tabs to show different application page will lead to be destroyed, content data is initialized and lost, in the SRC/layouts/MicroAppLayout under:

    The main application of the react-keep-Alive package must use MicroApp with MemoHistory. If you use MicroApp, there is no effect.Copy the code
  3. Qiankun environment page jump 404

    In the Qiankun environment, all route changes would trigger the monitoring of routes in Qiankun, requiring judgment on the environment: Export const qiankunJump = (URL :string, params = null) =>{window.__powered_by_qiankun__? history.pushState(params,name,url): umiHistory.push(url) } qiankunJump('/xxx')Copy the code
  4. Cannot read property ‘createContext’ of Undefind

    Externals: {'react': 'window.react ', 'react-dom': {'react':' window.react ', 'react-dom': 'window.ReactDOM', } => externals: { react: 'React', 'react-dom': 'ReactDOM', }Copy the code

Project optimization

1. Rely on sharing

If the main sub-app uses the same library or package (react,react-dom,moment, etc.), it can be imported using externals to reduce the waste of loading duplicate packages. The next time he uses it, he'll get it from the global variable first. This will allow you to reuse your content, Just make sure both the Url of the link simply const fetchScript = scriptUrl = > scriptCache [scriptUrl] | | (scriptCache [scriptUrl] = fetch(scriptUrl).then(response => response.text())); So as long as the subproject is configured with webpack externals and these public dependencies are on the same server, it can realize the on-demand introduction of the subproject's public dependencies. After one project uses the file, the other project does not load it repeatedly and can directly reuse the file.Copy the code

2. Resource sharing

Solving the resource sharing problem can improve the maintainability of projects that would otherwise be difficult to maintain components or tools shared by multiple systems. 1. Commonly used is to release into the NPM package, each project to install the update package. NPM link can be used for local debugging. But repeatedly updating packages is also tedious. Another option is to add "qiankun-common" to the package.json dependency: "Git+https://[email protected]: czero1995 / qiankun - common. Git" using the import {commonUtil} from 'qiankun - common; util.qiankunJump('/xxx')Copy the code

Project start

1. Run main-react NPM install NPM run start 2. App1-react NPM install NPM run start 3. App2-react NPM install NPM run start 4. Go to app3-react NPM install NPM run devCopy the code

Project deployment

  1. Subapplication Nginx needs to be equipped with cross-domain request headers:

      add_header Access-Control-Allow-Origin *;
      add_header Access-Control-Allow-Credentials true;
      add_header Cache-Control no-cache;
    Copy the code
  2. Nginx enables gzip compression:

      gzip  on;
      gzip_min_length 200;
      gzip_buffers 4 16k;
      gzip_comp_level 9;
      gzip_vary on;
      gzip_disable "MSIE [1-6]\.";
      gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
    Copy the code