静的アセットの取り扱い
- 関連: パブリックベースパス
- 関連:
assetsInclude
設定オプション
アセットをURLとしてインポートする
静的アセットをインポートすると、提供される際に解決されたパブリックURLが返されます
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
例えば、imgUrl
は開発中は /src/img.png
で、本番ビルドでは /assets/img.2d8efhg.png
になります。
この動作はwebpackの file-loader
と似ています。違いは、インポートが絶対パブリックパス(開発中はプロジェクトルートに基づく)または相対パスのいずれかを使用できることです。
CSSの
url()
参照も同じように処理されます。Vueプラグインを使用している場合、Vue SFCテンプレートのアセット参照は自動的にインポートに変換されます。
一般的な画像、メディア、フォントファイルタイプは、アセットとして自動的に検出されます。
assetsInclude
オプションを使用して、内部リストを拡張できます。参照されるアセットはビルドアセットグラフの一部として含まれ、ファイル名がハッシュ化され、最適化のためにプラグインによって処理されます。
assetsInlineLimit
オプション より小さいバイト数のアセットは、base64データURLとしてインライン化されます。Git LFSプレースホルダーは、それらが表すファイルの内容を含んでいないため、インライン化から自動的に除外されます。インライン化するには、ビルド前にGit LFS経由でファイルの内容をダウンロードしてください。
TypeScriptは、デフォルトでは、静的アセットのインポートを有効なモジュールとして認識しません。これを修正するには、
vite/client
を含めます。
url()
を介したSVGのインライン化
JSによって手動で構築された url()
にSVGのURLを渡す場合、変数は二重引用符で囲む必要があります。
import imgUrl from './img.svg'
document.getElementById('hero-img').style.background = `url("${imgUrl}")`
明示的なURLインポート
内部リストまたは assetsInclude
に含まれていないアセットは、?url
サフィックスを使用してURLとして明示的にインポートできます。これは、たとえば、Houdini Paint Workletsをインポートする場合に便利です。
import workletURL from 'extra-scalloped-border/worklet.js?url'
CSS.paintWorklet.addModule(workletURL)
明示的なインライン処理
アセットは、それぞれ ?inline
または ?no-inline
サフィックスを使用して、インライン化またはインライン化なしで明示的にインポートできます。
import imgUrl1 from './img.svg?no-inline'
import imgUrl2 from './img.png?inline'
アセットを文字列としてインポートする
アセットは、?raw
サフィックスを使用して文字列としてインポートできます。
import shaderString from './shader.glsl?raw'
スクリプトをワーカーとしてインポートする
スクリプトは、?worker
または ?sharedworker
サフィックスを使用してWebワーカーとしてインポートできます。
// 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()
// Inlined as base64 strings
import InlineWorker from './shader.js?worker&inline'
詳細は、Webワーカーのセクション を確認してください。
public
ディレクトリ
以下の条件に当てはまるアセットがある場合
- ソースコードで参照されない(例:
robots.txt
) - 正確に同じファイル名を保持する必要がある(ハッシュ化なし)
- ...または、単にURLを取得するためだけにアセットをインポートしたくない場合
プロジェクトルートにある特別な public
ディレクトリにアセットを配置できます。このディレクトリのアセットは、開発中はルートパス /
で提供され、distディレクトリのルートにそのままコピーされます。
ディレクトリのデフォルトは <root>/public
ですが、publicDir
オプションで設定できます。
public
アセットは常にルート絶対パスを使用して参照する必要があることに注意してください。たとえば、public/icon.png
はソースコードで /icon.png
として参照する必要があります。
new URL(url, import.meta.url)
import.meta.url は、現在のモジュールのURLを公開するネイティブESM機能です。ネイティブの URLコンストラクタと組み合わせることで、JavaScriptモジュールからの相対パスを使用して、静的アセットの完全な解決済みURLを取得できます。
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('hero-img').src = imgUrl
これは最新のブラウザでネイティブに動作します。実際、Viteは開発中にこのコードをまったく処理する必要がありません!
このパターンは、テンプレートリテラルを介した動的URLもサポートしています
function getImageUrl(name) {
// note that this does not include files in subdirectories
return new URL(`./dir/${name}.png`, import.meta.url).href
}
本番ビルド中に、Viteは必要な変換を実行するため、バンドルとアセットのハッシュ化後もURLは正しい場所を指します。ただし、URL文字列は分析できるように静的でなければなりません。そうでない場合、コードはそのまま残され、build.target
が import.meta.url
をサポートしていない場合にランタイムエラーが発生する可能性があります
// Vite will not transform this
const imgUrl = new URL(imagePath, import.meta.url).href
仕組み
Viteは getImageUrl
関数を以下に変換します
import __img0png from './dir/img0.png'
import __img1png from './dir/img1.png'
function getImageUrl(name) {
const modules = {
'./dir/img0.png': __img0png,
'./dir/img1.png': __img1png,
}
return new URL(modules[`./dir/${name}.png`], import.meta.url).href
}
SSRでは動作しません
このパターンは、Viteをサーバーサイドレンダリングに使用している場合は機能しません。なぜなら、import.meta.url
はブラウザとNode.jsで異なるセマンティクスを持つためです。また、サーバーバンドルはクライアントホストURLを事前に決定できません。