Javascript

gulpでsassとbabelとbrowserSyncを実行する方法

この記事ではsassのコンパイルとbabelでのトランスパイルとbrowserSyncによるブラウザ自動リロード、ベンダープレフィックス自動化をgulpで自動化するまでについて書きます。

こんにちはともです。

最近JavaScriptを勉強し始めました。フロントエンドってツールが豊富で嬉しいのですが、豊富すぎてよく分からない状態です。

今回はgulpというタスクランナー(タスクを自動化してくれるツール)を利用して色々な事を自動化して見たいと思います。

自動化するものは次のものです。

  1. sass→cssのコンパイル
  2. ES6以降→ES5へのトランスパイル
  3. ソースを変更したらブラウザをリロード
  4. ベンダープレフィックスを自動でつける

Node.jsのインストール

npm(Node Package Manager)というNode.jsのパッケージ管理ツールを利用しますのでNode.jsをインストールします。こちらからインストールして下さい。

LTS版(Long Term Supporting)という長期サポートしているバージョンの方が安定しているためそちらを選びます。

Node.jsをインストールするとnpmコマンドが利用できるようになります。

作業ディレクトリの作成

私は作業ディレクトリを次のディレクトリに作成しました。

/Users/●●●●●/Desktop/gulp-test

以降gulp-testディレクトリで作業をします。

package.jsonの作成

npm -y init

上記のコマンドを打って見てください。作業ディレクトリ内に「package.json」というファイルが作成されます。

package.jsonは作業ディレクトリで進めているプロジェクトでどのようなnodemodule(node.js製のパッケージ)を利用しているのか、製作者は誰なのか、などの情報が記載されています。

このpackage.jsonを共有することで開発に必要なパッケージが何か一目で分かります。

「-y」オプションを指定したので「package.json」には記載がされていません。適宜書いてください。

gulpとsassの導入

npm i -D gulp gulp-sass

上記のコマンドでgulpとgulp-sassをインストールしてください。

「i」は「install」の省略形で、「-D」オプションは「–save-dev」の省略形となります。

gulpやsassは開発用のツールであるため、「–save-dev」オプションでインストールします。

インストールすると「node_modules」配下に色々なパッケージと共に、「gulp」と「gulp-sass」がインストールされます。

これは「gulp」や「gulp-sass」も他のパッケージを利用して作成されているためです。

gulpとは

gulpとはタスクランナーと呼ばれるツールです。つまり、いくつかのタスクをまとめて実行してくれます。

今回で言えば、

  1. sass→cssのコンパイル
  2. ES6以降→ES5へのトランスパイル
  3. ソースを変更したらブラウザをリロード
  4. ベンダープレフィックスを自動でつける

これらのタスクをまとめて行ってくれるようにします。

gulpfile.js

作業ディレクトリ直下(私の場合gulp-test/)にgulpfile.jsというファイルを作成してください。現状のディレクトリは次のようになっています。

gulpfile.jsに実行するタスクを記載していきます。

const gulp = require('gulp')

gulp.task('sass', () => {
    const sass = require('gulp-sass')
    return gulp
        .src('./src/scss/*.scss')
        .pipe(sass())
        .pipe(gulp.dest('./dist/css'))
})

 

requireで「nodemodules/gulp/bin/gulp.js」を読み込み、gulpのオブジェクトを生成します。同様に「gulp-sass」のオブジェクトも生成します。

そして「gulp.task('タスク名', '実行する関数')」でタスクを作成します。

gulp.src()」で「./src/scss」の拡張子がscssファイルを読み込みます。

pipe()で繋げる事により、読み込みファイルのストリームを渡すことができます。読み込みんだストリームをsass()で処理し「scss→css」へのコンパイルが完了します。

コンパイル後のファイルを書き出すために、gulp.dest('書き出し先')で書き出します。

  1. srcでファイルの読み込み
  2. pipeでストリームをバケツリレー
  3. destで書き出し

scss→cssのコンパイル

先ほど作成したタスクを実行します。

npx gulp 任意のタスク名

npxコマンドで「./node_modules/gulp/bin/gulp.js」を実行します。

タスクに付けた名前が「sass」でしたので

npx gulp sass

で実行することができます。

「./src/scss/style.scss」を作成しておけば、「./dist/css/style.css」が作成されます。

ベンダープレフィックスの自動化

次のパッケージをインストールします。

npm i -D gulp-postcss postcss-cssnext

PostCSSというものを利用します。これはCSSを解析するツールです。

今回の場合ですと、「scss→css」後のcssをPostCSSで解析し、ベンダープレフィックスを自動で付けて欲しい訳です。そのためにPostCSSを利用します。

cssnextとは次世代のcssを利用するためのもので、ES6→ES5にトランスパイルするような仕組みです。

これらを利用してベンダープレフィックスの自動化を行います。

const gulp = require('gulp')

gulp.task('sass', () => {
    const sass = require('gulp-sass')
    const cssnext = require('postcss-cssnext')
    const postcss = require('gulp-postcss')
    const processors = [cssnext({ browsers: ['last 2 version'] })]//最新の2version対応
    return gulp
        .src('./src/scss/*.scss')
        .pipe(sass())
        .pipe(postcss(processors))//scss→css後のcssファイルを解析しcssnext
        .pipe(gulp.dest('./dist/css'))
})

