如何使用 Vike 和 Vite 構(gòu)建可擴(kuò)展的微前端
微前端允許您將大型 Web 應(yīng)用程序拆分為更小、可管理的部分。這種方法的靈感來自微服務(wù)架構(gòu),它允許不同的團(tuán)隊(duì)成員使用他們喜歡的框架和構(gòu)建工具獨(dú)立開發(fā)和擴(kuò)展應(yīng)用程序的不同部分。
Vite 是微前端的絕佳選擇,因?yàn)樗臉?gòu)建時(shí)間短且設(shè)置簡單。最近,情況得到了進(jìn)一步的改善,因?yàn)槟F(xiàn)在可以使用 Vike(以前稱為 vite-plugin-ssr)構(gòu)建 SSR(服務(wù)器端渲染)應(yīng)用程序,同時(shí)仍然可以從微前端架構(gòu)中受益。
在本教程中,我們將探討如何使用 Vike 和 vite-plugin-federation。我們將對 Vike 進(jìn)行簡短的介紹,介紹它的一些功能,這些功能使構(gòu)建 SSR 變得有趣,并討論如何利用它來構(gòu)建可擴(kuò)展的微前端。
什么是Vike?
Vike(不要與其父構(gòu)建工具 Vite 混淆)是 vite-plugin-ssr 的新名稱。Vike 最初是一個插件,旨在為 Vite 添加服務(wù)器端渲染 (SSR) 功能,但后來它已經(jīng)發(fā)展成為一個更全面的框架,用于構(gòu)建完整的 Web 應(yīng)用程序。
在這樣的場景,Vike 利用 Vite 的捆綁和開發(fā)服務(wù)器來設(shè)置一個服務(wù)器,以動態(tài)呈現(xiàn)應(yīng)用程序的頁面。當(dāng)用戶請求頁面時(shí),Vike 會在運(yùn)行時(shí)在服務(wù)器上生成 HTML,這使其成為具有頻繁更改的動態(tài)內(nèi)容的應(yīng)用程序的理想選擇。
除了作為 SSR 框架之外,Vike 還可以用作靜態(tài)站點(diǎn)生成器 (SSG),與 SSR 相比,它將在構(gòu)建時(shí)為您的網(wǎng)站預(yù)先生成 HTML 和資產(chǎn)文件,以便當(dāng)用戶請求頁面時(shí),服務(wù)器只需提供這些預(yù)先構(gòu)建的 HTML 文件。
主要特點(diǎn)
除了 SSR 和 SSG 功能外,Vike 的其他一些主要功能包括:
- 快速 —Vike 在設(shè)計(jì)上速度很快,因?yàn)樗昧舜a分割、鏈接預(yù)取和快速冷啟動等技術(shù)
- 零配置 — Vike 也幾乎不需要配置,只讓您在重要的地方進(jìn)行控制;其他一切都開箱即用
- 集成 — Vike 是一個完整的框架,可以輕松地與數(shù)據(jù)獲取、身份驗(yàn)證、服務(wù)器管理、CSS 框架和國際化工具集成
- 支持多種框架 — Vike 非常靈活,可與 React、Vue、Svelte 等框架或您喜歡的任何其他框架配合使用
Vike 入門
npm create vike@latest
# OR
yarn create vike
運(yùn)行此命令將提示您選擇首選的 JavaScript 框架,并根據(jù)所選框架創(chuàng)建新項(xiàng)目。
Vike 還支持 Bun 運(yùn)行時(shí),這意味著您可以使用以下命令啟動新項(xiàng)目:
bun create vike
Bati 用于高級設(shè)置
Vike 團(tuán)隊(duì)開發(fā)了一個腳手架工具 Bati,它允許您通過選擇首選的 CSS 庫(如 Tailwind 或 DaisyUI)、身份驗(yàn)證方法、數(shù)據(jù)庫、數(shù)據(jù)獲取庫等來自定義項(xiàng)目設(shè)置 - 所有這些都在安裝過程中完成。
例如,要使用 React 和 Tailwind 創(chuàng)建新的 Vike 應(yīng)用程序,您可以運(yùn)行:
npm create bati -- --react --tailwindcss
此命令將構(gòu)建所選安裝選項(xiàng)所需的文件和目錄。接下來,我們需要通過運(yùn)行來安裝所有必需的包:
npm install
最后,從以下位置開始您的應(yīng)用程序:
npm run dev
您的應(yīng)用程序現(xiàn)在應(yīng)該在瀏覽器中運(yùn)行,您應(yīng)該會看到類似于下圖的輸出:
圖片
使用 Vike 和 vite-plugin-federation 進(jìn)行微前端
Vike 不能僅用于構(gòu)建微前端;它必須與模塊聯(lián)合插件集成,該插件允許您在不同的應(yīng)用程序之間共享組件和狀態(tài)。在 Vite 生態(tài)系統(tǒng)中,一個流行的選項(xiàng)是 vite-plugin-federation。
要使用 vite-plugin-federation,我們需要設(shè)置至少兩個項(xiàng)目,其中一個將充當(dāng)主機(jī),另一個將作為遠(yuǎn)程項(xiàng)目,我們希望從中訪問某些組件或共享應(yīng)用程序狀態(tài)。
在我們的例子中,一個 Vike 項(xiàng)目將是主機(jī),而一個獨(dú)立的 vite+react/vue/svelte 項(xiàng)目將充當(dāng)遠(yuǎn)程項(xiàng)目。下圖也更好地說明了這一點(diǎn):
圖片
如上圖所示,我們將有一個獨(dú)立的組件(例如,卡片組件),在裸露的 Vite 應(yīng)用程序中創(chuàng)建,在本例中為 Vite + Vue。然后,我們將使用 vite-plugin-federation 在另一個獨(dú)立的 Vike-react 應(yīng)用程序中導(dǎo)入并重用此組件。
讓我們編寫一些代碼來查看實(shí)際的實(shí)現(xiàn)!
設(shè)置遠(yuǎn)程 Vite + Vue 應(yīng)用
首先,為您的微前端項(xiàng)目創(chuàng)建一個新文件夾并移動到其中:
mkdir micro-vike && cd micro-vike
接下來,運(yùn)行以下命令來創(chuàng)建遠(yuǎn)程 Vite + vue 應(yīng)用程序,我們將從中導(dǎo)出一個卡片組件,供其他獨(dú)立應(yīng)用程序重用:
npm create vite@latest vue-card -- --template vue
要繼續(xù),請移動到新的項(xiàng)目目錄并運(yùn)行以下命令,將 vite-plugin-federation安裝為 dev 依賴項(xiàng):
cd vue-card
npm install @originjs/vite-plugin-federation --save-dev
當(dāng)你在 dev 模式下運(yùn)行 Vite 應(yīng)用程序時(shí),它會檢查并嘗試在默認(rèn)的 5173 端口中運(yùn)行它;如果此端口不可用,它將在另一個隨機(jī)端口中啟動應(yīng)用程序。但是,對于我們的實(shí)現(xiàn),我們需要知道運(yùn)行遠(yuǎn)程應(yīng)用程序的端口,因?yàn)槲覀儗⒂嗛喫?/p>
因此,我們必須強(qiáng)制我們的應(yīng)用程序在自定義端口中啟動。為此,請打開您的項(xiàng)目package.json并更新 dev 腳本以匹配以下腳本:
. . .
"scripts": {
"dev": "vite --port 5001 --strictPort",
}
. . .
通過此新更新,我們的應(yīng)用程序被迫在端口 5001 中運(yùn)行。
接下來,我們來設(shè)計(jì)要導(dǎo)出的 card 組件。創(chuàng)建新 Card。vue 系列文件,并將以下代碼粘貼到其中:
<template>
<div class="container">
<h1 class="title">{{ title }}</h1>
<p class="description">{{ description }}</p>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
});
</script>
<style scoped>
.container {
padding: 16px;
background-color: #f9f9f9;
border-radius: 8px;
}
.title {
font-size: 24px;
color: #333;
margin-bottom: 8px;
}
.description {
font-size: 16px;
color: #666;
}
</style>
上面的代碼定義了一個基本的 Card 組件,該組件具有作用域樣式,并且該 card 接受 title 和 description 屬性。在繼續(xù)之前,你可以在你的 Vue 應(yīng)用程序中導(dǎo)入這個組件來測試并確保一切正常:
<!-- src/App.vue -->
<template>
<div>
<h1>Remote Vite + Vue app</h1>
<Card
title="Hello World"
descriptinotallow="This is a description passed as a prop."
/>
</div>
</template>
<script setup>
import Card from "./components/Card.vue";
</script>
您應(yīng)該會看到類似于下面的輸出。
圖片
要使 Card (卡片) 組件遠(yuǎn)程可用,請打開默認(rèn) vite。config。JS文件并使用以下代碼更新其內(nèi)容:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import federation from "@originjs/vite-plugin-federation";
export default defineConfig({
plugins: [
vue(),
federation({
name: "remote_app",
filename: "remoteEntry.js",
exposes: {
"./Card": "./src/components/Card.vue",
},
shared: ["vue"],
}),
],
build: {
modulePreload: false,
target: "esnext",
minify: false,
cssCodeSplit: false,
},
});
在這里,我們定義了一個名為 remote_app 的模塊聯(lián)邦,其他應(yīng)用程序可以使用它來引用我們的 Vite + Vue 應(yīng)用程序。此外,文件名:remoteEntry.js的option 指定生成的主入口文件的名稱;此文件包含其他應(yīng)用程序加載我們公開的組件所需的所有信息。
請務(wù)必驗(yàn)證此文件是否是在構(gòu)建項(xiàng)目后生成的。通常,它應(yīng)該在 http://localhost:5001/assets/remoteEntry.js 上提供。但是,在極少數(shù)情況下,它可以在 http://localhost:5001/dist/assets/remoteEntry.js 上獲得。
此外,在上面的配置中,我們使用了 exposes 選項(xiàng)來公開我們的 Card 組件,以便其他應(yīng)用程序可以使用 remote_app/Card 導(dǎo)入它。此外,因?yàn)槲覀兪褂玫氖悄K聯(lián)合,所以我們需要更新構(gòu)建過程以禁用 modulePreload,從而控制模塊的動態(tài)加載方式;我們還將 target 設(shè)置為 esnext,以確保我們使用模塊聯(lián)合正常工作所需的最新 JavaScript 功能。
最后,通過運(yùn)行以下命令構(gòu)建并啟動遠(yuǎn)程應(yīng)用程序:
npm run build
npm run dev
生成 remoteEntry 需要 build 命令。JS文件,并且 npm run dev 命令允許通過 localhost 訪問它。
設(shè)置Vike-react host應(yīng)用程序
現(xiàn)在,讓我們深入了解如何創(chuàng)建將利用我們剛剛公開的Card 組件的主機(jī)應(yīng)用程序?;氐侥闹黜?xiàng)目根目錄 micro-vike — 并通過運(yùn)行以下命令使用 Bati 搭建新的 Vike-react 基架:
npm create bati -- --react host
上面的命令在名為 host 的新目錄中設(shè)置項(xiàng)目,到目前為止,我們應(yīng)該有一個類似于下面的結(jié)構(gòu):
micro-vike/
├── vue-card/
│ └── . . .
└── host/
└── . . .
接下來,通過運(yùn)行以下命令在主機(jī)項(xiàng)目中安裝 vite-plugin-federation:
更新 vite.config.js文件以匹配以下內(nèi)容:
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import vike from "vike/plugin";
import federation from "@originjs/vite-plugin-federation";
export default defineConfig({
plugins: [
vike(),
react(),
federation({
name: "app",
remotes: {
remoteApp: "http://localhost:5001/dist/assets/remoteEntry.js",
},
shared: ["react", "react-dom"],
}),
],
build: {
modulePreload: false,
target: "esnext",
minify: false,
cssCodeSplit: false,
},
});
在這里,我們進(jìn)行了與遠(yuǎn)程應(yīng)用程序類似的更改,此外,我們還更新了主機(jī)應(yīng)用程序以連接到我們之前定義的 remoteEntry URL。
通過所有這些更改,我們現(xiàn)在可以在 Vike-react 項(xiàng)目中加載我們之前使用 Vue 創(chuàng)建的 Card 組件,如下所示:
// pages/index/+Page.jsx
import React from "react";
import Card from "remoteApp/Card";
export default function Page() {
return (
<>
<h1>Vike + React</h1>
<Card
title="Hello World"
description="This is a description passed as a prop."
/>
</>
);
}
使用以下命令啟動應(yīng)用程序:
npm run dev
當(dāng)我們運(yùn)行 Vike 應(yīng)用程序時(shí),您應(yīng)該會看到類似于下面的輸出:
圖片
就是這樣!我們已經(jīng)成功地將一個獨(dú)立的 Vite + vue 項(xiàng)目的 Vue 組件加載到另一個 Vike-react 項(xiàng)目中!
Monorepo 考慮
值得一提的是,您還可以集成 Nx 和 Turborepo 等 Monorepo 框架,以將您的微前端整合到一個存儲庫中。這樣,您可以進(jìn)一步簡化代碼共享、依賴項(xiàng)管理和配置,并減少維護(hù)工作。
但是,這是否是正確的選擇取決于您的項(xiàng)目要求。如果您有興趣開始使用 Nx,可以參考此采用指南:https://blog.logrocket.com/nx-adoption-guide。
結(jié)論
在本教程中,我們探討了 Vike、它的主要功能、如何開始使用它,以及如何將其與 vite-plugin-federation 結(jié)合使用以構(gòu)建可擴(kuò)展的微前端應(yīng)用程序。您還可以在此 GitHub 存儲庫中找到本教程中使用的所有代碼。
原文來源:https://blog.logrocket.com/build-scalable-micro-frontends-vike-vite/
原文作者:Elijah Asaolu
本文翻譯:一川