akiyoko blog

akiyoko の IT技術系ブログです

nodebrew で Mac の Node.js 環境をスッキリさせた

1. はじめに

Mac では、Node.js (node) は、Homebrew でインストールするのが一番手っ取り早いようなのですが、私の場合は Titanium Studio をアップデートしたときにインストールされたらしく、当然ながら特定バージョンの切り替えもできず、実行時に Permission Error が頻発したりして、苦労が絶えませんでした。


そこで今回、自身の Mac の Node.js 環境を全面的に見直してみたので、その履歴を残しておこうと思います。


なお、Grunt を使っていると、Node.js のバージョンによってビルドが失敗するということもあったので、Node.js のバージョン切り替えができるように、nodebrew で管理することにしました。


参考




 

2. 環境

Mac の OSバージョンは、

OSX 10.9.5

作業開始前の各種バージョンは、

$ node -v
v0.10.29
$ npm -v
1.4.14

でした。

 

3. やったこと

3.1. Node.js のアンインストール

まず、Node.js と npm をアンインストールします。


npm をアンインストールします。

$ sudo npm uninstall npm -g


Node.js をアンインストールします。

$ lsbom -f -l -s -pf /var/db/receipts/org.nodejs.pkg.bom | while read i; do sudo rm /usr/local/${i}; done
$ sudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.*

参考
http://www.seta-blog.co.jp/mac%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9Fnode-js%E3%82%92%E3%82%A2%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6homebrew/



もし、Homebrew でインストールしていた場合は、こちらでアンインストール。

$ brew uninstall node


アンインストールできたか確認します。

$ node -v
-bash: node: command not found
$ npm -v
-bash: npm: command not found


仕上げに .npm ディレクトリを消しておきました。

$ sudo rm -rf ~/.npm



 

3.2. nodebrew のインストール

コマンド一行でインストールできます。

$ curl -L git.io/nodebrew | perl - setup

~/.bash_profile に以下を追加します。

export PATH=$HOME/.nodebrew/current/bin:$PATH
$ source ~/.bash_profile

 

3.3. Node.js のインストール

nodebrew から Node.js をインストールします。

$ nodebrew ls-remote
$ nodebrew install-binary v0.10.38

### install-binary しただけでは使えません
$ node -v
-bash: node: command not found

$ nodebrew ls
v0.12.4

current: none

$ nodebrew use v0.12.4
use v0.12.4

$ node -v
v0.12.4
$ npm -v
1.4.28


npm のバージョンが低くて npm install が失敗する場合があるので、npm を最新化しておきます。

$ npm install -g npm

$ npm -v
2.11.2


 
最後に、npm install を sudo無しで実行できるようにしておきます。

$ sudo chown -R $(whoami) ~/.npm

$ sudo chown -R $(whoami) /usr/local/lib/node_modules

参考



本題はここまでで完了です。


ここからは、おまけ。



 

4. 実践編

Bower と Grunt を使って、とあるライブラリのビルドをしてみます。


まずは、Yeoman の三種の神器をインストールします(今回 yo は使いません)。

$ npm cache clean
$ npm install -g yo bower grunt-cli

$ yo --version
1.4.7
$ bower -v
1.4.1
$ grunt -version
grunt-cli v0.1.13


プロジェクトを作成します。

$ mkdir -p ~/work/videojs-test && cd $_

### 全て Enter
$ npm init
$ npm cache clean

### 全て Enter
$ bower init
$ bower install videojs --save
$ bower install videojs-contrib-media-sources --save
$ bower install videojs-contrib-hls --save

### インストールされたバージョンを確認
$ bower ls
videojs-test#0.0.0 /Users/akiyoko/work/videojs-test
├── videojs#4.12.9 (latest is 5.0.0-rc.2)
├── videojs-contrib-hls#0.17.2
└── videojs-contrib-media-sources#1.0.0

参考
Bower入門(基礎編) - from scratch



videojs-contrib-hls に dist/videojs.hls.min.js が無かったので、videojs-contrib-hls を grunt でビルドしようとしたら・・・、

$ npm install grunt --save-dev

$ cd bower_components/videojs-contrib-hls/
$ npm install

npm WARN engine pkcs7@0.2.3: wanted: {"npm":"^1.4.6","node":"^0.10"} (current: {"node":"0.12.4","npm":"2.10.1"})
npm WARN engine karma@0.10.10: wanted: {"node":"~0.8 || ~0.10"} (current: {"node":"0.12.4","npm":"2.10.1"})
npm WARN peerDependencies The peer dependency karma-jasmine@~0.1.0 included from karma will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency karma-requirejs@~0.2.0 included from karma will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency karma-coffee-preprocessor@~0.1.0 included from karma will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency karma-html2js-preprocessor@~0.1.0 included from karma will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency karma-script-launcher@~0.1.0 included from karma will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
 
> phantomjs@1.9.17 install /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma-phantomjs-launcher/node_modules/phantomjs
> node install.js

Download already available at /var/folders/rc/_0bgj5gd2d3_1_r87wq7x4fh0000gn/T/phantomjs/phantomjs-1.9.8-macosx.zip
Extracting zip contents
Removing /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom
Copying extracted folder /var/folders/rc/_0bgj5gd2d3_1_r87wq7x4fh0000gn/T/phantomjs/phantomjs-1.9.8-macosx.zip-extract-1434734856569/phantomjs-1.9.8-macosx -> /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom
Writing location.js file
Done. Phantomjs binary available at /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma-phantomjs-launcher/node_modules/phantomjs/lib/phantom/bin/phantomjs
npm WARN deprecated deflate-crc32-stream@0.1.2: module has been merged into crc32-stream
 
