nomodule によるフォールバック
nomodule 属性を使うと、ES Modules をサポートしないブラウザ向けのフォールバックスクリプトを提供できます。モダンブラウザでは無視され、古いブラウザでのみ実行されます。
基本的な使い方
<!-- モダンブラウザ用(ES Modules 対応) -->
<script type="module" src="app.modern.js"></script>
<!-- 古いブラウザ用(ES Modules 非対応) -->
<script nomodule src="app.legacy.js"></script>動作の仕組み
| ブラウザ | type="module" | nomodule |
|---|---|---|
| ES Modules 対応 | 実行する | 無視する |
| ES Modules 非対応 | 無視する | 実行する |
モダンブラウザ(Chrome, Firefox, Safari, Edge)
type="module" のスクリプトを実行し、nomodule は無視する
古いブラウザ(IE11 など)
type="module" は理解できず無視し、nomodule のスクリプトを実行する
なぜフォールバックが必要か
ES Modules を使ったコードには、古いブラウザで動作しない構文が含まれることがあります。
これらをサポートしない IE11 などのために、トランスパイルしたコードを用意する必要があります。
ビルド設定の例
Webpack や Vite などのバンドラーで、モダン版とレガシー版の両方をビルドします。
// webpack.config.js の例
module.exports = [
{
// モダンブラウザ用
entry: './src/index.js',
output: {
filename: 'app.modern.js'
},
target: 'es2020'
},
{
// レガシーブラウザ用
entry: './src/index.js',
output: {
filename: 'app.legacy.js'
},
target: 'es5',
module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}]
}
}
];HTML での実装例
<!DOCTYPE html>
<html>
<head>
<title>Module/NoModule Pattern</title>
</head>
<body>
<div id="app"></div>
<!-- モダンブラウザ用:軽量で高速 -->
<script type="module" src="dist/app.modern.js"></script>
<!-- レガシーブラウザ用:ポリフィル込みで重い -->
<script nomodule src="dist/app.legacy.js"></script>
</body>
</html>利点
バンドルサイズの最適化
モダンブラウザには最新の構文をそのまま配信できるため、不要なトランスパイルやポリフィルを含めずに済みます。
段階的な移行
古いブラウザのサポートを維持しながら、モダンな開発を続けられます。
Safari 10 の問題
Safari 10 には、nomodule を正しく無視しないバグがあります。
<!-- Safari 10 向けの修正 -->
<script>
// Safari 10 は nomodule を理解するが、スクリプトを実行してしまう
// この修正コードで対処
(function() {
var check = document.createElement('script');
if (!('noModule' in check) && 'onbeforeload' in check) {
var support = false;
document.addEventListener('beforeload', function(e) {
if (e.target === check) {
support = true;
} else if (!e.target.hasAttribute('nomodule') || !support) {
return;
}
e.preventDefault();
}, true);
check.type = 'module';
check.src = '.';
document.head.appendChild(check);
check.remove();
}
}());
</script>現在の状況
2024年現在、IE11 のサポートを終了するプロジェクトが増えています。ターゲットブラウザによっては、nomodule フォールバックは不要かもしれません。
プロジェクトの要件に応じて、フォールバックの必要性を検討してください。