前回(htmlwidgetsでD3.jsを使おうとしたら文字コードの闇に飲まれかけた話 - Technically, technophobic.)、
Rのパッケージビルド時にGulpでconcat+uglifyしてminifyされたJSとCSSを自動生成する方法を無駄に模索中です。
という次回予告をしましたが、その話です。
モチベーション
https://github.com/ramnathv/htmlwidgets/issues/56
での議論は、パッケージが提供しているminify済みのファイルを使おう、という流れです。
Bowerはbower.jsonの"ignore"
に書いてあるファイル以外すべてのファイルを対象のレポジトリからダウンロードします。.min.js
はたいがいのライブラリで提供されているので、たいがい使うことができます。でも、"main"
フィールドに書いてあるのはminifyされていないファイルなので、bower list --path
みたいなコマンドでminifyされたファイルの一覧を得ることはできません。
そもそもそういうふうになっているのはなぜなんでしょう。--minified
みたいなオプションをつくりましょう、という提案にこんなレスポンスがついています。
This is a job for your build system, not a package manager.
(https://github.com/bower/bower/issues/368)
ははあ。ご自分でminifyなさってください、と。なるほど。
やりましょうじゃないですか。
Gulpを使ってみる
gulp.js - the streaming build system
GruntじゃなくてGulpを使うとかっこいいいらしいので使ってみます。
Gulpとは
Javascriptのビルドシステムらしいです。よく知りません。
npm install -g gulp
とかでインストールできます。
Gulpを動かす
よくはわかりませんがgulpfile.jsという名前のファイルを置いて
gulp
ってやると動くらしいです。
使ったGulpのプラグイン
main-bower-files
: 必要なJavascript/CSSのファイルの一覧を取得します(bower.json
のmain
に書いてあるファイル)gulp-filter
: 正規表現とかでフィルターをかけますgulp-concat
: ファイルをひとつに結合しますgulp-uglify
: Javascriptをminifyします(gulp-uglifyjs
っていうのもあったんですけどどっちがいいのかよく分かりませんでした)gulp-uglifycss
: CSSをminifyします
gulpfile.js
Gulp file to compile JS/CSS for htmlwidgets
結果
まあめでたく動いてminifyされたファイルができます。これをいい感じにパッケージのYAMLに書けばぶじ動きます。
でもこれ、
毎回手で打つのめんどくさくない?
Makevarsを使ってみる
そこでMakevarsの出番です。Makevarsは、Makefileの一種で、src/Makevars
というファイルが置いてあればパッケージインストール時にそれに従ってビルドが走ります。
参考:Writing R Extensions: 1.2.1 Using Makevars
Makevarsの書き方
このあたりが参考になります。
Makevars
こんな感じです。相対パスを書く時は、src
が基準になるので、inst
に入れたいときは../inst
と書きます。
PACKAGE := metricsgraphics TARGETDIR := ../inst/htmlwidgets LIBDIR := $(TARGETDIR)/lib/$(PACKAGE)/ JSFILES := \ htmlwidgets/$(PACKAGE).js \ htmlwidgets/lib/jquery/dist/jquery.js \ htmlwidgets/lib/d3/d3.min.js \ htmlwidgets/lib/metrics-graphics/dist/$(PACKAGE).js CSSFILES := \ htmlwidgets/lib/metrics-graphics/dist/$(PACKAGE).css YAMLFILE := htmlwidgets/$(PACKAGE).yaml.tpl all: $(LIBDIR) $(LIBDIR)/$(PACKAGE).js $(LIBDIR)/$(PACKAGE).css $(TARGETDIR)/$(PACKAGE).yaml .PHONY: clean all $(LIBDIR): mkdir -p $(LIBDIR) $(LIBDIR)/$(PACKAGE).js: $(JSFILES) @rm -f $@ cat $^ | uglifyjs > $@ $(LIBDIR)/$(PACKAGE).css: $(CSSFILES) @rm -f $@ cat $^ | uglifycss > $@ $(TARGETDIR)/$(PACKAGE).yaml: $(YAMLFILE) sed 's/PACKAGE/$(PACKAGE)/' $< > $@ clean: @rm -rf -- $(TARGETDIR)
結果
これがMakefile使ったブランチです。
yutannihilation/metricsgraphics at use-makefile · GitHub
devtools::install_github("yutannihilation/metricsgraphics@use-makefile")
とかするとインストールできます。まあとりあえず動きました。knitしようとするとエラーが出るけど、そこは配置の問題なので調べれば何とかなるはず。
でもこれ、
- uglifyとかuglifycssがインストールされてるかチェックして、されてる場合とされてない場合で場合分けして、とかめんどくさくない?(uglify使えないとD3.jsが動かないので、そもそもの問題の解決になっていない)
- 実はあんまりファイルサイズ変わらなくない?(手元で試すと、1.3MBだったのが1MBになる程度だった。たぶん容量のほとんどはデータ)
- デバッグしづらくない?
...
うーん。たしかに。。
感想
労力の割にあんまメリットないっすね。疲れました...。
飽きたので大人しくbowerがダウンロードしてくるminify済みのファイルを使います。