概要

最近のフロントエンドの開発では、CSSやJavaScriptをそのまま書くのではなく、SassやAltJSと呼ばれるようなものを使い、別な言語で書いたものをそれぞれトランスパイラというものを使って、CSSやJavaScriptに変換していること多いです。

この変換のことをトランスパイルと言います(コンパイルとも呼ばれますが、トランスパイルという言い方の方が正確です)。

そこで、現在私が取り入れている、タスクランナーのgulpとモジュールバンドラのwebpackを組み合わせた開発環境の構築方法を紹介します。

タスクランナーとは

タスクランナーとは、ファイルの変更などを監視してそのファイルに処理を加えるものです。

なので今回の場合、SassやTypeScriptが書かれたファイルの変更を監視して、変更があったら、トランスパイルするという使い方をします。

タスクランナーとして有名なものには、Grantやgulpがありますが、Grantは最近使われることが減っているようで、タスクランナーとしては、gulpの方が現在使われているようなので、今回はgulpを使います。

モジュールバンドラとは

モジュールバンドラとは、JavaScriptなどのコードで、機能ごとなど、コードをモジュールとして分けておいた場合に、そのモジュールを連結(バンドル)して、ひとつまたは複数のファイルとして出力するものです。

このときに、状況によってはトランスパイルをします。

モジュールバンドラにはいくつかありますが、今回は人気の高いwebpackを使用します。

構成

実はwebpackには、タスクランナーの機能があります。

そういうことなので、gulpを使わずにwebpackだけでも目的を達成することができます。

しかし、私が使ってみた感想として、webpackは元々JavaScript用のため、JavaScript以外のCSSなどでトランスパイルをしようとすると、非常に設定が面倒に感じました。

そして、設定も複雑になってしまいました。

なので、JavaScript関係のトランスパイラの部分はwebpackに任せますが、それ以外のCSSなどのトランスパイラやタスクランナーの部分はgulpに任せてしまった方が、設定をしたときに、分かりやすくなったので、そのような方法を紹介します。

ちなみに、私はTypeScriptをトランスパイルしてJavaScriptを生成しているので、webpackを使ってTypeScriptをJavaScriptにトランスパイルします。

注意として、webpackのバージョンは3系です。それ以外のバージョンを使っていると、設定が、うまくいかない可能性が高いです。

環境

gulpやwebpackは、npmパッケージとして提供されているので、今回はnpmパッケージを使用します。

他にも、いくつかの方法で提供されているので、そちらを使っても構いません。

その場合は、インストールの方法が変わるので気をつけてください。

gulpとwebpackのインストール

npmのインストールは済んでいるものとして、まず、gulpとwebpackのインストールをします。

npm install --save-dev gulp webpack

パッケージのインストール時にpackage.jsonの開発用の所にパッケージの情報を書き込むために、--save-devを書いていますが、必要がない場合は使わなくても大丈夫です。

webpackの設定

webpackは、どのファイルをトランスパイルするのかという情報を設定ファイルから読み込んでいます。

なので、webpackを使うにはその設定ファイルを用意する必要があります。

設定はJavaScriptで記述し、ファイル名はなんでもいいのですが、ここではwebpack.config.jsという名前でファイルを用意します。

今回は、TypeScriptをトランスパイルしてJavaScriptにするので、このような設定となります。

module.exports = {
  entry: {
    app: './typescript/app.ts',
  },
  output: {
    path: `${__dirname}/script/`,
    filename: '[name].js'
  },
  resolve: {
    extensions: ['*', '.webpack.js', '.web.js', '.ts', '.tsx', '.js']
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: 'ts-loader'
      }
    ]
  }
}

