webpack と ES Module Import Assertions についての調査
ES Module の Import Assertions が各環境で使えるようになるのも遠くない。
しかし現実のユースケースではまだまだモジュールバンドラーを使ってデプロイ前にモジュール解決を済ませることが多いだろうから、Import Assertions を直接ブラウザ上で使用することは少ないだろう。
というわけでソースコードで Import Assertions を使ったときに、webpack によるモジュール解決がどのように振る舞うかを調べてみた。なぜ調べる必要があったかというと、ドキュメンテーションが(そこそこ探した限りでは)見つからず、ブログなどのアンオフィシャルなものすら見当たらなかったからだ。だが、GitHub の履歴を見ると間違いなく Import Assertions に対応する実装は加えられていたので、実態がどうなっているかは実際に動かして試すこととなった。
アサーションなし(ファイル拡張子による判別)
data.json
ファイルを拡張子付きのパスでインポートする。webpack は JSON のインポートをビルトインでサポートしており、これはそのまま自動的に JSON としてパースされる。

data.jsonのインポート(アサーションなし)
インポートのパスで拡張子を省略していても、デフォルトの webpack 設定が .json
の省略を許可しているので自動的に探索され、ファイルの拡張子から JSON であることを判別する。

data.jsonのインポート(アサーションなし、拡張子省略)
つまり、ファイルの拡張子を削除すると webpack はそのファイルが JSON であることがわからなくなり、モジュールのパースに失敗する。次の例では ./data
ファイルをインポートしようとしてパースできずにエラーになっている。

dataのインポート(アサーションなし、拡張子なし)は失敗する
アサーションあり ( JSON )
ここからは Import Assertions によるファイル形式のアサーションを試みる。 assert { type: 'json' }
を付与し、先ほどの拡張子がない JSON ファイルのインポートをすると、JSON であることを判別し、問題なくパースできていた。(エディタ上の赤線は無視してほしい)

dataのインポート(JSONアサーションあり)は成功する
その他のファイル形式のアサーション
webpack といえば Loader によってさまざまな形式のファイルをモジュール解決できるのが魅力だ。webpack の Import Assertions は JSON 以外にも対応しているのか一応試してみた。
JSON の拡張である JSON5 のファイル data.json5
をパースできるか試してみた。事前に json5-loader
をインストールした上で、特に webpack 設定には手を入れずに type: 'json5'
を指定してみたが、これではモジュール解決できなかった。エラーを見るに、JSON としてパースしようとして失敗したようだ。なぜ JSON だと解釈したのだろうか?

data.json5のパース(アサーションあり)は失敗
次に、 styles.postcss
というファイルを用意し、さらに webpack 設定に .css
ファイルについてのルールを追加した(一般的な style-loader
と css-loader
を通すもの)。そのうえで、 styles.postcss
ファイルを type: 'css'
だとアサーションしてインポートするとどうなるかを試してみた。
結果は以下のように、 .postcss
ファイルに対応する Loader がないためにパースできずエラーとなった。アサーションによって Loader を切り替えるようなことは(少なくとも今は)できないようだ。

cssであることをアサーションで教えることはできなかった
現状の結論
webpack の Import Assertions 対応は、現状では JSON 形式のアサーションだけが可能なようだ。そもそも拡張子さえあればもともと JSON のインポートはビルトインサポートされていることから、この対応で何か新しい機能が増えているわけではない。
開発者はこれまでどおりアサーションなしにインポートしてもよいが、それは webpack が気を利かせてくれているだけだ。そして webpack 以外でも JSON を読み込める標準化された記法に切り替えるという選択肢も用意されている、ということだろう。
今回の調査は Stackblitz 上の Node.js 環境で行った。再現したい場合はこちらを参照されたし。
