« Backbone.jsを使ったNode.jsアプリのCSRF対策 | トップページ | JSONデータの圧縮について »

2013年6月 1日 (土)

JavaScriptをminifyしてgzipしてS3へのアクセスにする

最近Require.jsが取り上げられることが多いのですが、私は使っていません。

Backbone.jsを使ったアプリには、非同期ローディングよりも、Javascriptをひとつのファイルにまとめてminifyして、gzip圧縮して最初に読み込んでしまうほうがいいと思ってます。

例えば今開発しているアプリのJavaScriptのそのままのSizeは651KBですがminifyすると517KBになり、gzip圧縮すると117KBとなります。

Node.jsを使っている私の一押しはやっぱりmincer です。

mincerの解説はAsset Pipelineのすすめ を参照ください。

mincerは、minify,gzip圧縮の機能はないので、別に対応する必要があります。 さらにそのファイルをS3にアップロードして、S3にJavaScriptをホスティングしてもらうまでのNode.jsのscriptを作成しました。

#!/usr/bin/env node
var fs = require('fs');
var gzip = require('gzip');
 
var http = require('http');
var Mincer = require('mincer');
var exec = require('child_process').exec
var querystring = require("querystring");
var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: ''access_key_id'',
secretAccessKey: ''secret_access_key'',
region: "ap-northeast-1"});
var s3 = new AWS.S3();
 
var environment = new Mincer.Environment();
environment.appendPath('app/assets/javascripts');
 
environment.findAsset('application.js').compile(function (err, asset) {
if(err){
console.log(err);
process.exit(1);
}
var params = [
'compilation_level=SIMPLE_OPTIMIZATIONS',
'output_format=json',
'output_info=compiled_code',
'output_info=warnings',
'output_info=errors',
'output_info=statistics'
]
params.push(querystring.stringify({js_code: asset.toString()}));
var param = params.join("&")
var request_header = {
'user-agent': 'node.js',
'content-length': param.length,
'content-type': 'application/x-www-form-urlencoded'
}
var options = {
host : "closure-compiler.appspot.com",
path : "/compile",
method : "POST",
headers : request_header
}
var msg = ""
var req = http.request(options,function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
msg += chunk
});
res.on('end', function (chunk) {
try{
var result = JSON.parse(msg);
}catch(e){
console.log(msg);
console.log(e.stack);
process.exit(1);
}
if(result.errors){
console.log(result.errors);
console.log("cancelled above error!");
process.exit(1);
}
var jsFile = __dirname + "/lib/compiled.js";
gzip(result.compiledCode, function(err, compData) {
if (err) throw err;
var params = {
Bucket: ''bucket_name'',
Key: asset.digestPath + ".jgz",
Body: compData,
ACL:'public-read',
ContentEncoding: "gzip",
ContentType: "application/x-javascript" };
s3.client.putObject(params,function(err,data) {
if (err) throw err;
var url = "https://s3-ap-northeast-1.amazonaws.com/" +
''bucket_name'' + "/" + asset.digestPath + ".jgz";
console.log("It\\'s post! " + url);
fs.writeFile(jsFile, "ASSET_JS_PATH='" + url + "';", function (err) {
if (err) throw err;
console.log('SUCCESS');
});
});
});
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(param);
req.end();
});

上記スクリプトの'' ''で囲まれている箇所は適切な値に置き変えてください。 また、mincerのmanifestファイルはapp/assets/javascripts/application.js だと仮定しています。適切に書き換えてください。

minifyには、googleのclosure-compilerのWebサービスを使って行なっています。

closure-compilerはjarとして、提供されているのでそれを使うのもいいと思います。Webサービスは極まれに落ちていることがあるし、今後もサービスが続くとは限らないので。ただ、Javaをinstallしていない環境を考慮したり、jarがそこそこ大きいので配布するのも面倒だったため、Webサービス利用にしました。

利用方法
npm install mincer
npm install aws-sdk
node mincer_s3upload.js

上記コマンドを実行すると、lib/compiled.jsに下記のようにs3のURLの定数が定義されます。(下記URLは適当)

ASSET_JS_PATH='https://s3-ap-northeast-1.amazonaws.com/bucketname/application-27c2c991a5dc8291254e23f14bc21829.js.jgz';

app.jsを下記のようにすることで、開発の場合は動的compileによりファイルの変更を即座に変更するようにしています。

require('./lib/compiled');
app.configure('development', function(){
var Mincer = require('mincer');
var environment = new Mincer.Environment();
environment.appendPath(__dirname + '/app/assets/javascripts');
app.use('/assets', Mincer.createServer(environment));
ASSET_JS_PATH = null
});
 
app.get('/', index);
 
function index(req, res, next){
res.render('index', { js_path: ASSET_JS_PATH });
}
view raw app.js This Gist brought to you by GitHub.

index.ejsは下記

<% if(js_path){ %>
  <script type="text/javascript" src="<%- js_path %>"></script>
<% }else{ %>
  <script type="text/javascript" src="/assets/application.js"></script>
<% } %>

Happy Backbone!!

|

« Backbone.jsを使ったNode.jsアプリのCSRF対策 | トップページ | JSONデータの圧縮について »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/68673/57501621

この記事へのトラックバック一覧です: JavaScriptをminifyしてgzipしてS3へのアクセスにする:

« Backbone.jsを使ったNode.jsアプリのCSRF対策 | トップページ | JSONデータの圧縮について »