$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

JSをbrowserifyでビルドし、ライセンスコメントを適切に残す

最近JSを利用するときは、依存モジュールはnpmを利用し、ES6やTypeScriptの仕様を開発には使った上で、ブラウザ用にコンパイルして配信するようになってきている。また同時にネットワークの負荷を下げるためにminifyを行う場合もある。

minifyはライセンスが絡むと少し難しい。例えばコメントを全て削除してしまうとライセンスコメントまで消えてしまう。この問題にはみんながそれぞれの手法で対処しているみたい。1年ほど前の記事でクライアントサイドJavaScriptのライセンス管理 | エンジニアブログ | GREE Engineering というものがあり、いろんなJSのコンパイルのためのライブラリが独自でライセンスの形式を決めていて、それにマッチしないものは消えてしまう、みたいな辛いことが起きてそうだった。

そこで今回は自分の勉強も兼ねて、npmのモジュールを含めてブラウザ用にコンパイルし、ライセンスコメントも残すための最小のコンパイル環境を作ってみる。

やりたいこと

npmでインストールしたモジュールを使い、ブラウザで動かすようのJSを書き、それをコンパイルしてminifyする。この時に依存モジュールのライセンスコメントを出力する。

利用する技術

依存モジュールをインストールする

プロジェクトのrootでnpm initして適切にpackage.jsonの設定をしたあと、必要なモジュールを入れていく。

# ビルド用
npm install gulp --save-dev
npm install browserify --save-dev
npm install gulp-uglify --save-dev
npm install vinyl-source-stream --save-dev
npm install vinyl-buffer --save-dev
npm install licensify --save-dev

# ブラウザのJSで利用したいもの
npm install jquery --save-dev
npm install lodash --save-dev

JSを用意する

jqueryとlodashを利用するJSを用意する。今回はとりあえずcommonjs形式でrequireしているだけ。

src/js/app.js

var $ = require('jquery');
var _ = require('lodash');

gulpでライセンスを残しながらJSをビルドする環境を作る

以下の様なgulpfile.jsを用意することで、先ほど書いたやりたいことを実現できるbuild-jsタスクを用意できる。

gulpfile.js

var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');

gulp.task('build-js', function () {
    return browserify({
        entries: './src/js/app.js' // どのファイルからビルドするか
    }).plugin('licensify') // licensifyプラグインの有効化
        .bundle() // browserifyの実行
        .pipe(source('app.js'))
        .pipe(buffer())
        .pipe(uglify({
            preserveComments: 'license' // ライセンスコメントを残しつつminify
        }))
        .pipe(gulp.dest('./static/js')); // 出力
});

これを実行することで、src/js/app.jsのファイルがビルドされて最終的にminifyされたJSがstatic/js/app.jsに出力される。

もう少し詳しく解説する。

licensifyプラグインを通しbrowserifyする

ライセンスコメントを確実に残すためにlicensify を利用する。browserifyのAPIでファイルを指定し、pluginメソッドでlicensifyを指定することで、licensifyプラグインを有効にした状態でJSをビルドすることが出来る。

browserifyをつかった後にvinyl-source-streamを使ったり、vinyl-bufferを使ったりしているのは、gulp と browserify と vinyl の話 - <body>gulpとBrowserifyでJSをビルドしてみた - Qiita を参考に。

ライセンスコメントを残す設定でuglifyする

gulp-uglifyのpreserveCommentsにlicenseを指定することでlicenseが記述されたコメントを残すことが出来る。

そもそもlicensifyを使わずにこのオプションを使えばライセンスコメントを残せると思っていたのだが、以下の二つの理由によりlicensifyを通したほうが確実と判断した。

  • 全ての形式のライセンスコメントに対応しているかわからない
  • いろいろ試してみたところなぜか出力されないライセンスコメントがあった
    • それがuglifyの奥底で起こってそうでデバッグにかなり時間が取られそうだったので諦めた

実際に実行してみる

以下のコマンドでビルドが行える。./node_moduels/.bin/gulpを利用しているのはグローバルなgulpコマンドを利用したくないため。

./node_modules/.bin/gulp build-js

するとstatic/js/app.jsにしたのように出力されるのでうまく行っていることが分かる。