> fsevents@0.2.1 install /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma/node_modules/chokidar/node_modules/fsevents
> node-gyp rebuild

  CXX(target) Release/obj.target/fse/fsevents.o
In file included from ../fsevents.cc:6:
../node_modules/nan/nan.h:339:13: error: no member named 'New' in 'v8::String'
    return  _NAN_ERROR(v8::Exception::Error, errmsg);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../node_modules/nan/nan.h:319:50: note: expanded from macro '_NAN_ERROR'
# define _NAN_ERROR(fun, errmsg) fun(v8::String::New(errmsg))
                                     ~~~~~~~~~~~~^
../node_modules/nan/nan.h:343:5: error: no member named 'ThrowException' in namespace 'v8'
    _NAN_THROW_ERROR(v8::Exception::Error, errmsg);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ・
    ・
    ・
../node_modules/nan/nan.h:181:38: note: expanded from macro 'NanSymbol'
#define NanSymbol(value) v8::String::NewSymbol(value)
                         ~~~~~~~~~~~~^
/Users/akiyoko/.node-gyp/0.12.4/deps/v8/include/v8.h:1379:8: note: 'IsSymbol' declared here
  bool IsSymbol() const;
       ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [Release/obj.target/fse/fsevents.o] Error 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/Users/akiyoko/.nodebrew/node/v0.12.4/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:269:23)
gyp ERR! stack     at ChildProcess.emit (events.js:110:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:1074:12)
gyp ERR! System Darwin 13.4.0
gyp ERR! command "node" "/Users/akiyoko/.nodebrew/node/v0.12.4/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/akiyoko/work/videojs-test/bower_components/videojs-contrib-hls/node_modules/karma/node_modules/chokidar/node_modules/fsevents
gyp ERR! node -v v0.12.4
gyp ERR! node-gyp -v v1.0.3
gyp ERR! not ok 

とエラーの嵐が。。


いろいろと調べてたどり着いたのが、こちら。

どうやら、Node.js のバージョンと karma のバージョンが合っていなかったのが、エラーの原因だとか。


そこで、nodebrew で Node.js のバージョンを v0.10系の最新版(StackOverflow で言及のあったバージョン)にしてやり直してみます。

$ nodebrew use v0.10.38
use v0.10.38

  ・
  ・
$ npm install

いろいろ WARN は出ましたが、ビルドは成功。
しかしながら、最後にブラウザのテストエラーがいっぱい出てしまいました。

そこで、

$ npm install --force

として、エラーが出ても無視することに。


その後、

$ grunt --force

とすると、dist 以下にファイルを生成することができました。

$ ls -al dist/
total 416
drwxr-xr-x   4 akiyoko  staff     136  6 20 02:51 .
drwxr-xr-x  23 akiyoko  staff     782  6 20 02:51 ..
-rw-r--r--   1 akiyoko  staff  155838  6 20 02:51 videojs.hls.js
-rw-r--r--   1 akiyoko  staff   49694  6 20 02:51 videojs.hls.min.js



ここから、grunt-bower-task を使って、プロダクション用のファイルを出力していきます。

$ cd ~/work/videojs-test/
$ npm install grunt-bower-task --save-dev

参考


Gruntfile.js を以下のように作成します。

module.exports = function(grunt) {
  grunt.initConfig({
    bower: {
      install: {
        options: {
          targetDir: './dist',
          //layout: 'byType',
          layout : function (type, component) {
            return type;
          },
          install: true,
          verbose: false,
          cleanTargetDir: true,
          cleanBowerDir: false
        }
      }
    }
  });
  grunt.loadNpmTasks('grunt-bower-task');
  grunt.registerTask('default', ['bower:install']);
};

参考



出力するファイルのディレクトリ構成を変更するために、bower.json に追記します。

ポイントとしては、videojs-contrib-hls と videojs-contrib-media-sources のライブラリには、"main" の書かれた bower.json が無かった(そもそも bower.json 自体が無かった)ので、"exportsOverride" で上書きしています。また、videojs の "exportsOverride" は、bower_components/videojs/bower.json のものをベースにしています。

{
  "name": "videojs-test",
  "version": "0.0.0",
  "authors": [
    "akiyoko blog <akiyoko@users.noreply.github.com>"
  ],  
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],  
  "dependencies": {
    "videojs": "~4.12.9",
    "videojs-contrib-media-sources": "~1.0.0",
    "videojs-contrib-hls": "~0.17.2"
  },  
  "exportsOverride": {
    "videojs": {
      "js": [
        "dist/video-js/video.js",
        "dist/video-js/video-js.swf"
      ],
      "css": "dist/video-js/video-js.min.css",
      "css/font": [
        "dist/video-js/font/vjs.eot",
        "dist/video-js/font/vjs.svg",
        "dist/video-js/font/vjs.ttf",
        "dist/video-js/font/vjs.woff"
      ]   
    },  
    "videojs-contrib-hls": {
      "js": "dist/videojs.hls.min.js"
    },  
    "videojs-contrib-media-sources": {
      "js": "src/videojs-media-sources.js"
    }                                                                                                                  
  }
}

参考
gruntのbower installでtargetDirにcopyするファイルを制御 | TEJI TECH BLOG



grunt コマンドを実行することで、以下のようなフォルダ構成で、プロダクション用のファイルを出力することができました。

$ grunt

$ tree dist/
dist/
├── css
│   ├── font
│   │   ├── vjs.eot
│   │   ├── vjs.svg
│   │   ├── vjs.ttf
│   │   └── vjs.woff
│   └── video-js.min.css
└── js
    ├── video-js.swf
    ├── video.js
    ├── videojs-media-sources.js
    └── videojs.hls.min.js