entry:の部分には、トランスパイルするTypeScriptのファイルを指定します。このとき、app: './typescripts/app.ts'としてapp:というものをつけておく理由は、次のoutput:でトランスパイルした結果の出力場所を指定する際に、filename: '[name].js'のように[name]のところが、entry:で指定したapp:`で置き換えられるためです。

output:path:は出力するディレクトリを指定しますが、、これはgulpの方でwebpackを呼び出す際に上書きするので、一応指定していますが、使われることはありません。

resolve:は、トランスパイルの対象となるファイルの拡張子を指定します。

一番重要なのは、module.rulesloaderの部分で、ここでどのようにトランスパイルするのかを指定します。

今回の場合、ts-loaderというものを使って、TypeScriptをJavaScriptに変換しています。

これだけでは、ts-loaderのパッケージがインストールされていないので、実際に使うにはインストールする必要があります。

npm install --save-dev typescript ts-loader

ts-loaderは、内部的にtypescriptパッケージを呼び出すので、typescriptもインストールします。

さらに、TypeScriptの設定を用意します。設定ファイルの名前はtsconfig.jsonです。

これによって、どのJavaScriptのバージョンでトランスパイルするのかを指定できます。

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs"
  },
}

targetのところを、状況に応じて書き換えてください。この場合、ECMAScript 5 でJavaScriptが作成されます。

gulpの設定

では、gulpの設定をしていきます。

gulpの設定は、gulpfile.jsという名前で、JavaScriptで書きます。

まず、gulpからwebpackを呼び出す設定を書きます。

var gulp = require('gulp');
var plumber = require('gulp-plumber');
var webpackStream = require('webpack-stream');
var webpack = require('webpack');

var webpackConfig = require('./webpack.config');

gulp.task('ts', function () {
    gulp.src('')
        .pipe(plumber())
        .pipe(webpackStream(webpackConfig, webpack))
        .pipe(gulp.dest('script'));
});

gulpでは、gulp.task()という形式で、実際のタスクを記述するので、このように書きました。

重要なのは、var webpackStream = require("webpack-stream")var webpack = require("webpack")の部分です。これらを使ってgulpからwebpackを使用します。

実際にwebpackのタスクを実行しているのは、pipe(webpackStream(webpackConfig, webpack))のところです。

webpackConfigは、var webpackConfig = require("./webpack.config")のように、webpackの設定ファイルであるwebpack.config.jsの場所を指定します。

gulpのタスクの最後でpipe(gulp.dest('script'))というものがあります。これは、このdestで設定した場所にwebpackでトランスパイラしてできたファイルが置かれます。

ちなみに、pipe(plumber())というのは、webpackの実行に失敗したとき、gulpで実行している他のタスクまで終了してしまうので、plumberというものを使って、webpackの実行に失敗しても、gulpのタスクが止まらないようしています。

gulp-plumberwebpack-streamなどは、インストールしないと使えないのでインストールします。

npm install --save-dev gulp-plumber webpack-stream

さらに、SCSSをトランスパイルするための設定を追加します。

var gulp = require('gulp');
var plumber = require('gulp-plumber');
var webpackStream = require('webpack-stream');
var webpack = require('webpack');
var sass = require('gulp-sass');

var webpackConfig = require('./webpack.config');

gulp.task('ts', function () {
    gulp.src('')
        .pipe(plumber())
        .pipe(webpackStream(webpackConfig, webpack))
        .pipe(gulp.dest('script'));
});

gulp.task('sass', function () {
    gulp.src('sass/app.scss')
        .pipe(plumber())
        .pipe(sass())
        .pipe(gulp.dest('style'));
});

pipe(sass())でgulp.srcに指定したファイルをトランスパイルします。

pipe(plumber())は、webpackの時と同じように、途中でエラーが発生した時に、他のタスクまで終了しないようにしています。

pipe(gulp.dest('style'))で結果の出力先を指定します。

ちなみにファイル名は、gulp.srcに指定したファイルの拡張子をcssに変えたものとなります。

こちらも、sassをトランスパイルするためのパッケージを追加する必要があります。

npm install --save-dev gulp-sass

最後に、gulpの実行時に実行するタスクの設定と、ファイルの変更を監視する設定を追加します。

var gulp = require('gulp');
var plumber = require('gulp-plumber');
var webpackStream = require('webpack-stream');
var webpack = require('webpack');
var sass = require('gulp-sass');

var webpackConfig = require('./webpack.config');

gulp.task('ts', function () {
    gulp.src('')
        .pipe(plumber())
        .pipe(webpackStream(webpackConfig, webpack))
        .pipe(gulp.dest('script'));
});

gulp.task('sass', function () {
    gulp.src('sass/app.scss')
        .pipe(plumber())
        .pipe(sass())
        .pipe(gulp.dest('style'));
});

gulp.task('watch', function() {
    gulp.watch('typescript/*.ts', ['ts']);
    gulp.watch('sass/*.scss', ['sass']);
});

gulp.task('default', ['ts', ts]);

gulpの実行時に実行するタスクは、gulp.task('default', …)で設定し、ファイルの変更を監視するのは、gulp.task('watch', …);で設定します。

gulp.task('watch', …);の方は、gulp.watch()で監視するファイルの指定と、変更があった時に実行するタスクの指定をしています。

実行

では、TypeScriptとSassをトランスパイルする設定を書き終わったので、実際にgulpを使って実行してみましょう。

現在のファイルの構成はこのようになっているものとします。

--- gulpfile.js
 |- tsconfig.json
 |- webpack.config.js
 |- node_modules/
    |- ……
    |- ……
 |- sass/
    |- app.scss
 |- style/
 |- typescript/
    |-- app.ts

場合によっては、node_modulesがないこともあります。

実行は、gulpfile.jsがある場所でします。

npmパッケージを--save-devをつけてインストールした場合は、次のコマンドで実行します。

./node_modules/.bin/gulp

これで実行できない場合は、次のコマンドで実行します。

gulp

これだけだと、ファイルの監視がされないので、ファイルの監視をするようにするには、コマンドにwatchをつけます。

./node_modules/.bin/gulp watch

または、このようにします。

gulp watch

このようにした場合、Ctrl(コントロール)キーとCキーを同時に押してgulpを止めるまで、ずっとファイルの監視を続けます。

まとめ

以上のような流れで、gulpとwebpackを使ってSassとTypeScriptをトランスパイルする環境を作ることができました。

覚えてしまえば、それほど難しいことではないですが、覚えるまではwebpackの設定ファイルの書き方が分からなかったり、gulpからwebpackを呼び出した時に結果の出力場所がおかしなことになったりと大変でした。

今回やったことは、gulpを使わずにwebpackだけでもできますが、やはりgulpとwebpackの両方を使った方が分かりやすい思います。

適材適所で、使い分けるもしくは組み合わせて使っていきましょう。