Vue + TypeScript + Babel + Bulma + webpackで作るSPAでレスポンシブなフロント開発5(ビルド編)

# リンク
- [開発環境構築編](https://qiita.com/va034600/items/a62238666149bcd9e719)
- [開発ツール編](https://qiita.com/va034600/items/c968b9f524f5d3127b93)
- [JavaScript Framework編](https://qiita.com/va034600/items/f203ea7a423967d5023c)
- [CSS Framework編](https://qiita.com/va034600/items/8541a076a9d3d140162f)
- [ビルド編](https://qiita.com/va034600/items/919ce3fa330f87f2a277)

[前回](https://qiita.com/va034600/items/8541a076a9d3d140162f)で一通り開発ができるかと思います。
最後に説明するのがビルドです。
開発ではビルド必要はないのですが、
本番ではビルドをする必要があるのでその説明を。

ソースはこちら
[github](https://github.com/va034600/sample-html/tree/master/project-base3)

# gulpfile.js

```javascript:gulpfile.js
var requireDir = require('require-dir');
var runSequence = require('run-sequence');

requireDir('./gulp/tasks', { recurse: true });

var gulp = require('gulp');

gulp.task('build-js', function (callback) {
    runSequence('webpack-build', callback);
});

gulp.task('build-css', function (callback) {
    runSequence('compile-scss', 'import-css', 'minify-css', callback);
});

gulp.task('build',function (callback) {
    runSequence('clean-dist', 'build-js', 'build-css', 'copy-dist', callback);
});

gulp.task('live', ['webpack-dev-server-live']);
```

この例の場合、タスク(gulp)は以下のように指定できます。

```sh
$ gulp build
$ gulp build-js
$ gulp build-css
$ gulp live
```

gulp buildはbuild-jsとbuild-cssを呼びます。それぞれjavascriptとcssを作ります。
作成されたファイルをnginx等webサーバに置く必要があります。
gulp liveはビルドされたjavascriptとcssを読み込んでいます。

```javascript
gulp.task('build-js', function (callback) {
```

gulp.taskの第１引数'build-js'はタスクを起動するためのキーです。
今回の場合、gulpfile.js内、もしくはgulp/tasksディレクトリにあるjsファイル内にタスクは定義されています。

```
└── gulp
    └── tasks
        ├── clean-dist.js
        ├── compile-scss.js
        ├── copy-dist.js
        ├── import-css.js
        ├── minify-css.js
        ├── webpack-build.js
```

## ビルド時に使うタスク

本番環境ではビルドされたファイル(javascript、css)が必要になります。
ビルドのために複数のタスクを使います。

buildのタスクの流れは`clean-dist -> build-js -> build-css -> copy-dist`となります。

## clean-dist

clean-distタスクは`dist`ディレクトリを削除するタスクです。
`dist`ディレクトリにはコンパイルされたファイルが出力されます。
二度目の時のためにとりあえずワークディレクトリを削除しておこうってことです。

```javascript:clean-dist.js
var gulp = require('gulp');
var del = require('del');

gulp.task('clean-dist', function(callback) {
    return del(['./dist'], callback);
});
```

## webpack-build

webpack-buildタスクはTypeScriptをコンパイルして、`dist/js-min`にjavascriptとして出力します。
設定はwebpack.config.build.jsに記述しています。

```javascript:webpack-build.js
var gulp = require('gulp');
var gulpWebpack = require('webpack-stream');
var webpack = require('webpack');

gulp.task('webpack-build', function() {
    var config = require("../../webpack.config.build.js");

    return gulp.src(config.entry.main)
        .pipe(gulpWebpack(config, webpack))
        .pipe(gulp.dest('./dist/js-min'));
});
```

## webpack.config.build.js

```javascript:webpack.config.build.js
const webpack = require('webpack');
var path = require('path');

var config = {
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].min.js',
    },
    resolve: {
        extensions: [".ts", ".vue", ".js"],
        modules: ['node_modules', 'src/main/html', 'src/main/js', 'src/lib/js', 'src/main/ts', 'src/lib/ts'],
        alias: {
            vue: 'vue/dist/vue.common.js'
        }
    },
    module: {
        rules: [
            {
                test: /\.vhtml$/,
                loader: 'vue-template-loader'
            },
            {
                test: /\.ts$/,
                use: [
                    {
                        loader: 'babel-loader'
                    },
                    {
                        loader: 'ts-loader'
                    }
                ]
            }
        ]
    },
    plugins:[
        //引数
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify("production")
        }),
        // 圧縮
        new webpack.optimize.UglifyJsPlugin(),
        // 重複モジュール削除
        new webpack.optimize.DedupePlugin(),
    ]
};

config.entry = {
    //mainファイルを作成する。複数作れば複数作られる。
    main: [
        'babel-polyfill',
        'isomorphic-fetch',
        'url-search-params-polyfill',
        "./src/main/ts/main.ts"
    ],
};

module.exports = config;
```

UglifyJsPluginやDedupePluginで出力されるjavascriptを小さく(難読化も)しています。

## compile-scss

compile-scssはSASSファイルをコンパイルしてcssにします。

```javascript:compile-scss.js
var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('compile-scss', function(callback) {
    return gulp.src('./src/main/scss/**/*.scss')
        .pipe(sass())
        .on('error', function(err) {
            console.log(err.message);
        })
        .pipe(gulp.dest("./dist/css-source"));
});
```

## import-css

import-cssはcssファイル内でimportを使っている場合、ファイルを結合します。

```javascript:import-css.js
var gulp = require('gulp');
var cssimport = require('gulp-cssimport');

gulp.task('import-css', function (callback) {
    return gulp.src('./dist/css-source/**/*.css')
        .pipe(cssimport({
            matchPattern: "*.css" // process only css
        }))
        .pipe(gulp.dest('./dist/css-import/'));
});
```

## minify-css

minify-cssはcssファイルをスペース、改行などを削除してコンパイルされたcssファイル自体を小さくします。

```javascript:minify-css.js
var gulp = require('gulp');
var minify = require('gulp-minify-css');
var rename = require('gulp-rename');

gulp.task('minify-css', function () {
    return gulp.src('./dist/css-import/**/*.css')
        .pipe(minify({
            processImport:false
        }))
        .pipe(rename({
            suffix: '.min'
        }))
        .pipe(gulp.dest('./dist/css-min/'));
});
```

## copy-dist

copy-distはコンパイルされたjavascript、cssを`dist`ディレクトリから必要なファイルを公開ディレクトリの`webRoot/dist`にコピーしてます。

```javascript:copy-dist.js
var gulp = require('gulp');

gulp.task('copy-dist', function(callback) {
    return gulp.src([
        'dist/css-min/index.min.css',
        'dist/js-min/main.min.js'
    ])
        .pipe(gulp.dest('webRootLive/dist'));
});
```

## index-build.html

index-build.htmlは`webRoot/dist`に出力されたされたファイル(index.min.css、main.min.js)を表示するためのファイルです。
想定としては本番用のhtmlファイルかと思ってください。

```javascript:webRoot/index-build.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/dist/index.min.css">
</head>
<body>

<div id="navigation"></div>
<div id="app"></div>
<div id="footer"></div>

<script src="/dist/main.min.js" type="text/javascript"></script>

</body>
</html>
```

# 最後に

これで一通りの説明が終わりました。
モダンなフロントって最初が難しいと思います。
どのライブラリを選択していいかわからないし。。。
その一構成の例として参考にしていただけると幸いです。

ではまた。

[github](https://github.com/va034600/sample-html/tree/master/project-base3)