次のようなscssファイルを作成しました。

.sample{
    display: flex;
}

コンパイル後は次のようになりました。

.sample {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex; }

自動でベンダープレフィックスがついています。

Babelの導入

npm i gulp-babel @babel/core @babel/preset-env -D

Babelを利用するためにbabel本体(babel/core)、gulpでbabelを利用するためのもの(gulp-babel)、環境に対応したトランスパイルを行うもの(babel/preset-env)をインストールします。

次のようにgulpfileを追記します。

gulp.task('babel', () => {
    const babel = require('gulp-babel')
    return gulp
        .src('./src/js/*.js')
        .pipe(babel())
        .pipe(gulp.dest('./dist'))
})

「./src/js」のjsファイルをトランスパイルし、「./dist/js」ディレクトリに書き出します。

npx gulp babel

上記のコマンドでトランスパイルが実行できます。

ブラウザ自動ロード

npm i -D browser-sync

ブラウザを自動でロードしてくれるパッケージ「browser-sync」をインストールします。

次のようにgulpfileに追記しました。

const browserSync = require('browser-sync').create()

gulp.task('serve', done => {
    browserSync.init({
        server: {
            baseDir: './dist',
            index: 'index.html',
        },
    })
    done()
})

gulp.task('watch', () => {
    const browserReload = done => {
        browserSync.reload()
        done()
    }

    gulp.watch('./dist/**/*', browserReload)
})

gulp.task('default', gulp.series('serve', 'watch'))

「watch」というタスクを作成しました。gulp.watch('監視するディレクトリ', '関数')で「./dist/**/*」に変更があればブラウザをリロードするように

「serve」というタスクを作成し、browserSyncのオブジェクトの初期化をします。

「default」というタスクを作成し、「serve」で初期化後に「watch」で監視するようにタスクを作成しました。

「./dist/index.html」を作成してください。このHTMLファイルにはbodyタグを作成してください。そうしないと自動ロードが反応しません。

npx gulp

このコマンドで「default」という名前のタスクが実行されます。index.htmlが変更されるとブラウザが自動でロードされていることがわかります。

全てのタスクを繋げる

これまでのタスク

  1. sass→cssのコンパイル
  2. ES6以降→ES5へのトランスパイル
  3. ソースを変更したらブラウザをリロード
  4. ベンダープレフィックスを自動でつける

を一連のタスクとします。

次のように「watch」タスクに追記します。

gulp.task('watch', () => {
    const browserReload = done => {
        browserSync.reload()
        done()
    }
    gulp.watch('./dist/**/*', browserReload)
    gulp.watch('./src/scss/*.scss', gulp.series('sass'))//追記
    gulp.watch('./src/js/*.js', gulp.series('babel'))//追記
})

作成した「sass」タスクと「babel」タスクを登録しました。

これで「src」のscssファイルやjsファイルを保存すると、コンパイル後のファイルがdist/に書き出されます。distに変更があったことを検知してブラウザの自動ロードは走ります。

最終的なgulpfile.jsは次です。

const gulp = require('gulp')
const browserSync = require('browser-sync').create()

gulp.task('sass', () => {
    const sass = require('gulp-sass')
    const cssnext = require('postcss-cssnext')
    const postcss = require('gulp-postcss')
    const processors = [cssnext({ browsers: ['last 2 version'] })]
    return gulp
        .src('./src/scss/*.scss')
        .pipe(sass())
        .pipe(postcss(processors))
        .pipe(gulp.dest('./dist/css'))
})

gulp.task('babel', () => {
    const babel = require('gulp-babel')
    return gulp
        .src('./src/**/*.js')
        .pipe(babel())
        .pipe(gulp.dest('./dist'))
})

gulp.task('serve', done => {
    browserSync.init({
        server: {
            baseDir: './dist',
            index: 'index.html',
        },
    })
    done()
})

gulp.task('watch', () => {
    const browserReload = done => {
        browserSync.reload()
        done()
    }
    gulp.watch('./dist/**/*', browserReload)
    gulp.watch('./src/scss/*.scss', gulp.series('sass'))
    gulp.watch('./src/js/*.js', gulp.series('babel'))
})

gulp.task('default', gulp.series('serve', 'watch'))

またpackage.jsonは次です。

{
  "name": "gulp-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    "browser-sync": "^2.26.3",
    "gulp": "^4.0.0",
    "gulp-babel": "^8.0.0",
    "gulp-postcss": "^8.0.0",
    "gulp-sass": "^4.0.2",
    "postcss-cssnext": "^3.1.0"
  },
  "dependencies": {}
}

まとめ

gulpでいくつかのタスクを自動化する事を行いました。

全てはパッケージを作成してくれた人に感謝ですね。ありがたく使わせて頂きます。

何か自分もOSSに貢献したいという気持ちになりますね。貢献できるように毎日勉強を続けたいと思います。