Assets
minista はテンプレートに使用している React の JavaScript を完全に切り捨てるため、実際の web サイトで実行する JavaScript は Config からのエントリー制にしています。
// minista.config.ts
export default {
assets: {
entry: ["src/assets/script.ts", "src/assets/style.css"],
},
}
※CSS のエントリーも可能ですが、v2 以降は後述する Bundle 機能の方が手軽です。
また、assets.entry
ではページごとに読み込む CSS・JavaScript を設定することも可能です。内部的には picomatch を使用しており、グロブ形式でページのパスを指定できます。
// minista.config.ts
export default {
assets: {
entry: [
{
name: "pc",
input: "src/assets/pc.ts",
insertPages: ["/pc/**/", "/pc/**/*"],
},
{
name: "smp",
input: "src/assets/smp.ts",
insertPages: ["/smp/**/", "/smp/**/*"],
},
],
},
}
Bundle
JSX のテンプレート Pages・Components・Root で import した CSS ファイルは自動的に bundle.css
として結合され全体に適応されます。
Partial Hydration
Components を部分的に React App として動くアセットに変換できます。参照パスの末尾に ?ph
を付与することで Partial Hydration の対象となります。
定義したコンポーネントでは React の Hook などを自由に使えます。ただし、コンポーネントは隔離されているためページから props を渡せません。また、named export には対応していません。
// Example Page
import BlockCounter from "../../components/block-counter?ph"
export default () => {
return <BlockCounter /> // You can't pass Props.
}
// components/block-counter.tsx
import { useState, useCallback } from "react"
export default () => {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount((c) => c + 1), [])
return (
<div className="block-counter">
<button onClick={increment} type="button">
increment
</button>
<p>count: {count}</p>
</div>
)
}
本番ビルドした際にすべての Partial Hydration 対象コンポーネントは集められ 1 つの JavaScript ファイルが生成されます。ページファイルには復元用のラップ要素 div
と静的な HTML が書き込まれます。 Cumulative Layout Shift (CLS) の抑制に有効です。
ブラウザでコンポーネントが画面に表示されると React App として復元されます。
<!-- Example Page -->
<head>
<script defer src="/assets/partial.js"></script>
</head>
<body>
<div data-partial-hydration="ph-1" style="display:contents;">
<div class="block-counter" data-reactroot="">
<button type="button">increment</button>
<p>count: 0</p>
</div>
</div>
</body>
useSplitPerPage
partial.js
を使うページに応じて分割し <script />
タグの挿入も最適化します。
// minista.config.ts
export default {
assets: {
partial: {
useSplitPerPage: true,
},
},
}
usePreact
partial.js
は Vite で Tree Shaking されますが react-dom
130KB を内包するため大きめです。そこで preact
をインストール、以下 Config を有効化してみてください。22KB 程度に削減できます。
$ npm install preact
// minista.config.ts
export default {
assets: {
partial: {
usePreact: true,
},
},
}
Raw
アセットを文字列としてインポートする場合は、参照ファイルの末尾に ?raw
を付与します。
import demoHtml from "../assets/demo.html?raw"
export default () => {
return (
<div
dangerouslySetInnerHTML={{
__html: demoHtml,
}}
/>
)
}
SVGR
SVG ファイルは React Component としてインポートできます。
import Logo from "../../assets/svgs/logo.svg"
export default () => {
return <Logo title="minista" className="svgr-logo" width={400} height={88} />
}
Sprite Icons
src/assets/icons
に SVG アイコンを入れると自動的にスプライト化され ID 付きのパスで簡単に使えます。
export default () => {
return (
<svg>
<use href="/assets/images/icons.svg#foo"></use>
</svg>
)
}
Remote Download
Config で assets.download.useRemote
を true
にするとテンプレートに流し込んだ CMS などのリモート画像を自動的にダウンロードしてパスを置換します。
export default () => {
return (
<img
src="https://user-images.githubusercontent.com/9658016/154976421-7762ca39-cea1-4e69-9296-ec1c9e35a088.png"
alt=""
/>
)
}
// => <img src="/assets/images/remote-1.png" alt="">