2017-06-23

Browserify x Babelでproductionコードを作るために分かっていなかったこと

ようやく本格的に Node.js + ES2015 ベースで JS がそこそこ快適に書けるようになってきました。

が、FAQ はちゃんと読もう!

babel/babelify: Browserify transform for Babel

思いっきり

Why aren't files in node_modules being transformed?

This is the default browserify behavior.

って書いてある!

結論

  • browserify transform は指定した順番に適用されるので、babelify と組み合わせている場合、まず babelify を通さないと例えば import などでいきなりコケる
  • brfs は babel と相性がよくないので brfs-babel を使う
  • とにかく browserify -g babelify -t babelify しろ

前提

Node.js でテストコードを書き、テストを高速に回すために適宜 Sinon などで stub を使う比較的モダンな開発が分かっていることとする。

課題

  • 依存する npm package のコードをすべて把握するのはなかなか難しい
  • 普段のテストは Node.js で動かすが production コードのターゲット環境が Node.js でない(例えばブラウザ)場合は、当たり前だが最終的にターゲット上でどう動くかは完全には分からない

対策

ブラウザなど Browserify を使うことで Node.js で開発したコードをターゲット上で動かすことができる場合、

  • browserify -g babelify -t babelify を指定することで依存パッケージまるごと Babel を通すことができる。これだけでも依存パッケージの組み合わせで悩むことはだいぶ減るはず(-g は global transform の意味)
  • eslint を使う
    • ブラウザなら eslint-plugin-compat を、Google Apps Script (で DI しないなら)eslint-plugin-googleappsscript 辺りを追加

辺りが有効な対策になりそう。

実際に困ったこと

Browserify は基本的には Node.js, CommonJS の世界のライブラリをブラウザの世界に連れてくることが仕事である。ただし、エンドポイントとなるコードから呼び出されているコードすべてに対してあらゆる transform を適用することはデフォルトの動作となっていない。確かに、IO にタッチせずロジックや加工を担う、Node.js で通常通り動くライブラリがすでにあって、これをブラウザの世界に連れてくる、というだけなら require の部分さえ解決すればだいたいはうまくいく。現実的な選択と言ってよいだろう。

これは言い換えると

  • require 対象が ES2015
  • ターゲット環境が ES5

な組み合わせで、browserify -t babelify を利用して ES5 ready なコードを生成したい場合、デフォルトでは build 済みのコードはすべてが ES 5 ready になるわけではない。

自分で書いている ES2015 なメインのコードは ES5 ready になってくれるだろう。ただし、require 先の ES2015 ready なコードは、 require の部分が解決されただけで bundle され、結果として ES2015 ready なコードが混ざったものができあがってしまう。

これを ES2015 ready な環境(例えば Node.js や最新のブラウザ)でテストしても問題は発見できない。あくまで ES 5 な環境でテストする必要がある。

とは言え、必ず ES5 環境で動かしてテストしなければいけないとなるとテストの実行コストが大きくなってしまう。ということで現実的な選択肢としては eslint で正しく ES5 互換のコードが生成されたかどうかを確認する、という形でだいぶマシになるだろう。

参考

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm