Vite のマルチルート
Vite のデフォルトだと package.json と同じルートの階層に index.html
があって、これがエントリポイント
Vite でエントリポイントを増やす場合は設定ファイルの rollupOptions
を使って rollup 側の設定を書くことになる
export default {
server: {
host: true,
},
build: {
rollupOptions: {
input: {
main: resolve(__dirname, "index.html"),
sub: resolve(__dirname, "sub.html"),
},
},
},
}
こうすると、 /sub
へのアクセスでは sub.html
が返され、それ以外はすべて index.html
のページになる
sub のアプリも SPA にしたくて、次のように書いても
input: {
main: resolve(__dirname, "index.html"),
sub: resolve(__dirname, "sub/index.html"),
},
/sub/*
へのアクセスは sub/index.html
にならず、 /sub/
や /sub/index.html
へのアクセスのみが sub/index.html
になる
/sub/abc
などへのアクセスは index.html
が返される
Vite 自身ではサポートしてないみたいなので、プラグイン等でサーバーの処理を書き換えて /sub/*
は /sub/index.html
になるようしないといけなそう
例)
https://stackoverflow.com/questions/78724231/how-to-setup-vite-multi-pages-react-spa-with-nested-routes-on-one-of-the-pages
マルチルート機能自体が Vite の設定というより rollup の設定を直接触って設定するものだし、完全なサポートになってなさそう
一般ユーザー用と管理者ユーザー用で別アプリだけどコードの多くを共有するのでエントリポイント 2 つでビルドみたいなケースは結構ありそうなのに
- app/user/index.html
- app/admin/index.html
みたいなエントリポイントにしたい
また、配置先もバラバラなケースがある
dir1/dir2/app1/*
dir1/dir3/dir4/app2/*
配置するフォルダがエントリポイントごとに違うけど Vite の設定ではサーバーのどこにアプリを設置するかは base
を一つ設定できるだけ
base
に相対パスの ./
も設定できるけど、これは .html ファイルから ./asset/file.js
みたいな読み込みになるだけ
HTML 中で base タグ等で制御してないと、別階層になる SPA ではアセットファイルが読み込めなくてエラーになる
出力先も同様で outDir
に一つ場所を指定できるだけ
エントリポイントごとに別々の出力にできない
ひとつの設定にまとめるより、それぞれ別の config ファイルを作ったほうがいいかも
上の 2 パターンでやってみるとこんな感じ
[app1.config.js]
import { dirname, resolve } from "node:path"
import { fileURLToPath } from "node:url"
const __dirname = dirname(fileURLToPath(import.meta.url))
export default {
server: {
host: true,
port: 8001,
},
base: "/dir1/dir2/app1",
build: {
outDir: "dist-app1",
rollupOptions: {
input: {
app1: resolve(__dirname, "app1.html"),
},
},
},
}
[app2.config.js]
import { dirname, resolve } from "node:path"
import { fileURLToPath } from "node:url"
const __dirname = dirname(fileURLToPath(import.meta.url))
export default {
server: {
host: true,
port: 8002,
},
base: "/dir1/dir3/dir4/app2",
build: {
outDir: "dist-app2",
rollupOptions: {
input: {
app2: resolve(__dirname, "app2.html"),
},
},
},
}
app1 を watch したいときは
pnpm vite -c app1.config.js
app2 を build したいときは
pnpm vite build -c app2.config.js
package.json に書くなら
{
"scripts": {
"app1": "vite -c app1.config.js",
"app2": "vite -c app2.config.js",
"build:app1": "vite build -c app1.config.js",
"build:app2": "vite build -c app2.config.js",
"build": "pnpm run build:app1 && pnpm run build:app2"
}
}
のような感じ
本題とそれるけど rollupOptions
の input
のオブジェクト
input: {
foo: resolve(__dirname, "bar.html"),
},
キーは foo
で、パスの方が bar.html
みたいに名前を揃えなくてもいい
パスは .html ファイルが存在するパスである必要があって、出力される HTML のファイル名は元のまま
この場合は bar.html
foo
の方は assets フォルダ内の .js ファイルの名前に使われる
キーを dir/foo
にすれば assets フォルダ内に dir フォルダが作られてその中に foo の .js ファイルが出力される
.js ファイルは自動で読み込まれる上にハッシュ値もつくものなので、名前を意識する必要はあまりなさそう
意識する必要のあるエントリポイントの .html ファイルの名前には影響しないので基本 .html のファイル名に合わせるで良さそう