LoginSignup
7
7

More than 5 years have passed since last update.

grunt-sprockets で複数の CoffeeScript を一つの無名関数内にまとめる

Posted at

以前書いた

Grunt で複数の CoffeeScript を一つの無名関数内にまとめる

browserify で複数の CoffeeScript を一つにまとめる

の続き。

今回は以下の記事で ysugimoto さんが作成された grunt-sprockets を使って CoffeeScript を一つの無名関数内にまとめてみる。

grunt-sprocketsタスクプラグイン作成とテストとTravis CIまでやってみる | ブログ :: Web notes.log
http://blog.wnotes.net/blog/article/create-grunt-task-plugin-and-testing-travis-ci

GitHub のリポジトリは以下にある。

ysugimoto/grunt-sprockets
https://github.com/ysugimoto/grunt-sprockets

準備

ディレクトリを作成して grunt-sprockets をインストール。
Coffee からコンパイルしたかったので grunt-contrib-coffee も入れている。

% mkdir -p sprockets-test/{src/{js,coffee},dest} && cd sprockets-test
% npm init
% npm install grunt grunt-contrib-coffee grunt-sprockets --save-dev

これでディレクトリ構造は以下のようになる。

sprockets-test
 ├── dest
 ├── node_modules
 │   ├── grunt
 │   ├── grunt-contrib-coffee
 │   └── grunt-sprockets
 ├── package.json
 └── src
     ├── coffee
     └── js

スクリプトの作成

以下のスクリプトを作成。

sprockets-test/src/coffee/foo.coffee
class Foo
  name: ->
    'Foo'
sprockets-test/src/coffee/bar.coffee
class Bar
  name: ->
    'Bar'
sprockets-test/src/js/main.js
(function() {
//= require foo.js
//= require bar.js

  var foo = new Foo();
  var bar = new Bar();

  console.log(foo.name());
  console.log(bar.name());
}).call(this);

ここで気をつけなくてはいけないのだが、sprockets のディレクティブ( //= require ~ )がインデントされていると上手く動作しない。

node_modules/grunt-sprockets/tasks/sprockets.js 内でディレクティブを抜き出している正規表現が /^\/\/=\srequire(_tree)?(?:\s+)?(.+)$/mg と行頭から指定されている事によるっぽいので、この辺弄ればどうにか出来そうではある。

ただ、元々 Rails で使う時は確かにディレクティブは行頭開始なのでそういう仕様という事かもしれない。

少なくとも確認時点のバージョン 0.7.0 の grunt-sprockets では行頭から開始していないと動作しなかった。

Gruntfile.js

Gruntfile.js は以下のようにした。

sprockets-test/Gruntfile.js
module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        coffee: {
            compile: {
                options: {
                    bare: true,
                },
                files: [{
                    expand: true,
                    cwd: 'src/coffee',
                    src: ['*.coffee'],
                    dest: 'src/js/',
                    ext: '.js',
                }]
            }
        },
        sprockets: {
            main: {
                files: [
                   'src/js/main.js',
                ],
                dest: 'dest/main.js',
            },
        },
    });
    grunt.loadNpmTasks('grunt-contrib-coffee');
    grunt.loadNpmTasks('grunt-sprockets');
    grunt.registerTask('default', ['coffee', 'sprockets']);
};

sprockets タスクの設定はほとんど concat と同じ。
coffee 側で bare: true を指定して個々のスクリプトを無名関数でラップしないようにしておく必要があるのも同じ。

実行

用意ができたので grunt を実行してみる。

% grunt
Running "coffee:compile" (coffee) task
>> 2 files created.

Running "sprockets:main" (sprockets) task
[Processing]: "src/js/main.js" ...
[Processing]: "src/js/foo.js" ...
[Processing]: "src/js/bar.js" ...
Build file: dest/main.js ...

Done, without errors.

生成された dest/main.js は以下のような内容。

sprockets-test/dest/main.js
(function() {
var Foo;

Foo = (function() {
  function Foo() {}

  Foo.prototype.name = function() {
    return 'Foo';
  };

  return Foo;

})();

var Bar;

Bar = (function() {
  function Bar() {}

  Bar.prototype.name = function() {
    return 'Bar';
  };

  return Bar;

})();


  var foo = new Foo();
  var bar = new Bar();

  console.log(foo.name());
  console.log(bar.name());
}).call(this);

require ディレクティブで指定した位置にスクリプトが挿入されている事が判る。
実行してみる。

% node dest/main.js 
Foo
Bar

問題なく動作した。

Rails で見慣れている Sprockets のディレクティブがそのまま使えるのは馴染みやすくてやはり嬉しい。

concat とほぼ同じような挙動をするが、個人的には concat で結合順を Gruntfile.js 内で指定するよりは、ソースコード内で依存関係を明示出来る grunt-sprockets の方が良いんじゃないかと思った。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7