ぼくたちがフロントエンドエンジニアと呼ばれるまで

Sassコーディングを行なう上で必要となる各種自動化の話

こんにちは、エンジニアの尾形です。

前回のブログではCSS規約やSassによるコーディングの実例についてお伝えしました。
今回はSassコーディングを行なう上で必要となる各種自動化の例についてご紹介します。
面倒な作業を自動化して作業を効率化しましょう。

タスクランナー使っていますか?

WEBサイトの制作では「Sassのコンパイル」や「CSSの圧縮」などいくつかの作業(タスク)があります。これらの面倒な作業を自動で行なってくれるのがタスクランナーです。

ご存知の方も多いと思いますが、プログラマーの三大美徳の「怠惰」「短気」「傲慢」というものがあります。三つとも印象が良くない言葉ですが、今回のテーマの「自動化」はまさに「怠惰」のことです。労力を減らして楽をする、開発効率を上げる、ということですね。

残りの二つの「短気」と「傲慢」にも簡単に触れておきます。
・短気・・・コンピューターが期待通りに動かないことへの怒りのこと。その怒りの元となっている問題を改善・改良してより良いプログラムにしたいですね。(人に対する怒りとは違います)
・傲慢・・・自分の書いたプログラムに自信と責任を持つこと。人前に出しても恥ずかしくないプログラムを書きたいですね。

タスクランナーには GulpGrunt などいくつかあります。今回は、近年人気の Gulp を使用しました。タスクの処理をJavaScript で記述できるのも選んだ理由のひとつです。

Gulpについて、より詳しく知りたい方は、外部のサイトをご参照ください。
5分で導入! タスクランナーGulpでWeb制作を効率化しよう – ICS MEDIA

Sassをコンパイルする

Gulpを使用してSassをコンパイルします。
コンパイル時にベンダープレフィックスの付与や圧縮(minify)などを行なっています。

// プラグインを読み込む
var gulp = require('gulp');
var gulpif = require('gulp-if');
var sass = require('gulp-sass');
var sassVariables = require('gulp-sass-variables');
var sourcemaps = require('gulp-sourcemaps');
var autoprefixer = require('gulp-autoprefixer');
var minifycss = require('gulp-minify-css');

// Sassコンパイルタスク
gulp.task('sass', function() {
    var env = process.env.APP_ENV || 'development';
    var isProduction = (env === 'production');   // ※1-1

    gulp.src('./src/scss/app.scss')   // ※1-2
        .pipe(gulpif(!isProduction, sourcemaps.init()))   // ※1-3
        .pipe(sassVariables({   // ※1-4
            $env: env
        }))
        .pipe(sass())   // ※1-5
        .pipe(gulpif(!isProduction, sourcemaps.write({ includeContent: false })))
        .pipe(gulpif(!isProduction, sourcemaps.init({ loadMaps: true })))
        .pipe(autoprefixer())   // ※1-6
        .pipe(gulpif(isProduction, minifycss()))   // ※1-7
        .pipe(gulpif(!isProduction, sourcemaps.write('.', {
            sourceMappingURL: function(file) {   // ※1-8
                return '/css/app.css.map';
            }
        })))
        .pipe(gulp.dest('../css/'));   // ※1-9
});

※1-1 環境変数APP_ENVによって開発と本番を切り替えます。
※1-2 対象のSassファイルを指定します。これ以降 pipe() で処理を繋げていきます。
※1-3 本番でなければsourcemapsを有効にします。sourcemapsに関してはトリッキーな記述となっていますが、これはautoprefixerを使うとsourcemapsが正しく出力されなかったためです。下記を参考にしてこのような記述にしています。
[Gulp] gulp-sass + gulp-autoprefixer + gulp-sourcemaps で SourceMap を出力したい

※1-4 環境変数によってSass上で処理を振り分けたい場合はここで指定します。Sass上では以下のように変数を参照することができます。

@if($env=='production') {
    $img-url-base: 'http://example.com';
}

※1-5 sassプラグインを実行します。
※1-6 ベンダープレフィックスを自動で付与します。
※1-7 本番ならminifyします。
※1-8 sourcemapのURLを書き換えたい場合はここで指定します。
※1-9 cssの出力先を指定します。

ファイルの変更を監視して、自動でSassをコンパイルする

Gulpではファイルの変更を監視することも可能です。
これにより、Sassファイルの変更を検知して自動でコンパイルをすることができます。

var watch = require('gulp-watch');
var batch = require('gulp-batch');

// ファイル変更監視タスク
gulp.task('watch', function() {
    // 監視のオプション
    var watchOptions = {
        usePolling: true,
        interval: 1500,
        binaryInterval: 1500
    };

    // Sassファイルの監視
    watch(['./src/scss/**/*.scss'], watchOptions, batch(function(events, done) {   // ※2-1
        gulp.start('sass', done);   // ※2-2
    }));
});

※2-1 監視対象のSassファイルを指定します。
※2-2 Sassコンパイルタスクを実行します。

なお、私たちの開発環境では標準のwatchだと監視が正常に動きませんでしたので、監視の方法を変更しています。以下に詳しく説明します。

