Closed6
Vite
実務でも Vite を使用する機会が増えてきたため、公式ドキュメントをちゃんと読むスクラップ
Vite を使う理由
- ES モジュールがブラウザで使用できるようになるまで、JS にネイティブのモジュールシステムはなかった
- だから、webpack、Rollup、Parcel などのバンドラが生まれた
- ただ、これらのツールは JS の使用量が多くなるとパフォーマンスの問題が発生する
- 開発サーバーを立ち上げるときに、アプリケーション全体を隅々までクロールしてビルドする必要がある
- Vite はこの問題にどう対応するか
- アプリケーションのモジュールを依存関係とソースコードの 2 つのカテゴリーに分割
- esbuild を使用して依存関係の事前バンドル
- ソースコードはネイティブ ESM を行使してソースコードを提供
- ブラウザも実質的にバンドラーの一部に
- Vite はブラウザのリクエストに応じて、ソースコードを変換して提供するだけ
- キャッシュなども使用してより高速に
- Vite は開発サーバーではバンドルしないが、プロダクションでは Rollup でバンドルする
- ネットワークのラウンドトリップ増加が問題
- esbuild でバンドルしない理由は、Rollup のエコシステムを利用したいから
- 開発ビルドに esbuild、本番ビルドに Rollup を使用するためビルド結果に差異が出やすいなどの問題
- 将来的には Rolldown に置き換えられる方向
- Rolldown は Rollup の Rust ポートを構築する取り組み
特徴
- npm 依存関係の解決と事前バンドル
-
node_modules/.vite
に事前バンドル済みの依存関係をキャッシュする - 再バンドルしたい場合は、
vite --force
ornode_modules/.vite
を削除
-
import { someMethod } from 'my-dep'
↓
import { someMethod } from '/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd'
- HMR
-
create-vite
を使用した場合は設定不要で HMR が有効になる
-
- TypeScript
- Vite の責務は TS のトランスパイル ( esbuild を使用 )
- 型チェックは行わない
-
tsconfig.json
の設定"isolatedModules": true
- https://typescriptbook.jp/reference/tsconfig/isolatedModules
- JSX
- .jsx と .tsx も標準サポート
- esbuild によりトランスパイルされる
静的アセット
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
- 開発中
imgUrl
->/img.png
- 本番ビルド
imgUrl
->/assets/img.2d8efhg.png
SSR
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import express from 'express'
import { createServer as createViteServer } from 'vite'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
async function createServer() {
const app = express()
// ミドルウェアモードで Vite サーバーを作成し、app type を 'custom' に指定します。
// これにより、Vite 自体の HTML 配信ロジックが無効になり、親サーバーが
// 制御できるようになります。
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})
// Vite の接続インスタンスをミドルウェアとして使用。独自の express ルータ
// (express.Route()) を利用する場合は、router.use を使用してください
// (たとえばユーザーが vite.config.js を編集した後に)サーバーが再起動しても、
// `vite.middlewares` は同じリファレンスのままです(ただし、新しい Vite の内部スタックと
// プラグインが注入されたミドルウェアが使用されます)。
// 次のコードは再起動後でも有効です。
app.use(vite.middlewares)
app.use('*', async (req, res) => {
// index.html を提供します - 次にこれに取り組みます。
})
app.listen(5173)
}
createServer()
app.use('*', async (req, res, next) => {
const url = req.originalUrl
try {
// 1. index.html を読み込む
let template = fs.readFileSync(
path.resolve(__dirname, 'index.html'),
'utf-8',
)
// 2. Vite の HTML の変換を適用します。これにより Vite の HMR クライアントが定義され
// Vite プラグインからの HTML 変換も適用します。 e.g. global preambles
// from @vitejs/plugin-react
template = await vite.transformIndexHtml(url, template)
// 3. サーバーサイドのエントリーポイントを読み込みます。 ssrLoadModule は自動的に
// ESM を Node.js で使用できるコードに変換します! ここではバンドルは必要ありません
// さらに HMR と同様な効率的な無効化を提供します。
const { render } = await vite.ssrLoadModule('/src/entry-server.js')
// 4. アプリケーションの HTML をレンダリングします。これは entry-server.js から
// エクスポートされた `render` 関数が、ReactDOMServer.renderToString() などの
// 適切なフレームワークの SSR API を呼び出すことを想定しています。
const appHtml = await render(url)
// 5. アプリケーションのレンダリングされた HTML をテンプレートに挿入します。
const html = template.replace(`<!--ssr-outlet-->`, appHtml)
// 6. レンダリングされた HTML をクライアントに送ります。
res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
} catch (e) {
// エラーが検出された場合は、Vite にスタックトレースを修正させ、実際のソースコードに
// マップし直します。
vite.ssrFixStacktrace(e)
next(e)
}
})
理念
Vite は、すべてのユーザーのすべてのユースケースをカバーするつもりはありません。Vite は、Web アプリケーションを構築するための最も一般的なパターンをすぐにサポートすることを目指しています
Vite は、モダンなコードを書くことを後押しする opinionated な機能を提供します
このスクラップは2024/01/04にクローズされました