静的アセットの取り扱い
Importing Asset as URL
静的アセットをインポートすると、配信された際に解決されたパブリックな URL が返されます:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
例えば、 imgUrl
は、開発中は /img.png
となり、本番用ビルドでは /assets/img.2d8efhg.png
となります。
振る舞いは webpack の file-loader
に似ています。異なるのは、絶対的なパブリックパス(開発中のプロジェクトのルートに基づく)または、相対パスを使用することができるという点です。
CSS 内の
url()
の参照も同様に扱われます。Vue プラグインを使用している場合、 Vue の SFC テンプレート内の asset references も自動的にインポートに変換されます。
一般的な画像、メディア、フォントなどの拡張子は自動的にアセットとして検出されます。また、
assetsInclude
オプション で内部リストを拡張することができます。参照されたアセットは build assets graph の一部として含まれ、ハッシュ化されたファイル名を取得し、プラグインを用いて最適化されます。
assetsInlineLimit
オプション で指定したバイト数よりも小さいアセットは base64 データの URL としてインライン化されますGit LFS のプレースホルダは、それが表すファイルの内容を含んでいないため、自動的にインライン化の対象から除外されます。インライン化するには、ビルドする前に必ずファイルの内容を Git LFS 経由でダウンロードするようにしてください。
TypeScript はデフォルトでは静的アセットのインポートを有効なモジュールとして認識しません。これを修正するには、
vite/client
を追加します。
明示的な URL のインポート
内部リストや assetsInclude
に含まれていないアセットは URL の末尾に ?url
を付与することで明示的にインポートすることができます。これは、例えば Houdini Paint Worklets をインポートするときに便利です。
import workletURL from 'extra-scalloped-border/worklet.js?url'
CSS.paintWorklet.addModule(workletURL)
import workletURL from 'extra-scalloped-border/worklet.js?url'
CSS.paintWorklet.addModule(workletURL)
アセットを文字列としてインポートする
アセットは末尾に ?raw
を付与することで文字列としてインポートすることができます。
import shaderString from './shader.glsl?raw'
import shaderString from './shader.glsl?raw'
スクリプトを Worker としてインポートする
スクリプトは末尾に ?worker
もしくは ?sharedworker
を付与することで web workers としてインポートすることができます。
// Separate chunk in the production build
import Worker from './shader.js?worker'
const worker = new Worker()
// Separate chunk in the production build
import Worker from './shader.js?worker'
const worker = new Worker()
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
// Inlined as base64 strings
import InlineWorker from './shader.js?worker&inline'
// Inlined as base64 strings
import InlineWorker from './shader.js?worker&inline'
詳細は Web Worker section を参照してください。
public
ディレクトリ
アセットが以下のような場合のとき:
- ソースコードで参照されない (例:
robots.txt
) - 全く同じファイル名を保持する必要がある(ハッシュ化しない)
- …または、アセットの URL を取得するためだけに、アセットのインポートを単純に書きたくない
そのとき、プロジェクトのルート配下の特別な public
ディレクトリにアセットを置くことができます。このディレクトリに配置されたアセットは開発環境ではルートパス /
で提供され、そのまま dist ディレクトリのルートにコピーされます。
ディレクトリのデフォルトは <root>/public
ですが、 publicDir
オプション で設定することができます。
注意点:
public
内のアセットを絶対パスで参照する際は常に次のように行う必要があります。 - 例えば、public/icon.png
はソースコード内では/icon.png
のように参照されなければなりません。public
内のアセットは、 JavaScript からはインポートすることができません。
new URL(url, import.meta.url)
i
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('hero-img').src = imgUrl
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('hero-img').src = imgUrl
これはモダンブラウザでネイティブに動作します。実際、開発中に Vite はこのコードを処理する必要が全くありません!
このパターンはテンプレートリテラルによる動的な URL もサポートします:
function getImageUrl(name) {
return new URL(`./dir/${name}.png`, import.meta.url).href
}
function getImageUrl(name) {
return new URL(`./dir/${name}.png`, import.meta.url).href
}
本番環境では、バンドル後やアセットハッシュ化の後でも URL が正しい場所を指すように、Vite が必要な変換を行ないます。ただし、URL の文字列は解析できるように静的である必要があります。そうでない場合はコードがそのまま残ってしまい、build.target
が i
をサポートしていない場合はランタイムエラーが発生する可能性があります。
// Vite はこれを変換しません
const imgUrl = new URL(imagePath, import.meta.url).href
// Vite はこれを変換しません
const imgUrl = new URL(imagePath, import.meta.url).href
SSR では動作しません
ブラウザと Node.js で i
のセマンティクスが異なるため、 このパターンは Vite をサーバサイドレンダリングで使用している場合には動作しません。サーババンドルは事前にクライアントホストの URL を決定することもできません。