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


リンク

前回
サンプルソースを落として開発環境を構築、起動までを確認しました。
今回は開発環境で使う開発ツールのパッケージマネージャ(npm) タスクランナー(gulp) モジュール管理(webpack)の説明をします。

ソースはこちら
github

パッケージマネージャ

npm

ちょっと前まではbowerなどありましたが、今はこれが主流かなと。
npmで必要なファイルはpackage.jsonとなります。
package.jsonには開発、実行時に使用するライブラリが明記されていて、npm installを実行するときに使います。
実行するとnode_modulesにjsやscssなどのファイルをどこかしらからダウンロードします。package-lock.jsonも同時に生成されます。package-lock.jsonについてはとりあえず、なにかあるなぁくらい認識で。

package.json
{
  "name": "project-base3",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "author": "",
  "license": "",
  "devDependencies": {
    "babel-core": "6.21.0",
    "babel-loader": "6.2.10",
    "babel-preset-es2015": "6.18.0",
    "css-loader": "^0.28.10",
    "del": "^2.2.2",
    "gulp": "3.9.1",
    "gulp-cssimport": "^5.0.0",
    "gulp-uglify": "2.0.0",
    "gulp-rename": "^1.2.2",
    "gulp-sass": "3.1.0",
    "gulp-minify-css": "^1.2.4",
    "require-dir": "0.3.0",
    "run-sequence": "1.2.2",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.20.2",
    "ts-loader": "1.3.1",
    "typescript": "2.2.1",
    "vue-class-component": "5.0.1",
    "vue-loader": "12.0.4",
    "vue-template-compiler": "2.3.3",
    "vue-template-loader": "0.3.1",
    "webpack": "2.2.0",
    "webpack-dev-middleware": "1.9.0",
    "webpack-dev-server": "2.3.0",
    "webpack-hot-middleware": "2.15.0",
    "webpack-stream": "^3.2.0"
  },
  "dependencies": {
    "babel-polyfill": "6.23.0",
    "bulma": "0.6.1",
    "isomorphic-fetch": "2.2.1",
    "url-search-params-polyfill": "2.0.0",
    "vue": "2.3.3",
    "vue-router": "2.5.3",
    "vuex": "2.3.1",
    "vuex-router-sync": "4.2.0"
  }
}

devDependenciesは開発及びビルド時にdependenciesは実行時に必要となるファイルを明記します。

ライブラリを追加したい場合は以下のコマンドを実行します。

$ npm install bulma --save
$ npm install webpack --save-dev

--save,--save-dev(オプション)を追加するとpackage.jsonに追加されます。
--saveはdependenciesに、--save-devはdevDependenciesにそれぞれ追加されます。

タスクランナー

gulp

grunt、webpackでも代用ではありますが、今回はgulpで。

gulpfile.jsファイル

タスクを記述していきます。
タスクにはwebpack dev serverの起動、ビルドなどがあります。

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

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

var gulp = require('gulp');

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

gulpのタスク

defaultしかないのでわかりにくいですが、
この例の場合、タスク(gulp)は以下のように指定できます。

$ gulp
$ gulp default

webpack dev serverが立ち上がります。

└── gulp
    └── tasks
        └── webpack-dev-server.js

webpack dev serverの設定

設定はwebpack-dev-server.jsに記述していきます。

webpack-dev-server.js
var gulp = require('gulp');
var webpack = require("webpack");
var WebpackDevServer = require("webpack-dev-server");

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

gulp.task('webpack-dev-server', function(callback) {
    new WebpackDevServer(compiler, {
        contentBase:"webRoot",
        publicPath: webpackConfig.output.publicPath,
        hot: true,
        historyApiFallback: true
    }).listen(3000, "localhost", function(err) {
        if(err) throw new gutil.PluginError("webpack-dev-server", err);
        callback();
    });
});

