vite2 接入 qiankun 微前端


關注公眾號: 微信搜索 前端工具人 ; 收貨更多的干貨

原文鏈接: 自己掘金文章 https://juejin.cn/editor/drafts/7078238272064847903

vite 已經大火了, 自從用上了就停不下來` ;

但礙於 vite 初來乍到, 生態不夠成熟, 有些功能還是比較尷尬的,比如微前端;

qiankun 微前端搭建詳細步驟及常見問題,可參考之前文章 https://juejin.cn/post/6943763969576271879

以下源碼也已上傳至 github

開篇

去年初項目接入微前端的時候,就准備使用 vite, 一頓構操作下來,發現 vite 應用一直無法獲取生命周期, 才知道那時 qiankun 暫時不支持 vite 應用

大致原因如下:

  • vite 構建的 js 內容必須在 type=modulescript 腳本里;
  • 當時qiankun 的源碼依賴之一 import-html-entry 則不支持 type=module 這個屬性 (目前已支持);
  • qiankun 是通過 eval 來執行這些 js 的內容,而 vite 里面 import/export 沒有被轉碼, 所以直接接入會報錯:不允許在非type=modulescript 里面使用 import;

在去年年尾的時候,在qiankunissues 中找到了2種方法;

還是這些大佬牛逼;下面介紹下這2種方法

方法一 (不推薦)

  • 結合 rollup/plugin-html 插件;
  • 修改Vite.config.js中的build配置默認Vite的輸出目標targetmodule,改為esnext
  • 詳細步驟可參考 https://github.com/umijs/qiankun/issues/1268

缺點:

  • 可以實現生產環境接入,開發環境不行;
  • vite沒有動態publicPath的支持;所以 Vite.configbase 配置需要寫死;
  • vite code-splitting(代碼分割)功能並不支持iifeumd兩種格式,導致路由無法懶加載;
  • 圖片資源只會被打包成 base64,無論圖片大小

方法二 (推薦)

vite-plugin-qiankun 插件; github文檔

優點

  • 保留 vite 構建 es 模塊的優勢
  • 一鍵配置,不影響已有的 vite 配置
  • 支持 vite 開發環境
  1. 安裝插件

pnpm add vite-plugin-qiankun

  1. vite.config.ts 配置
// vue3
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun';
import { resolve  } from 'path';
export default ({ mode }) => {
  const __DEV__ = mode === 'development'
  return defineConfig({
    alias: {
      '@': resolve('src'),
    },
    server: {
      port: 7711,
      origin: '//localhost:7711'
    },
    base: __DEV__ ? '/' : '//localhost:7711',
    plugins: [ vue(),
      qiankun('sub-vite2-vue3', {
        useDevMode: true
    })],
  })
}
// react
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import qiankun from 'vite-plugin-qiankun';
import reactRefresh from '@vitejs/plugin-react-refresh'
// useDevMode 開啟時與熱更新插件沖突
const useDevMode = true
export default ({ mode }) => {
  const __DEV__ = mode === 'development'
  return defineConfig({
    server: {
      port: 7722,
      origin: '//localhost:7722'
    },
    base: __DEV__ ? '/' : '//localhost:7722',
    plugins: [
      ...(
        useDevMode ? [] : [
          reactRefresh()
        ]
      ),
      qiankun('sub-vite2-react', {
        useDevMode: true
      })
    ],
  })
}
  1. 導出相應的生命周期
// vue3 main.ts  無關代碼自行省略
// @ts-nocheck
import { createApp } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import App from "./App.vue";
import routes from "./router";
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

let router = null;
let instance = null;

renderWithQiankun({
  mount(props) {
    storeTest(props);
    render(props);
    instance.config.globalProperties.$onGlobalStateChange =
      props.onGlobalStateChange;
    instance.config.globalProperties.$setGlobalState = props.setGlobalState;
  },
  bootstrap() {
    console.log("%c ", "color: green;", "sub-vite2-vue3 app bootstraped");
  },
  unmount(props: any) {
    instance.unmount();
    instance._container.innerHTML = "";
    instance = null;
    router = null;
  },
});

function render(props = {}) {
  const { container } = props;
  router = createRouter({
    history: createWebHistory(!qiankunWindow.__POWERED_BY_QIANKUN__ ? "/sub-vite2-vue3" : "/"),
    routes
  });

  instance = createApp(App);
  instance.use(router);
  instance.mount(container ? container.querySelector("#app") : "#app");
}

function storeTest(props) {
  props.onGlobalStateChange &&
    props.onGlobalStateChange(
      (value, prev) =>
        console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
      true
    );
  props.setGlobalState &&
    props.setGlobalState({
      ignore: props.name,
      user: {
        name: props.name
      }
    });
}
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  render({});
}
// react  main.ts  無關代碼自行省略
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";

// vite-plugin-qiankun helper
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

function render(props: any) {
  const { container } = props;
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    container
      ? container.querySelector("#root")
      : document.getElementById("root")
  );
}

renderWithQiankun({
  mount(props) {
    console.log("sub-vite2-react mount");
    render(props);
  },
  bootstrap() {
    console.log("bootstrap");
  },
  unmount(props: any) {
    console.log("sub-vite2-react unmount");
    const { container } = props;
    const mountRoot = container?.querySelector("#root");
    ReactDOM.unmountComponentAtNode(
      mountRoot || document.querySelector("#root")
    );
  },
});

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  render({});
}

如發現子應用圖片資源 404 , 控制台報錯顯示該資源在主應用路勁下;則 vite.config.ts 增加 origin

...
server: {
  ...
  origin: '//localhost:7722'
},

參考資源:

  1. https://github.com/umijs/qiankun/issues/1257
  2. https://github.com/tengmaoqing/vite-plugin-qiankun


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM