シェーダー、HTMLテンプレート、CSVのフィクスチャ。フロントエンドでは、JavaScript以外のテキストファイルを読み込みたい場面がよくあります。これまでは`fetch()`で取得するか、ビルドツールのraw importに頼るのが一般的でした。
Chrome 155が、TC39のImport Text(Stage 3)に対応しました。`import ... with { type: "text" }`と書くと、テキストファイルを文字列としてESモジュールに取り込めます。この記事では、Import Textで何が変わるのか、使い方、バンドラー対応の注意点を整理します。
30秒でわかる結論
- Chrome 155が`import ... with { type: "text" }`に対応した。
- テキストファイルを文字列としてESモジュールグラフに取り込める。
- `fetch()` + `await response.text()`の定型コードを減らせる。
- Web Worker内のモジュールでも使える。
- 現時点ではChrome限定。Stage 3なので、公開サイトの基幹機能にはまだ早い。
何が起きたのか:Import TextのStage 3とChrome 155
Import Textは、TC39でStage 3まで進んでいる提案です。`import`文のimport attributesとして`{ type: "text" }`を指定すると、ファイルの中身を文字列として読み込みます。Chrome 155がこの機能を実装しました。
似た仕組みにJSON modules(`with { type: "json" }`)があります。JSON modulesはJSONをオブジェクトとして読み込みますが、Import Textは任意のテキストを文字列として読み込みます。CSS、HTML、GLSL、CSV、Markdownなどを、モジュールとして扱えるイメージです。
何が変わるのか:fetchからimportへ
これまでテキストファイルを読むには、実行時に`fetch()`して`text()`を呼ぶ必要がありました。非同期処理、パス解決、エラーハンドリング、キャッシュを自分で扱うことになります。
// これまで: fetchで取得
const response = await fetch("/shader.glsl");
if (!response.ok) throw new Error("failed to load shader");
const shader = await response.text();// Import Text: モジュールとして取り込む
import shader from "./shader.glsl" with { type: "text" };Import Textなら、モジュールグラフの一部として静的に解決されます。バンドラーが依存関係を把握でき、ビルド時にファイルを同梱できます。`fetch()`の非同期処理や、公開パスの管理から解放されます。
項目 | fetch | Import Text |
|---|---|---|
取得タイミング | 実行時 | モジュール解決時 |
非同期処理 | 必要 | 不要 |
バンドラー連携 | 手動でパス管理 | 依存関係として扱える |
Worker | fetchで取得 | モジュールとしてimport |
使い方:シェーダーとテンプレート
代表的なのは、WebGL/WebGPUのシェーダー、HTMLテンプレート、テスト用のフィクスチャです。
import vertexShader from "./shaders/vertex.glsl" with { type: "text" };
import fragmentShader from "./shaders/fragment.glsl" with { type: "text" };
import template from "./templates/card.html" with { type: "text" };
const material = new ShaderMaterial({
vertexShader,
fragmentShader,
});
container.innerHTML = template;テキストを文字列として扱うため、テンプレートエンジンに渡す、シェーダーをコンパイルする、CSVをパースする、といった処理にそのまま使えます。
コード内の`<`や`&`は、HTMLファイルとしてではなく「テキスト」として読み込まれます。テンプレートをHTMLとしてDOMに挿入する場合は、サニタイズが必要です。Import Textはサニタイズまでは行いません。
Import TextとJSON modulesの違い
JSON modulesは`with { type: "json" }`を使い、JSONをオブジェクトとして読み込みます。一方、Import Textは任意のテキストを文字列として読み込みます。使い分けは「構造化データならJSON modules、生のテキストならImport Text」です。どちらもimport attributesを使いますが、読み込み結果の型が異なります。
たとえば設定ファイルを読むならJSON modules、シェーダーやテンプレートならImport Textが向きます。Import Textは文字列を返すだけなので、パースやバリデーションは自分で行います。Zodなどで検証する前提なら、JSON modulesよりImport Textの方が扱いやすい場合もあります。
実務での使い方:ビルド資産としてのテキスト
- WebGL/WebGPUのシェーダーを、JSから分離して管理する。
- HTMLメールやカードのテンプレートを、文字列としてimportする。
- テスト用のCSV/JSONフィクスチャを、モジュールとして読み込む。
- ライセンス文、使い方のMarkdown、CLIのヘルプ文を埋め込む。
- Web Workerで使うシェーダーやテンプレートを、同じモジュールグラフで管理する。
- Web Componentsのテンプレート文字列を、HTMLファイルとして編集してimportする。
- CLIツールのヘルプ文やライセンス文を、Markdownのままバンドルに含める。
特にシェーダーは、JSの文字列テンプレートに埋め込むとシンタックスハイライトが効かず、編集しにくいという課題がありました。Import Textなら`.glsl`ファイルとして編集し、ビルド時に取り込めます。
注意点:Chrome限定とStage 3
- 対応はChrome 155のみ。Firefox/Safariは未対応。
- TC39 Stage 3のため、仕様が変わる可能性がある。
- バンドラー(Vite/Webpack等)の対応状況を確認する。未対応ならビルドで失敗する。
- MIMEタイプやファイル拡張子の設定が必要な場合がある。
- テキストをDOMに挿入する場合は、XSS対策としてサニタイズする。
本番サイトで使っていい?→ 公開サイトの基幹機能には、まだ早いです。Chrome限定の社内ツール、プロトタイプ、ビルド時にバンドラーが解決してくれる構成なら試せます。クロスブラウザが必要なら、従来の`fetch()`かraw importを残してください。
フォールバック:バンドラーに任せる
Import Textが使えない環境では、バンドラーのraw import(Viteの`?raw`、Webpackの`asset/source`)が代替になります。ただし、構文はバンドラーごとに異なります。
// Viteの例(Import Text非対応環境の代替)
import shader from "./shader.glsl?raw";Import Textが標準化されれば、バンドラー固有の構文を減らせます。それまでは、プロジェクトのビルド環境に合わせて使い分けます。
対応状況と使う判断
環境 | 対応 | 備考 |
|---|---|---|
Chrome 155以降 | 対応 | `with { type: "text" }` |
Firefox | 未対応 | Stage 3のため今後実装の可能性 |
Safari | 未対応 | Stage 3のため今後実装の可能性 |
バンドラー | 対応状況による | Vite/Webpackのraw importを併用 |
自分なら使うか:条件付きで使う。 Chrome限定の社内ツールや、バンドラーが解決してくれる構成なら試します。公開サイトのコア機能には、Firefox/Safariの対応とStage 4化を待ってから導入します。
まとめ
- Chrome 155がImport Textに対応し、テキストをESモジュールとして読めるようになった。
- `fetch()` + `text()`の定型コードを減らし、バンドラーの依存関係に乗せられる。
- シェーダー、テンプレート、フィクスチャ、Markdownなどに向く。
- Chrome限定・Stage 3のため、公開サイトの基幹機能にはまだ早い。
- バンドラーのraw importをフォールバックにし、小さなツールから試す。






