アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

Stylus の依存関係を import で管理する

July 20, 2015開発import, Stylus

これまで Stylus ファイルの依存関係は gulp で管理していた。Stylus を CSS にコンパイルするタスクで src へ明示的に順番を設定して、それを concat することで単一の bundle.css を生成する。例えば以下のような感じ。

var gulp = require( 'gulp' );
var $    = require( 'gulp-load-plugins' )();

// Stylus コンパイルと結合
gulp.task( 'stylus', function() {
  return gulp.src( [
      common.src + '/stylus/App.styl',
      common.src + '/stylus/MusicList.styl',
      common.src + '/stylus/Toolbar.styl',
      common.src + '/stylus/Icon.styl'
    ] )
    .pipe( $.plumber() )
    .pipe( $.sourcemaps.init() )
    .pipe( $.stylus() )
    .pipe( $.concat( 'bundle.css' ) )
    .pipe( $.minifyCss() )
    .pipe( $.sourcemaps.write( '.' ) )
    .pipe( gulp.dest( common.src ) );
} );

この方法だと Stylus ファイル単体では依存関係が分からない。例えば未知の font-family が登場したとき、それが使用可能であることを確認するためには gulpfile.js や HTML の <link> タグなどを調べる必要がある。

依存関係が変更されたときに gulpfile.js の編集が発生するのも面倒だ。増減に気をつけながら運用するのはストレスを感じる。もっと気軽に管理したい。

これらの問題を解決するため Stylus の import 機能を活用してみる。

これまでは import は共通の色やサイズ、MixIn 定義に限定。これ以外に用いると CSS 標準の動的な import に変換されるものと認識しており避けていた。しかし実際に gulp-stylus 経由で通常のスタイルを import してコンパイルしてみたところ CSS 標準にはならず静的結合された。つまり Browserify/babelify を利用したときの ES6 module みたいに使える。

例えば以下のよう書くと、

@import "CommonColor.styl"

// ページ全体
body, html {
  width 100%
  height 100%
  margin 0
  padding 0
}

@import "Icon.styl"
@import "Toolbar.styl"
@import "MusicList.styl"

はじめに CommonColor.styl、次にこの Stylus 自身、その後に Icon.stylToolbar.stylMusicList.styl という順にコンパイルされる。import の位置は自由なのでサンプルのように import 後にスタイルを書いて更に続ける、といった記述も可能。

これを CSS にコンパイルする gulp タスクは以下。

var gulp = require( 'gulp' );
var $    = require( 'gulp-load-plugins' )();

// Stylus コンパイルと結合
gulp.task( 'stylus', function() {
  return gulp.src( [ common.src + '/stylus/App.styl' ] )
    .pipe( $.plumber() )
    .pipe( $.sourcemaps.init() )
    .pipe( $.stylus() )
    .pipe( $.rename( 'bundle.css' ) )
    .pipe( $.minifyCss() )
    .pipe( $.sourcemaps.write( '.' ) )
    .pipe( gulp.dest( common.src ) );
} );

前述のサンプルから変更した部分は 6 行目と 10 行目。

まずは 6 行目。コンパイル対象となる Stylus は単一化される。これはいわばエントリー ポイント。ここに依存する Stylus を import で参照してゆく。参照される側で更に import を書いてもよい。ここが全 Stylus の起点になるため App.styl とか Main.styl みたいなファイル名にしておくと分かりやすい。

次に 10 行目。従来 gulp-concat していた部分を gul-rename に変更。結合は gulp-stylus が実行するので、その結果となるファイル名を bundle.css にしているだけ。

これで Stylus 管理がずいぶん楽になりそうだ。