第三回 Raspberry Pi 3に最新のNode.jsをインストールする

今回はRaspberry PiにNode.jsをインストールしようと思った所、思ったより時間がかかったので作業メモを書きます。

Raspberry Piにはデフォルトでnodeコマンドが入っていましたがとても古いものでした。素直にsudo apt-get install nodejsをしても同じく古いものが入るし、nodeではなくてnodejsコマンドになります。よって、npmのnを使ってnodeをインストールしていきます。以下を参考にしました。
http://qiita.com/seibe/items/36cef7df85fe2cefa3ea

インストール手順

まずは普通にnodejsとnpmをインストールします。

sudo apt-get install -y nodejs npm

次に最新のnodeをインストールします。完了したら、インストールされた場所にパスが通るように修正します。環境によってまちまちなので、既存のものなどを消すなどして対応しましょう。

sudo npm cache clean
sudo npm install n -g
sudo n stable

このように最新のnodeが入りました。

pi@raspberrypi:~ $ node -v
v6.0.0

今後のアップデートに対応していく方法は以下の記事にまとめてありました。今回入れたnpmが古かったので、この方法でnpmは別途最新にしました。
http://parashuto.com/rriver/tools/updating-node-js-and-npm

PHPで連想配列をオブジェクトにする

設定値など配列で保存されている値をアロー演算子でアクセスできるようにしたい。この場合は(object)でキャストするだけで可能でした。

$config = [
'a' => 1,
'b' => 2,
'c' => 3
];
var_dump($config);
var_dump((object) $config);
$ php hoge.php
array(3) {
'a' =>
int(1)
'b' =>
int(2)
'c' =>
int(3)
}
class stdClass#1 (3) {
public $a =>
int(1)
public $b =>
int(2)
public $c =>
int(3)
}

しかしこれだと多次元配列には対応していないので直下だけがオブジェクトになり、それ以降の階層は配列のまま残ってしまいます。

$config = [
'a' => 1,
'b' => [
'd' => 2,
'e' => 3
],
'c' => 4
];
var_dump((object) $config);
$ php hoge.php
class stdClass#1 (3) {
public $a =>
int(1)
public $b =>
array(2) {
'd' =>
int(2)
'e' =>
int(3)
}
public $c =>
int(4)
}

これを解決するにはjson_encodeしてからjson_decodeすると良いです。10万回実行したところ0.53sと割りと高速です。

$config = [
'a' => 1,
'b' => [
'd' => 2,
'e' => 3
],
'c' => 4
];
var_dump(json_decode(json_encode($config)));
$ php hoge.php
class stdClass#1 (3) {
public $a =>
int(1)
public $b =>
class stdClass#2 (2) {
public $d =>
int(2)
public $e =>
int(3)
}
public $c =>
int(4)
}

しかしなんだか行儀が悪いので、再帰的にキャストするような目的に沿った以下の関数を作ってもいいかもしれません。でもこれは10万回あたり3.653sと遅めでしたw

function arrayToObject($mixed) {
if (!is_array($mixed)) {
return $mixed;
}
return (object) array_map(function($value) {
return arrayToObject($value);
}, $mixed);
};
$config = [
'a' => 1,
'b' => [
'd' => 2,
'e' => 3
],
'c' => 4
];
var_dump(arrayToObject($config));

連想配列なら素直に連想配列として使う方が良いんでしょうか。json_decodeでJSONをパースした時にオブジェクトになる件を受けて、もっとオブジェクト化したい欲を感じてしまいました。

node-sassでSassファイルをコンパイルする

Sassのコンパイルに高速に動作するnode-sassを使います。node-sassのインストールは非常に簡単です。

インストール

npmを使う場合

npm install -g node-sass

yarnを使う場合

yarn global add node-sass

コンパイル

あとはコンパイルしたいファイルと出力先を指定するだけ。

node-sass test.scss test.css

CSSとHTMLだけの小型プロジェクトであれば、webpackなどを使ってwebpack.config.jsonとかpackage.jsonなどの設定ファイルを用意するよりも、node-sassだけで単発でコンパイルする方がプロジェクトが綺麗になるかと思います。

よく使うコマンド

ファイルを更新したら自動コンパイルする場合は-w--watchを付ける

node-sass test.scss test.css -w

--output-styleでコンパイル結果を調整できます。デフォルトはnestedになっていますが、出力結果のCSSを整形して出力するならexpandedを指定します。

node-sass test.scss test.css --output-style expanded

本番公開時に圧縮コンパイルする場合はcompressedを指定します。

node-sass test.scss test.css --output-style compressed

小技

catで流すこともできます

cat test.scss | node-sass > out.css

デフォルトはインデントのスペース数は2ですがこれは変更できます

node-sass test.scss test.css --output-style expanded --indent-width 4

インデントをタブにしたい時はタブにできます

node-sass test.scss test.css --output-style expanded --indent-type tab

その他いろんなオプションがあります(日本語訳しておきました)

-w、--watch                ディレクトリまたはファイルを見る
-r、--recursive            ディレクトリやファイルを再帰的に監視する
-o、--output               出力ディレクトリ
-x、--omit-source-map-url  出力からソースマップのURLコメントを省略する
-i、--indented-syntax      stdinのデータをsassコードとして扱う(対scss)
-q、--quiet                エラー以外のログ出力を抑止する
-v、--version              バージョン情報を表示します。
--output-style            CSS出力スタイル(ネストされた| expanded | compact | compressed)
--indent-type             出力CSSのインデントタイプ(スペース|タブ)
--undent-width            インデント幅。スペースまたはタブの数(最大値:10)
--linefeed               ラインフィードスタイル(cr | crlf | lf | lfcr)
--source-comments         出力にデバッグ情報を含める
--source-map              ソースマップを出力する
--source-map-contents     マップにインクルードした内容を埋め込む
--source-map-embed        データURIとしてsourceMappingUrlを埋め込む
--source-map-root         基本パスはそのままsource-mapに出力されます
--include-path            インポートされたファイルを探すパス
--follow                  symlinkedディレクトリに従う
--precision               10進数で許可される精度の量
--importer                カスタムインポーターを含む.jsファイルへのパス
--functions               カスタム関数を含む.jsファイルへのパス
--help                    ヘルプの表示

原文は以下

-w, --watch                Watch a directory or file
-r, --recursive            Recursively watch directories or files
-o, --output               Output directory
-x, --omit-source-map-url  Omit source map URL comment from output
-i, --indented-syntax      Treat data from stdin as sass code (versus scss)
-q, --quiet                Suppress log output except on error
-v, --version              Prints version info
--output-style             CSS output style (nested | expanded | compact | compressed)
--indent-type              Indent type for output CSS (space | tab)
--indent-width             Indent width; number of spaces or tabs (maximum value: 10)
--linefeed                 Linefeed style (cr | crlf | lf | lfcr)
--source-comments          Include debug info in output
--source-map               Emit source map
--source-map-contents      Embed include contents in map
--source-map-embed         Embed sourceMappingUrl as data URI
--source-map-root          Base path, will be emitted in source-map as is
--include-path             Path to look for imported files
--follow                   Follow symlinked directories
--precision                The amount of precision allowed in decimal numbers
--importer                 Path to .js file containing custom importer
--functions                Path to .js file containing custom functions
--help                     Print usage info