browserify(coffeeify)からUglifyJS2を経由してbundle.min.js.mapを作るレシピ


bowerでリリースする場合.js, .min.js, .min.js.mapの3種類をアップロードする形式を時々見ますが、browserifyしたコードを圧縮、かつソースマップ付きでリリースする方法が中々見つからなかったので、以下、解決方法です。

.
├── bundle.js
├── bundle.js.map
├── bundle.min.js
├── bundle.min.js.map
└── index.coffee

手順としては

  • browserify--debugオプションでインラインソースマップを生成
  • bundle.js.map < exorcistで生成したインラインソースマップをファイルに変換
  • bundle.js < 普通にbrowserifyする
  • bundle.min.js < uglifyjsbundle.jsを圧縮。そのさい、--in-source-mapオプションでbundle.js.mapを食わす
  • bundle.min.js.map < ソースマップの再出力先を--source-mapで定義

動作確認方法

{
  "name": "uglify-with-map",
  "scripts": {
    "start": "browserify index.coffee --transform coffeeify --debug | exorcist bundle.js.map -b . > bundle.js",
    "poststart": "uglifyjs bundle.js --in-source-map bundle.js.map --mangle --compress --output bundle.min.js --source-map bundle.min.js.map"
  },
  "dependencies": {
    "browserify": "^11.1.0",
    "coffeeify": "^1.1.0",
    "exorcist": "^0.4.0",
    "uglify-js": "^2.4.24"
  }
}

以下のようにコマンドを実効するだけです。

echo 'this is coffee script' > index.coffee
tree .
# .
# ├── index.coffee
# └── package.json

npm install
# ...
npm start
# browserify index.coffee --transform coffeeify --debug | exorcist bundle.js.map -b . > bundle.js
# uglifyjs bundle.js --in-source-map bundle.js.map --mangle --compress --output bundle.min.js --source-map bundle.min.js.map

tree . -L 1
# .
# ├── bundle.js
# ├── bundle.js.map
# ├── bundle.min.js
# ├── bundle.min.js.map
# ├── index.coffee
# ├── node_modules
# └── package.json

生成したbundle.min.jsを適当にindex.htmlで読み込むと

index.html
<script src="bundle.min.js"></script>

上記のように、コンパイル元の行数が表示されて、ソースマップが移植できたことが確認できます。

npm installしたbrowserifyなどのコマンドは、npm scripts経由でないと動作しないことに注意してください。

プログラム経由でやる場合

上記コマンドと同等の処理をプログラムで行う場合は、下記のようになります。

tree . -L 1
# .
# ├── index.coffee
# ├── node_modules
# ├── package.json
# └── task.js

node task.js
task.js
// Dependencies
var browserify= require('browserify');
var exorcist= require('exorcist');
var uglifyjs= require('uglify-js');

var fs= require('fs');

// Environment
var bundle= {
  js: 'bundle.js',
  min: 'bundle.min.js',
};

// Main
browserify('index.coffee',{
  transform: 'coffeeify',
  debug: true,
})
.bundle()
.pipe(exorcist(bundle.js+'.map',null,null,'.'))
.pipe(fs.createWriteStream(bundle.js),'utf8')
.on('close',function(){
  var minified= uglifyjs.minify(bundle.js,{
    mangle: true,
    inSourceMap: bundle.js+'.map',
    outSourceMap: bundle.min+'.map',
  });

  fs.writeFileSync(bundle.min,minified.code);
  fs.writeFileSync(bundle.min+'.map',minified.map);
})

参考: The simple way - mishoo/UglifyJS2(github)