開発環境の構成は以下のとおりです。
・VirtualBoxを使用。ホストOSはWindows、ゲストOSはLinux。
・ホストOS上のフォルダーをゲストOS側で共有フォルダーとしてマウントする。
・ゲストOS側でgulpを実行する。

この構成の場合、標準のwatchではファイルの変更を検知してくれません。その理由は、標準のwatchの場合は更新を検知するためにファイルのatime(最終アクセス日時)が使用されるようなのですが、VirtualBoxの共有フォルダーではatimeが更新されないためです。そこで、監視オプションに「usePolling: true」を指定して監視方法をポーリング方式に変更し、能動的に検知するようにしています。ただ、この方式では定期的にファイルの状態を問い合わせることになるため、その分処理が重くなるのがネックです。「interval: 1500」のように監視のインターバルを指定することができますので、リアルタイム性とシステム負荷を考慮したうえで決定するのがよいと考えます。

ファイルの変更を自動でブラウザに反映する

これまでの開発では、HTMLやCSSファイルを変更したらブラウザーを手動でリロードしていましたが、この作業もGulpで自動化できます。

ファイルの変更を監視し、自動でブラウザのリロードを行なってくれる Browsersync というツールがあり、Gulpのプラグインとして提供されていますので、それを使用します。

var browserSync = require('browser-sync');

// WEBアプリケーションへのプロキシーとしてBrowsersyncを起動するタスク
gulp.task('browser-sync', function() {
    browserSync.init({
        proxy: 'http://xxxxxxxxxx',   // ※3-1
        port: 3000,   // ※3-2
        ui: {
            port: 3001   // ※3-3
        },
        reloadDelay: 1000,
        open: false,   // ※3-4
    });
});

// ブラウザーのリロードを行なうタスク
gulp.task('browser-sync-reload', function() {
    browserSync.reload();
});

※3-1 WEBアプリケーションが動作しているアドレスです。
※3-2 Browsersyncのポートです。このポートにつなぐと※3-1のWEBアプリケーションに転送されます。
※3-3 Browsersyncのユーザーインターフェースのポートです。
※3-4 Browsersyncの起動時にブラウザーを自動で開かないようにしています。

上記でリロードの仕組みができましたので、前述のwatchタスクに以下を追加し、ファイルが変更されたらブラウザーのリロードを行なうようにします。

    // HTML/CSS/JavaScriptファイルの監視
    // sassコンパイルによって生成されたcssファイルもここで監視します
    watch(['**/*.html', '**/*.css', '**/*.js'], watchOptions, batch(function(events, done) {   // ※4-1
        gulp.start('browser-sync-reload', done);   // ※4-2
    }));

※4-1 監視対象のHTML/CSS/JavaScriptファイルなどを指定します。
※4-2 ブラウザーのリロードを行なうタスクを実行します。

まとめと予告

今回はSassコーディングを行なう上で必要となる自動化の例について書かせていただきました。今回紹介したタスク以外にも自動化できるタスクはいろいろあります。例えば、
・Sass上にスタイルガイド用のコメントを記述して、Gulpでスタイルガイドを自動生成する
・コンパイル時に、特定のディレクトリに画像ファイルをコピーする
なども自動化できます。どんどん自動化して、より一層作業を効率化していきたいですね。

HTML/CSS/Sassに関する記事は今回で最後となります。
次回からは、数回にわたってAngular1によるSPA開発についてご紹介させていただきます。

第4回
Angular1 基本編
– はじめに(Angular2, Angular4がリリースされたのにAngular1を使っている経緯。Angular2への移行を見送った話)
– TypeScriptでコーディングする(静的型付けの重要性)
– TypeScriptの型定義ファイルについて(@typesパッケージを使用。@typeで提供されていないモジュールや自作した型定義についてはtypingsを使用)
– ライブラリーについて(jQueryとの共存)(基本はnpmリポジトリを使用。npmに存在せずbowerにのみ存在する場合のみbowerを使用)
– ディレクトリー構成(サンプル紹介)
– 自動コンパイルについて(gulpタスクの紹介)
– minify対策について(対策しないとエラーになる話)

フロントエンドエンジニアへの道

1- HTML/CSSコーディングはじめるぞ〜HTML/CSSコーディングを行なうにあたっての事前準備
2- チーム作業をするための最適なCSS規約、Sassについて考えた
3- Sassコーディングを行なう上で必要となる各種自動化の話
4- Angular1によるSPA開発 – 基本編
5- Angular1によるSPA開発 – 設計編
6- Angular1によるSPA開発 – Tips編

LINEで送る
Pocket

この記事を書いた人・プロフィール
オガティー
ニックネーム: オガティー

2014年3月から現職。当社のベンチャービジネスに心惹かれて入社。
それ以前はソフトハウス(2社)に在籍。
エンジニア歴はもう少しで20年。通信キャリアーのシステム開発、サーバーサイドプログラミングの経験が長い。
エンジニアとしてのベースはJava屋。Androidアプリ開発も。サーバーサイドはPHP, Node.jsが多い。
フロントエンドエンジニアとしては駆け出し。
趣味:ギター、ドラム、フットサル、お酒