Help us understand the problem. What is going on with this article?

npm とか bower とか一体何なんだよ!Javascript 界隈の文脈を理解しよう

More than 3 years have passed since last update.

背景

Javascript で Web アプリを作ろうとすると、よくわからないことだらけで超混乱します。

  • npm と bower の違いは?
    • npm はサーバーサイド用、bower はクライアントサイド用らしいよ
    • えっ、でもなんで bower のインストールに npm が必要なの?
      • サーバーサイドは Rails で書きたいから npm 要らないと思うんだけど・・・
  • ていうかサーバーサイドJSとか node.js って何?
  • よく見る browserify って何?

こういった疑問が沸き上がるのは、各ツールが生まれた文脈がよくわかっていないからです。いろいろ調べてやっとちょっとわかってきたのでメモします。間違いがあったらご指摘ください。

「CommonJS」誕生 - Javascript は汎用プログラミング言語へ

その昔、Javascript 大好きおじさんは言いました。

Javascript 最高!ブラウザで使うだけではもったいない!汎用言語にしよう!

しかし、そうは言っても Javascript には足りないものがたくさんありました。その最たるものがモジュール機能です。C言語なら #include、ruby なら require、golang なら import。どんな言語でも用意されている、他のファイルを読み込んで使えるようにする機能が、なんと Javascript には用意されていませんでした。

そこで2009年ごろ、まったく新しい汎用言語としての Javascript の仕様を策定する動きが発足しました。こうして生まれたのが CommonJS です。

CommonJS はあくまで仕様であり、CommonJS というライブラリが存在するわけではありません。Common Lisp みたいなものです。CommonJS の仕様に則って実装された処理系のひとつが、かの有名な node.js です。Common Lisp に対する CLisp みたいなものです。こうして Javascript は、めでたく ruby のような汎用スクリプト言語の仲間入りを果たしました。実際、node.js は ruby と同じように node コマンドでスクリプトを実行できます。

$ node helloworld.js

追記(2015/10/01)

現在 node.js は独自の進化を遂げ、もはや CommonJS に準拠していません(参考1)(参考2)。node.js のことは「CommonJS みたいなやつ」だと思っておいてください。

CommonJS 界のパッケージ管理ツール「npm」誕生

実のところ、CommonJS の仕様策定はまだ全然終わっていません。それでも前述のモジュール機能はすぐに策定されたようで、もう使うことができます。そうなれば必然的に生まれてくるのが、gem や pip のようなパッケージ管理ツールです。

node.js の世界では、npm というパッケージ管理ツールを使います。npm のリポジトリに、node.js という言語で書かれた便利ツール達がどんどん追加されていきます。ここで、node.js はもはやブラウザという檻から外れた汎用言語なので、作られるツールも「コマンドラインで使って開発を楽にするツール」という趣が強いです。例えば、

  • http-server : 簡易webサーバー。
  • grunt : タスクランナー。
  • bower : パッケージ管理ツール。

ん?

ブラウザ用JS のためのパッケージ管理ツール「bower」

いま名前のあがった bower は、node.js ではなく、ブラウザで動く昔ながらの Javascript のためのパッケージ管理ツールです。パッケージの例としては、

  • JQuery
  • AngularJS
  • パララックス(かっこいいスクロール)を実装できる君

など。昔ながらの Javascript といえどもパッケージに依存性はあるし、インストールも簡単になるので、パッケージ管理ツールが存在することによるメリットは十分にあるのです。

そして、bower 自体は node.js で実装されています。これが、bower を使うために npm をインストールしないといけなかった理由です。実際のサーバーサイドの開発に ruby を使おうが php を使おうが、bower という node.js で書かれたプログラムを実行するために、node.js という処理系が必要なのです。

なおややこしいことに、AngularJS など一部のメジャーなパッケージは(たとえそれがブラウザ上で動くライブラリであろうと)bower でも npm でも配布されています。2014年の11月に、npm のブログ上で「npm が統一リポジトリになりますよ」宣言が公開されたそうですが、あんまりちゃんと片付いてはいないようです。

「Browserify」誕生 - 天界と地上を繋ぐ魔法

繰り返しになりますが、node.js はブラウザという枠を外れて独自に進化した言語です。逆に言うと、node.js として書かれた Javascript はそのままではブラウザで動きません。ところが、node.js の持つモジュール機能や npm 上にある無数の便利ツールにすっかり慣れてしまった node.jser 達は、もはや素の Javascript には戻れない体になってしまいました。

