先日、npmからconst
など一部ブラウザが対応してないコードが入ってしまってハマったが、逆にpublishする側になったら以外と「これどうしようか?」と思って調べた。
目的
- npmにpublishするためのビルドがしたい
- なるべく簡易に、ミニマムに。
- うっかりbrowser対応されてないようなコードで利用者が不幸になるのなるべく防止したい。ぐらいな心持ち
- 「えっbabel-cilって同名ファイル吐き出してるだけじゃん。これ何に使うの」という疑問の解消
目的外のこと
- 積極的にbabelっていく話
-
.babelrc
次第でどんどん使えますが、そこ自体は目的にしてません。お好みで。
-
- node.js向けオンリーのnpmパッケージの事
- 用途次第で、ブラウザが対象外なものなら、複雑化させずにそのままpublishしていいんじゃないか派です。
- module 解決したり結果bundleしたりminifyしたりする話
- しません。browserify、webpack、rollupらへん使いましょう
- umdなども吐く話
- しません。browserify、webpack、rollupらへん使いましょう
- なんとなく著名パッケージ眺めると良いかもしれません(後述)
方法:babel-cliを使う
babel-cliはそもそも何をしてくれるのか?
単純にbabel
というコマンドで、引数として与えられたディレクトリのファイルを変換する。
単体で使った場合には、純粋にコードの静的変換だけをしている。
当然、Webpackやbrowserifyを使った時のように、require
やimport/export
の解決をしたりはしない。
% npm run build
> sample@0.0.1 build /path/to/project
> babel src --out-dir lib
src/index.js -> lib/index.js
src/some-module.js -> lib/some-module.js
通常のWeb開発だとbrowserify
やwebpack
と組み合わせてbundleするので、あんまり使い所ないのでは?と思っていたが、npmにpublishするときは逆にbundleせずにバラバラに変換するだけ、というのが都合が良い。
Setup
babel-cli
とbabel-preset-es2015
入れておく
$ npm i -D babel-cli babel-preset-es2015
お好みでrimraf
。ビルド前にディレクトリクリーンしておくのに便利
$ npm i -D rimraf
ディレクトリ構成
だいたいこんな感じ。
├── src // ビルド前のファイル
│ ├── some-module.js
│ └── index.js
├── test // テスト
├── lib // ビルド後ファイル。
│ ├── some-module.js
│ └── index.js
├── README.md
└── package.json
package.json
babel-cli
をディレクトリごとlib/
に出力して、公開対象をlib/
にする。
package.jsonはこんな感じになる。
{
:
"main": "lib/index.js", // 重要
"scripts": {
"prebuild": "rimraf lib",
"build": "babel src --out-dir lib", // 重要
"preversion": "npm run build",
:
:
},
"files": [
"lib" // 重要
],
"devDependencies": {
:
"babel-cli": "^6.14.0",
"babel-preset-es2015": "^6.14.0",
"rimraf": "^2.5.4"
:
}
}
-
main
フィールドはlib/main
- 同様、
file
には["lib"]
と指定。 -
npm run build
でbabel src --out-dir lib
で src -> lib と吐き出す。 - 他のscriptsは単なる便利化。
-
pre
,post
をつけておけば自動的にビルド実行してくれる。npm version
、npm publish
時に漏れないようにbuildしておく。 -
prebuild
でrimraf
を使ってディレクトリクリーンしておく。
-
もしsrc
でimport/export
を利用して、Webpack 2系やrollupのtree shakingを使いたいと思っているのであれば、下記を記載しておいても良い。
{
:
"main": "lib/index.js",
"module": "src/index.js", // for webpack 2
"jsnext:main": "src/index.js", // for rollup
:
}
Tree shakingについて詳しく知りたい場合は下記あたりが詳しめなので参照のこと。
- http://qiita.com/cognitom/items/e3ac0da00241f427dad6#tree-shaking
- http://chuckwebtips.hatenablog.com/entry/2016/01/26/020235
.gitignore
生成ターゲットは基本ignoreしといていいはず。
lib/
.babelrc
あんまり特殊な事は無いが、最低限これ入れておけば大丈夫だろう、ぐらいなチョイスとしてpreset-es2015
を入れた。1
loose
オプションをtrue
にすべきかなど悩ましいが、reduxあたりを参考にtrue
にした。
{
"presets": [
["es2015", { "loose": true }]
]
}
欄外メモ:.babelrcのenvとBABEL_ENV
reduxのbabelrcを覗くと、env
というオプションが設定されている。
{
"plugins": [
:
:
],
"env": {
"commonjs": {
"plugins": [
["transform-es2015-modules-commonjs", { "loose": true }]
]
}
}
}
これは特定の場合だけに特定のpresetオプションを効かせたい場合に使えるらしい。
$ BABEL_ENV=commonjs babel src --out-dir lib
とすると、env.commonjs
に記載したpresetを追加で効かせる、という効果。
普通そんなに使わなそうだなと思ったが、bablejs.ioによると、このような特定bundle向けの他に、「developmentの時だけ特定のpluginを効かせたい」というようなことも利用想定としているようだ。
まとめ
参考にした package.json
npm向けはbabel-cliにしてるパッケージ
今回取った手法 + webpack的な感じ。
webpack併用しているのが多いが、npm用というよりumd配布など向けっぽい
Grunt使ってビルド
rollup派
思ったよりパラパラ見てたらrollup派がいた。
雑感
- babel-cli今までデバッグ用ぐらいにしか使えない子だと思っててごめんなさい
- webpackとかbrowserifyナシで全然いけるのはだいぶ楽
- umdとか結構配布しているけど、需要どれだけあるんだろう?と思った。
-
preset-latest
でも良いかなとも思っているが、まだちゃんと調べられてないので保留した。 ↩