軽く説明すると、contentBaseでルートディレクトリ(今回はwebRoot)を指定します。
実装するソースはTypeScript、SASSとなりますが、そのままではブラウザでは判読できないので、
javascript、cssにコンパイルしてからブラウザで読ませます。
開発時はコンパイルされたファイル(javascript、css)をwebpack dev server内のメモリ上に作成されて、物理的には作成されません。
その際のwebpack dev serverからの出力先をpublicPathで指定します。
今回の場合は以下のように出力されます。

http://localhost:3000/public/main.min.js
http://localhost:3000/public/style.min.js

historyApiFallbackがポイントです。
この設定がSPA環境、vue-routerでHTML5 historyモードで動作させるために必要な設定です。
この設定をすることで

http://localhost:3000/
http://localhost:3000/sample-button/

でアクセスしても同じwebRoot/index.htmlを参照します。
本番環境ではwebpack dev serverを使わず、nginxやspring mvc等でfallbackの設定するかと思います。

nginxの場合は。
conf:default.conf
location / {
root /usr/share/nginx;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}

spring mvcの場合は。

StartController.java
@Controller
@RequestMapping(value="/**")
    public class StartController extends BaseController {
}

詳しくはVue Router HTML5 History モードを参照してください。

webpack dev serverの設定

webpack dev serverの設定はwebpack.config.jsに記述しています。

webpack.config.js
const webpack = require('webpack');
var path = require('path');

var config = {
    devtool: "source-map",

    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].min.js',
        publicPath: "/public/"
    },
    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: /\.scss$/,

                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader'
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            },
            {
                test: /\.ts$/,
                use: [
                    {
                        loader: 'babel-loader'
                    },
                    {
                        loader: 'ts-loader'
                    }
                ]
            }
        ]
    },
    plugins:[
        new webpack.LoaderOptionsPlugin({
            debug: true
        }),
        new webpack.HotModuleReplacementPlugin()
    ]
};

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

module.exports = config;

source-map

source-mapは出力されたjavascriptからTypeScriptのファイルをデバッグするために使われます。
これでChromeやintellij(web storm)でTypeScriptファイルをデバッグできるようになります。

entry

TypeScriptのルートファイルを指定したらそのファイルを元にJavaScriptを作成します。
今回はmainのみになります。

test

testは一致したファイル(この場合は拡張子が.tsのもの)に各種loaderを当てていきます。

test: /\.ts$/,
use: [
{
    loader: 'babel-loader'
},
{
    loader: 'ts-loader'
}
]

ts-loader、次にbabel-loaderを使ってコンパイルします。
これでTypeScript->ES2015->ES5となります。

HotModuleReplacementPlugin

HotModuleReplacementPlugin はファイルを保存するたびにリロードするかと思いますが、画面全体をリロードするのではなく、修正したファイルのみリロードするようになります。

ささっとタスクランナーの説明をしました。
ビルドについてはまた後で説明します。
とりあえず、開発用までです。

jQueryから脱出したい人のためのなんとなくなフロント開発入門5(ビルド編)

モジュール管理

JavaScriptのモジュール管理とはブラウザのJavaScript(ES5)ではJavaScriptから別のJavaScriptを呼ぶ仕組みがないので、その仕組みを補うのがモジュール管理かなと。
今回はモジュール管理はwebpackを使います。

トランスパイル

.babelrc

.babelrcはBabelの設定ファイルです。
es2015でjavascript(今回はTypeScript)を書きますよ。的なやつです。

.babelrc
{
  "presets": ["es2015"]
}

tsconfig.json

tsconfig.jsonはTypeScriptの設定ファイルです。

tsconfig.json
{
  "compilerOptions": {
    "target": "es2015",

    "experimentalDecorators": true,

    "sourceMap": true,

    "allowSyntheticDefaultImports": true,
    "lib": [
      "dom",
      "es5",
      "es2015.promise"
    ],
    "module": "es2015",
    "moduleResolution": "node"
  }
}

TypeScriptをes2015で出力しますよかな。

TypeScriptでvueを使う場合の設定方法がTypeScript のサポートに書いてあります。

終わりに

開発ツール編はとりあえずここまでで。
まだ本題の実装に入っていません。
環境構築だけで相当な労力を使います。
初めての人はここまででも大変かと思います。

github