Astro 的特點之一,就是可以使用各家框架的元件,像是 React, Vue, Svelte 等,能夠將不同來源的元件拼合到一頁上,在 Monorepo 的架構下就能用來將元件通用於靜態網頁跟需要高互動的網頁專案之間,非常有趣。
不過還是有些限制,Astro 主要在 Server 環境下生成靜態資源,所以一些需要瀏覽器環境才能運作的套件就不能用,像是 css-in-JS 的套件,所以目前用不了需要 emotion 支撐的 MUI。
不過或許可以靠搭配 Base-UI 跟 tailwind 的方式利用一些 MUI 的功能,之後來試試看,這邊先來設定 tailwind ,讓專案有一個可以在各框架之間通用的樣式系統。
pnpm add -D @astrojs/tailwind
將 tailwind 集成到 astro 上。
// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
// ...
integrations: [tailwind()],
});
在 astro 專案下設定 tailwind 。
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
const { join } = require('path');
module.exports = {
content: [
join(
__dirname,
'{src,pages,components,app}/**/*!(*.stories|*.spec).{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
),
...createGlobPatternsForDependencies(__dirname),
],
plugins: [],
corePlugins: {
preflight: false,
},
};
跟之前一樣要讓 tailwind 關注有依賴關係的 lib 當中的套件,好生成樣式。
再來在 React 元件包裡生成一個元件。
pnpm exec nx generate @nx/react:component
✔ What is the name of the project for this component? · ui-react-components
✔ What name would you like to use for the component? · HelloAstro
✔ Which stylesheet format would you like to use? · none
✔ Should this component be exported in the project? (y/N) · false
元件直接用 tailwind 做樣式。
export interface HelloAstroProps {}
export function HelloAstro(props: HelloAstroProps) {
return (
<div>
<h1 className="text-red-500">🧑🚀 Hello, Astronaut!</h1>
</div>
);
}
export default HelloAstro;
再來設定讓 astro 能認得 React 元件
pnpm add -D @astrojs/react
將 React 設定導入 Astrio。
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import react from '@astrojs/react';
export default defineConfig({
// ...
integrations: [tailwind(), react()],
});
這樣就能在 .astro 檔案中使用 React 元件了。
import { HelloAstro } from '@ironman-nextjs/ui/react-components';
<html lang="en"><head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header title={SITE_TITLE} />
<main>
<HelloAstro/>
<!-- ... -->
</main>
</body>
</html>
不過到這邊還沒辦法讓元件中的 tailwind 樣式產生作用,因為 NX 無法自動將 Astro 專案跟 React 元件生成關聯,要在雙邊設定 tag 來做手動關聯。
// astro project.json
{
// ...
"tags": ["scope:ironman-astro"],
"implicitDependencies": ["tag:scope:ironman-astro"]
}
// react ui project.json
{
// ...
"tags": ["scope:ironman-astro"]
}