細かすぎて伝わらない Sails.js v0.9.3 のtipsまとめ
Sails.jsは0.8系から0.9系にバージョンアップした際、仕様が大きく変わったので少しまとめてみました。
ちなみにSails.jsは もう v0.9.4のリリース終わって v0.9.7です。。。(2013/10/17現在)
grunt 依存
sails lift(node app.js) 実行時、内部的にgrunt を実行しています。これはv0.9系の一番大きい変更であり、一番やっかいな仕様変更です。
これにより、grunt[default]を実行し、そこからSails(Express)でサーバを起動するタイプの処理(grunt-express-serverなど)が動作しません。
また、これに付随するのか node-supervisor での起動も出来ません。再起動を延々繰り返します。
(2014/4/1追記)
ignoreファイルを設定することで動作します
(2014/4/1追記終わり)
公式にはforever を使うことを推奨しているようです。
本番・非本番環境の切り替え
内部で実行されるgruntコマンドが、本番系と非本番系で切り替わります。`sails.config.environment == "production"` であれば 本番環境と判定します。
`config.environment` はNODE_ENV設定を再優先し、次にsails.config で割り当てられた値を採用します。
(NODE_ENV指定例: NODE_ENV='production' sails lift など )
私の場合、以前のsails.jsの習慣から 「local.js が有るか無いか」 で本番・非本番の切り替えとしています。
/config/application.js
ファイルを作成し、
module.exports.environment = process.env.NODE_ENV || 'production'
と記述して次の関係としています。
- local.js が存在しない場合
- application.js の module.exports.environment ( = sails.config.environment ) が採用され、設定値 'production' を使用
- local.js が存在する場合
- application.js の module.exports.environment を上書きし、初期設定値の 'development'を使用
つまり
- application.js << local.js <<<<<< NODE_ENV
の関係となります。
これにより 本番環境下では 必ず/config/local.js を除外(※)し、NODE_ENVの設定変更は行わなくて済むようにしています。
(※ gitignoreによる、git pull もしくは git server へのpush でのファイルデプロイが前提)
更に書くと 個人的には npm start が基本的な動作になるようになる。という個人的な統一性をもたせているというのもあります。
.tmp フォルダへのコンパイル出力
先程の項目で 本番と非本番でgrunt 実行コマンドが切り替わると書きました。詳細はこのようになります。
sails.config.environment: 'development'
- grunt [default]
- assets フォルダファイルを .tmp フォルダに展開、また、less,coffeescript ファイルなどはコンパイルしたファイルを出力
grunt のconnect.static により、.tmp/public フォルダはドメイントップディレクトリとなります。
sails.config.environment: 'production'
- grunt prod
- .tmp フォルダへ出力されたファイルを minフォルダに concat,uglify展開(.tmp/min/production.js)
開発環境時(grunt[default])は圧縮などを行わず、処理時間を短縮しています。
圧縮ファイルへのパス参照問題
concat,uglify されたファイルを参照するために <style>や<script> のパスの変更するのが大きな手間となります。(みなさんは他のフレームワークなどでどうされているか、少し気になるところでは有りますが)
sails.js ではこれを解消するために --linker オプションを用意しています。
--linkerオプション
初期フォルダ構成生成コマンド、sails new に --linker オプションを付与します。
すでにsails new でフォルダを生成してしまった場合でも移行は出来ますが、ここでは説明を省きます。
構成上の大きな違いは assetsフォルダに展開されたlinker フォルダと /view/layout.ejs
へ出力されたファイル内の <!--SCRIPTS-->などのコメント群です。
linkerフォルダ内の js/styles/templates
ファイルはそれぞれ js/css/jst-template
の構成です。
開発時は、linker オプション無しでの動作とそう変わりません。
違うのは 本番(environment: 'production') 実行時です。
例えば、/assets/linker/js
フォルダのファイルは、/.tmp/public/linker/js
へコンパイル処理されたあと、/.tmp/min/production.js
へ出力されます。
さらに(ここ重要)、/view/layout.ejs
内の <!--SCRIPTS--><!--SCRIPTS END-->で囲われている個所が自動で書き換えられます。
environment: 'development'
<!--SCRIPTS-->
<script src="/linker/js/socket.io.js"></script>
<script src="/linker/js/sails.io.js"></script>
<script src="/linker/js/app.js"></script>
<!--SCRIPTS END-->
environment: 'production'
<!--SCRIPTS-->
<script src="/min/production.js"></script>
<!--SCRIPTS END-->
css は、 <!--STYLES--><!--STYLES END--> で記述されたブロックが書き換えれれます。
grunt における sails-linker によって、 grunt ⇔ grunt prod(本番系・非本番系)でパスが自動的に変更される事になります。
ここで問題となるconcat による結合順序ですが、その設定は Gruntfile.js内で記述されています。
(ちなみにdevelopment時の呼び出し順も同様)
var cssFilesToInject = [
'linker/**/*.css'
];
/**
* Javascript files to inject in order
* (uses Grunt-style wildcard/glob/splat expressions)
*
* To use client-side CoffeeScript, TypeScript, etc., edit the
* `sails-linker:devJs` task below for more options.
*/
var jsFilesToInject = [
// Below, as a demonstration, you'll see the built-in dependencies
// linked in the proper order order
// Bring in the socket.io client
'linker/js/socket.io.js',
// then beef it up with some convenience logic for talking to Sails.js
'linker/js/sails.io.js',
// A simpler boilerplate library for getting you up and running w/ an
// automatic listener for incoming messages from Socket.io.
'linker/js/app.js',
// *-< put other dependencies here >-*
// All of the rest of your app scripts imported here
'linker/**/*.js'
];
/**
* Client-side HTML templates are injected using the sources below
* The ordering of these templates shouldn't matter.
* (uses Grunt-style wildcard/glob/splat expressions)
*
* By default, Sails uses JST templates and precompiles them into
* functions for you. If you want to use jade, handlebars, dust, etc.,
* edit the relevant sections below.
*/
var templateFilesToInject = [
'linker/**/*.html'
];
'/assets' フォルダ と '/assets/linker' の使い分けは、ライセンス付きでの使用が前提かどうかで良いと思っています。
'linker' 以下のファイルは、結合・圧縮され 'production.xx' へと出力されるので、単体での使用が望ましいものは 'assets' フォルダ直下で良いのではないでしょうか?
https 起動
v0.9.3 では sails.config.ssl で設定できませんでした
module.exports.express = {
ssl: {
key: require("fs").readFileSync( require("path").resolve( "ssl/server.key" )).toString(),
cert: require("fs").readFileSync( require("path").resolve( "ssl/server.crt")).toString()
}
}
どうやらsails.js側(express wrapper)で設定出来ず、express のserverOptionで直接設定するしかないようです。
(v0.9.4ではおそらく解決済み Issue #844 )
module.exports.express = {
serverOptions:{
key: require("fs").readFileSync( require("path").resolve( "ssl/server.key" )).toString(),
cert: require("fs").readFileSync( require("path").resolve( "ssl/server.crt")).toString()
}
}