ESModules について


予習のために調べたことをまとめました。
勘違いや誤りがあるかもしれませんので、修正・指摘歓迎いたします

ESModules とは

  • JavaScript から別の JavaScript を読み込む為の仕組み
  • いままで CommonJS で実現していたことをJSの標準仕様にしたという理解
  • 仕様を決めるのに苦労した様子
    • ESModules と CommonJS の相互運用問題
    • ESModules の判定方法をどうするか問題
  • まだ production 環境などに採用するのは時期尚早かも?

対応状況

  • Node.js は v8.5 から実験的に対応されている
    • --experimental-modules フラグを付与する
  • 主要ブラウザは概ね対応済み

利用例

Browser

<script type="module" src="index.mjs">
  • type="module" を指定する
  • 認証も必要なら crossorigin="use-credentials" を付与

Node

node --experimental-modules index.mjs
  • 拡張子を .mjs にする
  • --experimental-modules フラグを付与する

実装例

import hello from './hello'

export default () => {
  hello('world')
}
  • ファイルの拡張子は .mjs
  • import の際に .mjs は省略して良い (.mjs -> .js の順で探索される為)
  • 既に ES2015 (with Babel) で実装しているなら慣れ親しんでいるかも

require はできない

const hoge = require('./hoge')
  • CommonJSとは記法が異なる

named import はできない

import { piyo } from './hoge'
  • Babel だとトランスパイルできてしまうので注意
import hoge from './hoge'
const { piyo } = hoge
  • これなら書ける

使えなくなるグローバル変数がある

  • __filename
  • __dirname
  • require
  • module
  • exports
  • arguments

Tips

__dirname を代替する

const __dirname = path.dirname(new URL(import.meta.url).pathname)

エディタで import.meta が syntax error になる場合

何が嬉しいのか

  • webpack などでバンドルしなくていい(遠い将来に)
  • babel などでトランスパイルしなくていい(遠い将来に)
  • HTTP/2 で各モジュールを並列配信できれば速くできるかも?

参考