關注公眾號: 微信搜索 前端工具人
; 收貨更多的干貨
原文鏈接: 自己掘金文章 https://juejin.cn/editor/drafts/7078238272064847903
vite
已經大火了, 自從用上了就停不下來` ;
但礙於 vite
初來乍到, 生態不夠成熟, 有些功能還是比較尷尬的,比如微前端;
qiankun
微前端搭建詳細步驟及常見問題,可參考之前文章 https://juejin.cn/post/6943763969576271879
以下源碼也已上傳至 github
開篇
去年初項目接入微前端的時候,就准備使用 vite
, 一頓構操作下來,發現 vite
應用一直無法獲取生命周期, 才知道那時 qiankun
暫時不支持 vite
應用
大致原因如下:
vite
構建的js
內容必須在type=module
的script
腳本里;- 當時
qiankun
的源碼依賴之一import-html-entry
則不支持type=module
這個屬性 (目前已支持); qiankun
是通過eval
來執行這些js
的內容,而vite
里面import/export
沒有被轉碼, 所以直接接入會報錯:不允許在非type=module
的script
里面使用import
;
在去年年尾的時候,在qiankun
的 issues
中找到了2
種方法;
還是這些大佬牛逼;下面介紹下這2種方法
方法一 (不推薦)
- 結合
rollup/plugin-html
插件; - 修改
Vite.config.js
中的build
配置默認Vite
的輸出目標target
是module
,改為esnext
- 詳細步驟可參考
https://github.com/umijs/qiankun/issues/1268
缺點:
- 可以實現生產環境接入,開發環境不行;
vite
沒有動態publicPath
的支持;所以Vite.config
中base
配置需要寫死;vite
code-splitting(
代碼分割)功能並不支持iife
和umd
兩種格式,導致路由無法懶加載;- 圖片資源只會被打包成
base64
,無論圖片大小
方法二 (推薦)
vite-plugin-qiankun
插件; github文檔
優點
- 保留
vite
構建es
模塊的優勢 - 一鍵配置,不影響已有的
vite
配置 - 支持
vite
開發環境
- 安裝插件
pnpm add vite-plugin-qiankun
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
})
],
})
}
- 導出相應的生命周期
// 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'
},
參考資源: