1. 程式人生 > 實用技巧 >微前端

微前端

隨著專案工程越來越大,打包慢、載入慢等問題也隨之而來,想著有什麼方案可以解決呢?偶然之間看到微前端的概念,那什麼是微前端呢?

  微前端主要是借鑑後端微服務的概念。簡單地說,就是將一個巨無霸(Monolith)的前端工程拆分成一個一個的小工程。別小看這些小工程,它們也是“麻雀雖小,五臟俱全”,完全具備獨立的開發、執行能力。整個系統就將由這些小工程協同合作,實現所有頁面的展示與互動。

上面是一些網上摘抄的概念,那怎麼落地呢?

找了半天,終於找到了,它就是阿里的qiankun框架基於single-spa構建,下面是具體的構建流程:

  1、新建一個專案;

  2、cd /projectname -> npm init 工程

·  3、cnpm install qiankun -S 或 yarn add qiankun

  4、專案結構

 

 5、index.js

import { registerMicroApps, setDefaultMountApp, start, runAfterFirstMounted } from 'qiankun';

import render from './VueRender';

render({ loading: true });

const loader = loading => render({ loading });

registerMicroApps(
  [
    {
      name: 
'bigScreen', entry: '//localhost:7101', container: '#subapp-viewport', loader, activeRule: '/bigScreen', }, { name: 'terryMusic', entry: '//localhost:8080', container: '#subapp-viewport', loader, activeRule: '/terryMusic', }, ], { beforeLoad: [ app
=> { console.log('[LifeCycle] before load %c%s', 'color: green;', app.name); }, ], beforeMount: [ app => { console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name); }, ], afterUnmount: [ app => { console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name); }, ], }, ); /** * Step3 設定預設進入的子應用 */ setDefaultMountApp('/bigScreen'); /** * Step4 啟動應用 */ start(); runAfterFirstMounted(() => { console.log('[MainApp] first app mounted'); });

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Terry - MicroFront</title>
</head>

<body>
  <div class="mainapp">
    <!-- 標題欄 -->
    <header class="mainapp-header">
      <h1>Terry微前端應用落地</h1>
    </header>
    <div class="mainapp-main">
      <!-- 側邊欄 -->
      <ul class="mainapp-sidemenu">
        <li onclick="push('/bigScreen')">big-screen</li>
        <li onclick="push('/terryMusic')">terry-music</li>
      </ul>
      <!-- 子應用  -->
      <main id="subapp-container"></main>
    </div>
  </div>

  <script>
    function push(subapp) { history.pushState(null, subapp, subapp) }
  </script>
</body>

</html>

package.json

{
  "name": "terry-micro-front",
  "version": "1.0.0",
  "description": "微前端",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server"
  },
  "author": "terry",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.7.2",
    "@babel/plugin-transform-react-jsx": "^7.7.0",
    "@babel/preset-env": "^7.7.1",
    "babel-loader": "^8.0.6",
    "cross-env": "^7.0.2",
    "css-loader": "^3.2.0",
    "html-webpack-plugin": "^3.2.0",
    "less-loader": "^6.2.0",
    "qiankun": "^2.3.1",
    "style-loader": "^1.0.0",
    "vue": "^2.6.12",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0"
  }
}

VueRender:用於載入vue專案

import Vue from 'vue/dist/vue.esm';

function vueRender({ loading }) {
  return new Vue({
    template: `
      <div id="subapp-container">
        <h4 v-if="loading" class="subapp-loading">Loading...</h4>
        <div id="subapp-viewport"></div>
      </div>
    `,
    el: '#subapp-container',
    data() {
      return {
        loading,
      };
    },
  });
}

let app = null;

export default function render({ loading }) {
  if (!app) {
    app = vueRender({ loading });
  } else {
    app.loading = loading;
  }
}

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './index.js',
  devtool: 'source-map',
  devServer: {
    port: '7099',
    clientLogLevel: 'warning',
    disableHostCheck: true,
    compress: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    historyApiFallback: true,
    overlay: { warnings: false, errors: true },
  },
  output: {
    publicPath: '/',
  },
  mode: 'development',
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-transform-react-jsx'],
          },
        },
      },
      {
        test: /\.(le|c)ss$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: './index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
      },
    }),
  ],
};

子應用配置:Vue專案為例:

成品:

以上就是整個專案搭建過程以及程式碼,有興趣的可以一起學習哦!