そこで生み出されたのが browserify です。browserify を使うと、まるでC言語を機械語にコンパイルするように、node.js スタイルで書かれたコードをブラウザ上で動くものに変換 することができます。普段は node.js スタイルの高級言語を使ってコーディングして、作業の最後にブラウザで動く低級言語に変換すればよいのです。

実践

実践で復習しましょう。上記のことがらを踏まえて、

  • node.js のインストール
  • npm で browserify をインストール
  • CommonJS スタイルでコーディング
  • browserify でブラウザ向けにビルドして表示

をやってみます。今度こそ理解できるはず!

node.js のインストール

やり方はいろいろあると思いますが、Mac なら homebrew を使うのが簡単です。処理系をインストールするわけですから、homebrew を使うのは自然なことです。

$ brew install node.js

npm で browserify をインストール

node.js をインストールすると、もう npm も使えるようになっています。最初に初期設定を行います。

$ mkdir npm_test
$ cd npm_test
$ npm init

(いろいろ聞かれるけど全部エンターで OK)

終わったら browserify をインストールしてみましょう。

npm install -g browserify

ここで、-g オプションはパッケージのグローバルインストールを意味します。browserify はいつでも使う便利ツールなのでシステム全体にインストールします。開発中のプロジェクト固有のパッケージをインストールするときは、-g オプションを外せば、プロジェクトフォルダの node_module フォルダ配下にダウンロードされます。

browserify という node.js 製の便利ツールをインストールするので、npm を使いました。これも自然に理解できると思います。

CommonJS スタイルでコーディング

npm_test 配下に src フォルダを作って、こんなコードを準備してみます。

src/add.js
// たし算モジュールを定義
module.exports = function (a, b) {
  return a + b;
};
src/main.js
// たし算モジュールを読み込み
var add = require('./add');

var txt = document.createTextNode(add(114, 514));
document.body.appendChild(txt);

モジュールの定義と読み込みをやっているあたりに CommonJS を感じましょう。このままではブラウザで実行できません。

あわせて、表示用の html を準備します。

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>test</title>
    </head>
    <body>
        <script src="dest/build.js"></script>
    </body>
</html>

最後に、browserify でビルドした JS を出力するフォルダだけ作っておきましょう。

$ mkdir dest

現在のファイル構成はこんな感じです。

npm_test
├── dest
├── index.html
├── package.json
└── src
    ├── add.js
    └── main.js

browserify でブラウザ向けにビルドして表示

いよいよビルドしましょう。

$ browserify src/main.js -o dest/build.js

上記を実行すると、dest フォルダに build.js が生成されます。

dest/build.js
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = function (a, b) {
  return a + b;
};

},{}],2:[function(require,module,exports){
var add = require('./add');

var txt = document.createTextNode(add(114, 514));
document.body.appendChild(txt);

},{"./add":1}]},{},[2]);

元コードで書いた require が解決されて、禍々しいコードが吐き出されています。index.html を開けば、めでたく足し算の結果が表示されているはずです。

おわりに

ここまで読んで、冒頭に書いた疑問に答えられるようになっていれば幸いです。

  • npm と bower の違いは?
    • npm はサーバーサイド用、bower はクライアントサイド用らしいよ
    • えっ、でもなんで bower のインストールに npm が必要なの?
      • サーバーサイドは Rails で書きたいから npm 要らないと思うんだけど・・・
  • ていうかサーバーサイドJSとか node.js って何?
  • よく見る browserify って何?

その他

browserify を毎回実行するのがめんどくさい件について

gulp でできるらしいです。gulp とか grunt とか一体何なんだよ!

browserify の -t オプションについて

場合によっては、CommonJS → ふつうのJS 以外にも変換が必要なことがあります。例えば CoffeeScript の変換など。これらに関しても一気通貫で変換できるよう、browserify には transform module なるプラグインが存在します。あらかじめインストールのうえ、-t オプションで指定すると一緒に変換してくれるようです。

$ npm install reactify
$ browserify -t reactify src/aaa.jsx > dest/aaa.js

結局 bower を使ってない件について

bower でインストールしたパッケージは components/ フォルダの中にどんどん入っていくのですが、これをどうやってロードしたらいいのかわからなかったのでやめました。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away