/**
 * Modules in this bundle
 * @license
 * 
 * jquery:
 *   licenses: MIT
 *   author: jQuery Foundation and other contributors
 *   maintainers: dmethvin <dave.methvin@gmail.com>, scott.gonzalez <scott.gonzalez@gmail.com>, m_gol <m.goleb@gmail.com>, timmywil <timmywillisn@gmail.com>
 *   homepage: http://jquery.com
 *   version: 2.1.4
 * 
 * lodash:
 *   license: MIT
 *   author: John-David Dalton <john.david.dalton@gmail.com>
 *   maintainers: jdalton <john.david.dalton@gmail.com>, mathias <mathias@qiwi.be>, phated <blaine@iceddev.com>, kitcambridge <github@kitcambridge.be>, d10 <demoneaux@gmail.com>
 *   contributors: John-David Dalton <john.david.dalton@gmail.com>, Benjamin Tan <demoneaux@gmail.com>, Blaine Bublitz <blaine@iceddev.com>, Kit Cambridge <github@kitcambridge.be>, Mathias Bynens <mathias@qiwi.be>
 *   homepage: https://lodash.com/
 *   version: 3.10.1
 * 
 * This header is generated by licensify (https://github.com/twada/licensify)
 */
!function e(t,n,r){function i(u,a){if(!n[u]){if(!t[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(o)return o(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[u]={exports:{}};t[u][0].call(l.exports,function(e){var n=t[u][1][e];return i(n?n:e)},l,l.exports,e,t,n,r)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;u<r.length;u++)i(r[u]);return i}({1:[function(e,t,n){/*!
 * jQuery JavaScript Library v2.1.4
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-04-28T16:01Z
 */
!function(e,n){"object"==typeof t&&"object"==typeof t.exports?t.exports=e.document?n(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return n(e)}:n(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t="length"in e&&e.length,n=Z.type(e);return"function"===n||Z.isWindow(e)?!1:1===e.no
// 以下ずっとminifyされたjsが続く

まとめ

今回はnpmのモジュールを含めてブラウザ用にコンパイルし、ライセンスコメントも残すための最小のコンパイル環境を作ってみた。最近のJSはいろいろ進歩していて、昔は非常に面倒だったことが簡単に出来るようになって嬉しい。

emacsでweb-modeを利用してHTML + Xslate(TTerse)の環境でsyntax highlightする

仕事でHTMLを書くときは大体HTML + Xslate(TTerse syntax)という構成でやっている。今まではhtml-modeを使っていたのだけど、流石にXslateのsyntaxがハイライトされないのだるくなってきた。そこでweb-modeというのが便利と見たことがあったので入れてみた。

インストールする

package-list-packagesしてweb-modeを入れる。その後以下の様な設定を書く。

(require 'web-mode)
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(setq web-mode-engines-alist
      '(("template-toolkit" . "\\.html?\\'" )))

この設定をしておくだけで、

  • .htmや.htmlという拡張子の時にweb-modeを起動する
  • .htmや.htmlの時、Template::Toolkitの記法にマッチしていれば、ハイライトしてくれる

と出来る。XslateのTTerseはTemplate::Toolkit互換なので、このようにするだけで良い。

使ってみる

例えばはてな教科書のサンプルである https://github.com/hatena/perl-Intern-Bookmark/blob/master/templates/bookmark.html を表示してみる。

f:id:shiba_yu36:20160105222804p:plain

上のようにHTMLのハイライトとXslateのハイライトが同時に行えるようになった。

まとめ

web-modeを導入してみた。まだハイライトがあまり綺麗じゃないのでどこかのタイミングでカラーを調整したい。

2015年振り返り

今年はディレクターからエンジニアに戻ったり、引っ越しなどをして私生活が大きく変わったり、仕事がむちゃくちゃ忙しかったりと、何かと慌ただしい年だった。

ディレクターからエンジニアへ

いろいろあってエンジニアに戻りたいということになったので、仕事はディレクターからエンジニアに戻った。ディレクター時代に自分のエンジニアとしての足りない部分がだいぶ分かってきていたので、今年は足りない部分をなくしていくということをしている。

  • Perl以外の言語を触った経験が少なかったので、ScalaやTypeScriptなどの言語を勉強した
    • 静的型付け言語の基本みたいなのが学べてよかった
  • 流行り技術は無視して、とりあえず基本的な分野について学んだ
    • 文字コードについて学んだり、オブジェクト指向入門読んだり、セキュリティ周りのことを勉強したり
    • けっこう良かったので今後も基本的な分野をちゃんと勉強しつつ、気晴らしに流行りを追っかけるくらいの気持ちでいこうと思う


ディレクターに一回なってからエンジニアに戻ったの非常に良い経験だった。

エンジニアに戻ってチームで仕事をしていると、ディレクターといろいろ意見のすり合わせをする。その時ディレクターがなぜこういうことを言うのか、という背景知識があるので、スムーズに話し合いが進めることができた。

また、今年の最後3か月くらいは、自らもエンジニアをしつつチームのエンジニアをまとめるみたいなポジションにいたけど、この時もディレクター、エンジニア、デザイナの意見の背景がなんとなく見えていたのでやりやすかった。エンジニアの意見はもちろんのこと、一度ディレクターになったことでディレクターの意見もなんとなく分かるようになったし、ディレクターとしてデザイナに接していたことでデザイナーが大事にしていることをなんとなく掴むことができた。

ディレクターになっていろいろ大変だったけど、良い経験ができてよかった。挑戦させてくれてサポートも充実している会社で、一度マネージャーとかやってみない?みたいなことを言われたなら、何も考えず嫌だと思わないで一回考えてみても良さそうと思った。

結婚して引っ越しした

結婚して引っ越した。寮とかで共同生活していたけど、賃貸で二人暮らしみたいなのは初めてでそこは不安だったけど、今のところ一人暮らしより楽しいので良かった。自分の時間みたいなのは減ったけど、減った分だらだらしている時間が減って集中力は上がった気がする。

投資を始めた

なんとなく経済の動きに興味を持っておかないといけないなーと思って投資を始めた。単独の株を買うというのはだるそうだし、時間に見合わなそうなので、インデックス系の投資信託を買うことにした。

基本的に放置戦略で、今年は株価がいろいろ揺れ動いた結果損しているんだけど、まあ何も考えずこのまま続けようと思う。

まとめ

今年は仕事にプライベートに大きい変化があった年だったけど、良い変化だった気がするので来年もこの調子で頑張りたい。

【番外編】今年のブックマーク数ランキング

今年は106記事ブログを書いた。去年や一昨年よりブログの記事数が減ってしまったので来年はもっと書きたい。あと今年はエンジニアリングに関わる記事のブクマ数がしょぼいので、来年はもっとエンジニアリングをやっていって記事を書きまくりたい。

$shibayu36->blog;の2015年ブックマークランキングベスト73(累計3049ブックマーク)

# タイトル
1位 プロジェクトを成功させるために最初におこなっていること - $shibayu36->blog;
2位 学習のため書籍を読むときは明確に目的を決める - $shibayu36->blog;
3位 自分流Elasticsearch入門 - $shibayu36->blog;
4位 Scala入門記 - $shibayu36->blog;
5位 評価制度の目的とは何か考えてみる - $shibayu36->blog;
6位 乱数の性質とセッショントークンの作成 - $shibayu36->blog;
7位 符号化文字集合と文字符号化方式 - 「プログラマのための文字コード技術入門」を読んだ - $shibayu36->blog;
8位 Amazon SESとSNSを利用してバウンスメールを自動的にハンドリングする - $shibayu36->blog;
9位 良いビジョンとは何か - ザ・ビジョンを読んだ - $shibayu36->blog;
10位 「1分間顧客サービス」を読んだ - $shibayu36->blog;
11位 「師弟登壇2015」ではてなの研修について発表しました - $shibayu36->blog;
12位 会社は儲けるためにあるのか - $shibayu36->blog;
13位 暗号技術の要点を学ぶ - 「暗号技術入門」を読んだ - $shibayu36->blog;
14位 第10回elasticsearch勉強会に行ってきました - $shibayu36->blog;
15位 kindle 50%セールで大量購入してしまった - $shibayu36->blog;
16位 「Cartonの内部」について社内勉強会で発表した - $shibayu36->blog;
17位 「体系的に学ぶ安全なWebアプリケーションの作り方」再読した - $shibayu36->blog;
18位 「考えるカラス」が良すぎる - $shibayu36->blog;
19位 「ベストを尽くせ」だけではベストは生まれない - 「マネジメントとは何か」を読んだ - $shibayu36->blog;
20位 git gcの自動実行はいつ行われるのか - $shibayu36->blog;
21位 ScalaのOptionとEitherで例外処理を行う方法 - $shibayu36->blog;
22位 「アドレナリンジャンキー」読んだ - $shibayu36->blog;
23位 Test::Time::AtというCPANモジュールをリリースしました - $shibayu36->blog;
24位 歴史文学「HHhH」 - $shibayu36->blog;
25位 Emacsでscala-mode2とensimeを使ってScala環境を作る - $shibayu36->blog;
26位 Scala入門してる - 演算子編 - $shibayu36->blog;
27位 HTML5 スタンダード・デザインガイド読んだ - $shibayu36->blog;
28位 #yapcasia 2015に参加しました - $shibayu36->blog;
29位 「嫌われる勇気」読んだ - $shibayu36->blog;
30位 gitでpush前のcommitの一覧をリスト記法で取得する - $shibayu36->blog;
31位 Scala入門してる - クラスとオブジェクト編 - $shibayu36->blog;
32位 城崎温泉に旅行に行った - $shibayu36->blog;
33位 Code Completeがお買い得らしい - $shibayu36->blog;
34位 EmacsでTypeScript環境を整える - $shibayu36->blog;
35位 elasticsearchにwikipediaのデータをインデックスする - $shibayu36->blog;
36位 台湾旅行に行った - $shibayu36->blog;
37位 「夕凪の街 桜の国」 - $shibayu36->blog;
38位 長期投資にかなった投資信託の条件を学ぶ - 「投資信託はこの9本から選びなさい」読んだ - $shibayu36->blog;
39位 TheSchwartzが次に実行するjobをどう見つけるか - $shibayu36->blog;
40位 user-emacs-directoryを利用して、特定のディレクトリにemacsの設定を隔離する - $shibayu36->blog;
41位 「高速スケーラブル検索エンジン ElasticSearch Server」読んだ - $shibayu36->blog;
42位 typescript-modeの時に、キー入力で自動でtypescript-insert-and-indentが実行されるのを止める - $shibayu36->blog;
43位 26歳になりました - $shibayu36->blog;
44位 Web API: The Good Parts読んだ - $shibayu36->blog;
45位 「アニメを仕事に!」読んだ - $shibayu36->blog;
46位 Emacsを24.5に上げたらmarkdown-modeのインデントがおかしくなった - $shibayu36->blog;
47位 Scala入門してる - 環境導入編 - $shibayu36->blog;
48位 温泉シバソンやりました - $shibayu36->blog;
49位 Perlで、あるファイルが必要のないモジュールをuseしてないか調べるスクリプト - $shibayu36->blog;
50位 Scalaスケーラブルプログラミングを読んだ - $shibayu36->blog;
51位 「敗者のゲーム」読んだ - $shibayu36->blog;
52位 「だましの手口」読んだ - $shibayu36->blog;
53位 kindleで本がセールっぽいのでいくつかポチった - $shibayu36->blog;
54位 scalaで時間操作メモ - $shibayu36->blog;
55位 git-pr-releaseでリリースPRの変更ファイルの情報を扱えるようになりました - $shibayu36->blog;
56位 「黄金の羽根」を手に入れる自由と奴隷の人生設計読んだ - $shibayu36->blog;
57位 「経済ってそういうことだったのか会議」読んだ - $shibayu36->blog;
58位 scalaでcase classをエイリアスする - $shibayu36->blog;
59位 タスク管理ツールをProducteevからTodoistにした - $shibayu36->blog;
60位 「惡の華」読んだ - $shibayu36->blog;
61位 「超簡単 お金の運用術」読んだ - $shibayu36->blog;
62位 「玩具修理者」読んだ - $shibayu36->blog;
63位 「弱いつながり 検索ワードを探す旅」読んだ - $shibayu36->blog;
64位 税金がタダになるおトクな「NISA」活用入門読んだ - $shibayu36->blog;
65位 3月に読んだ本 - $shibayu36->blog;
66位 鳥取日帰り旅行に行きました - $shibayu36->blog;
67位 「ETF投資入門」読んだ - $shibayu36->blog;
68位 エリックエヴァンズのドメイン駆動設計が実質50%オフだったので即座に買った - $shibayu36->blog;
69位 「北欧フィンランド 食べて旅してお洒落して」を読んだ - $shibayu36->blog;
70位 gitで特定commitの日付を取得する - $shibayu36->blog;
71位 2014秋アニメの感想 - $shibayu36->blog;
72位 「投資信託はこうして買いなさい」を読んだ - $shibayu36->blog;
73位 世界にひとつしかない「黄金の人生設計」読んだ - $shibayu36->blog;

generated by 年間ブックマークランキングジェネレーター