Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CJSとESMとnpmパッケージ / CommonJS and ES Modules and ...

CJSとESMとnpmパッケージ / CommonJS and ES Modules and npm package

Node学園 31時限目の発表資料です
https://nodejs.connpass.com/event/90936/

shimataro

June 29, 2018
Tweet

More Decks by shimataro

Other Decks in Technology

Transcript

  1. 背景 背景 JavaScript(ECMAScript)のモジュール require() / module.exports (CommonJS; CJS) import /

    export (ES Modules; ESM) ネイティブESMはあまり使われていない (BabelでCJSに変 換するのが一般的) でもきっとそのうち普及する
  2. 今回のゴール 今回のゴール CJS / ESM / Babelの どれからでも使える パッケージモジ ュールを作りたい

    ↓ // パッケージ "foo" export default foo; export {bar}; // CJS const {default: foo, bar} = require("foo"); // ESM / Babel import foo, {bar} from "foo";
  3. 今回のゴール 今回のゴール パッケージの条件 ソースコードは単一 ビルド時に複数ファイルの生成はOK default export / named exports

    両方対応 ソースコード内に変なハックは入れない おまじない NG 古い文法 NG 作る側にも使う側にも、極力負担をかけない
  4. CJSとESM CJSとESM 拡張子 .mjs はESM それ以外の拡張子はCJS export default foo; export

    {bar}; module.exports = foo; // または exports.default = foo; exports.bar = bar;
  5. パッケージの構成 パッケージの構成 package.json 内の main を 拡張子なし で指定 2種類のindexを用意 ./index.js

    (CJS/Babel用) ./index.mjs (ESM用) http://yosuke- furukawa.hatenablog.com/entry/2016/05/10/111102 { ... "main": "./index", // ".js" はつけない ... }
  6. コード生成 - CJS コード生成 - CJS index.js は普通にBabelで変換すればOK ↓ export

    default foo; export {bar}; exports.default = foo; exports.bar = bar;
  7. コード生成 - ESM コード生成 - ESM index.mjs は何もしなくてOK? Nodeがサポートしている文法だけを使うならOK デコレータとかstatic

    propertiesとか使えない 汎用 パッケージなら、ある程度古いバージョンもサポー トしたい せめてLTSくらいは… そのために 古い文法 を使うのは嫌だ というわけで、 やっぱりBabelは使いたい
  8. コード生成 - ESM コード生成 - ESM Babel使用時の注意 その1 babel-preset-env のデフォルトはCJS形式

    import / export構文を変換しない場合はこうする // .babelrc { "presets": [ ["env", {"modules": false}] ] }
  9. コード生成 - ESM コード生成 - ESM Babel使用時の注意 その2 拡張子が自動的に .js

    になる ESMでは .mjs じゃないとダメ Babel7に --keep-file-extension が登場 拡張子を変更しないオプション 変換元の拡張子も .mjs にする必要あり まだbeta段階
  10. 実際に作ってみた 実際に作ってみた ESM(.mjs) / Babel CJS https://github.com/shimataro/hell-word npm install @shimataro/hell-word

    import foo, {bar} from "@shimataro/hell-word"; foo(); // "hell, word" bar(); // "地獄の言葉" const {default: foo, bar} = require("@shimataro/hell-word"); foo(); // "hell, word" bar(); // "地獄の言葉"
  11. まとめ まとめ 単一ソースからCJS/ESM/Babel対応のパッケージを作 る方法 まずESMの export 構文で作る CJS用は exports.default に変換→

    .js ESM用はそのまま→ .mjs package.json の "main" に拡張子をつけない サンプル作ってみたからよかったら参考にしてね 関西Node学園もよろしく! 手品に興味があったら声をかけてね!