新規立ち上げのチームを異動して、1年前に作った会社のフロントエンド環境(Vue.js + webpack(+Gulp))をベースに環境を作っていたのですが、
色々古かったので、新しくしました
今回作ったものはGitHubにあげてます
https://github.com/kurosame/vuejs-boilerplate
この中からやったことをいくつかピックアップして紹介したいと思います
パッケージを最新にする
npm install -g npm-check-updates
npm-check-updates -u // package.jsonのパッケージを全て最新にして上書く
npm update // package.jsonに記載してあるバージョンに更新する
npm install
今回みたいにバージョンアップするパッケージが多い場合は、これでいいと思う
他のパッケージに依存しているパッケージがあったとしたら、一緒に上げないと意味ないかもしれないので
Gulpをやめる
webpackを使っていれば、Gulpはいらないっていう話ではなく、
今のプロジェクトに関しては不要かなっていう判断をした
主に以下のGulpタスクが動いていた
・バンドルファイルの変更を検知して、browser-sync
を使ってブラウザをリロードしてるタスク
・unit testのkarmaを動かすタスク
・コードの変更をwatchするタスク
・webpack-stream
を使ってコードをバンドルするタスク
・dist内を全部削除するタスク
・assetsをdistにコピーするタスク
全てnpm-scripts + webpack + webpack-dev-server
で置き換えれるので、これを機に置き換えた
変更箇所を抜粋すると以下のような感じになる
"scripts": {
"start": "webpack-dev-server",
"build": "webpack",
"test": "NODE_ENV=test karma start karma.conf.js"
}
const Copy = require('copy-webpack-plugin')
const Clean = require('clean-webpack-plugin')
devServer: {
contentBase: 'dist',
historyApiFallback: true,
open: true,
port: 8000,
proxy: {
'/api/*': 'http://mock.example.jp:8001'
}
},
plugins: [
// assetsをコピー
new Copy([
{
from: 'assets',
to: 'assets'
}
]),
// distを綺麗にする
new Clean(['dist/**/*'], {
root: `${__dirname}/..`,
verbose: false
})
]
コード静的解析の強化
1年前
yarn add --dev eslint-config-vue eslint-plugin-vue
"extends": "vue"
eslint-plugin-vue
を導入した当初はたぶんあまりルールが厳しくなく、
必要なルールを後から追加していくというのを考えていたが、結局あまりやらなかったので、
今回は初めからきついルールにして後からルールを減らしていく方式に変えた
それが次のページ
ちなみにeslint-plugin-vue
がVue.jsのESLintの公式パッケージらしいので、
1月1日にリリースされたv4.0.0を今後使うかもしれません
現在
yarn add --dev eslint-config-airbnb-base prettier eslint-config-prettier eslint-plugin-prettier
"extends": ["airbnb-base", "prettier"],
"plugins": ["prettier"]
ルールが厳しいAirbnbのルールにした
後、コードフォーマッタになるのですがPrettierを導入
eslint-config-prettier
やeslint-plugin-prettier
を入れているのはESLintとPrettierが競合するのを防ぐ為に入れてる
これらのプラグインを設定してあげることで、ESLintのルールとしてPrettierを追加できる
(これをやらないとたぶんPrettierで直されたコードがESLintに引っかかるという無限ループに陥るので。。笑)
また、IDEやエディタがPrettierに対応していたら、是非設定してみてください
私はVSCodeを使っているので、以下のプラグインを入れてます
Prettier - Code formatter
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
上記プラグインをインストール後、VSCodeの設定で以下を追加
"editor.formatOnSave": true,
"prettier.eslintIntegration": true
保存する度に.eslintrc
の設定をみて、コードフォーマッタをかけてくれるので
めちゃめちゃ快適にコード書けます!
Babelを新しくする
babel-preset-es2015
とかはもう廃止されるはずなので、今更ですがbabel-preset-env
に変えた
1年前
"presets": ["es2015", "stage-2"]
ES2015のstage-2(Draft)の文法も使いたい(使ってるのでトランスパイルしてほしい)という設定になる
ブラウザが既にサポートされている文法であっても全てES5に変換している
現在
"presets": [
[
"env",
{
"targets": {
"browsers": ["last 2 versions", "IE 11"]
},
"modules": false,
"useBuiltIns": true
}
]
]
targetsでブラウザのバージョンを指定している
そのバージョンのブラウザで既にサポートされているES文法であれば、ES5へのトランスパイルは行われない
> 5% in JP
browsersオプションでは上記のように日本でシェア5%より大きいブラウザに限定っていう細かい指定も可能
ちなみにオプションを指定しないとES2015以降全ての変換を行うことになる
補足
babel-preset-env
とかbabel-polyfill
とかbabel-plugin-transform-runtime
とかの違い
babel-preset-env
が行うのは文法の変換のみ
オプションのtargetsに指定したブラウザにそもそも無い機能については、importする必要がある
それを実現するのがbabel-polyfill
これをimportすればブラウザでサポートされていない機能を補填してくれる
エントリーポイントに指定しているJSとかで以下のようにimportする必要がある
import 'babel-polyfill'
先程の.babelrc
の設定で"useBuiltIns": true
としていたが、
これをtrueにしておくとブラウザが対応していない機能のみimportすることができる
ただし、コード内で使ってなくてもブラウザが対応していない機能であればimportする
babel-plugin-transform-runtime
について
コード内で新しい機能を見つけたらES5に変換するプラグイン
ブラウザが既に対応している機能でも変換してしまう
"plugins": ["transform-runtime"]
で、どれ使うの?
http://kangax.github.io/compat-table
これ見たら分かると思いますが、モダンブラウザの中ではほぼIEの為にあるようなもの
話が逸れますが、
IE対応による懸念って、IE用に個別実装が必要だから別途工数かかるよねって思ってる人が多い気がしますが
実際今紹介したライブラリのおかげでIE用に実装する部分はほとんどないです
本当の懸念はIEが無ければ必要なかったbabel-polyfill
による機能のimportや、もしくはbabel-plugin-transform-runtime
を使用することによるパフォーマンス低下です
今後IE対応をするか否かを判断する機会があれば、IEで一部の人は助かるけど、その代わりに全体の質が落ちるかもよってのを意識してもらえると良いと思います
ちなみにVue.jsに関してを言えばv3以降はIEをサポートしません
https://medium.com/@gustojs/vuejs-3-and-other-top-news-from-q-a-event-with-core-vue-devs-c9834946ae7b
個人的には現状は
IE対応が必要な場合は、babel-plugin-transform-runtime
を使う
IEが捨てれるならbabel-polyfill
を使う
っていう感じで考えてますが
babel-plugin-transform-runtime
がどの程度パフォーマンスに影響するかにもよると思います
あまり影響がなければ、babel-plugin-transform-runtime
でもありかなと思います
babel-preset-env
2.0.0について(現在β版)
"useBuiltIns": "usage"
という設定が追加される
ブラウザが対応していない機能のpolyfillを自動でimportするため、
コード内でbabel-polyfill
をimportする必要がない(コードを変える必要がない)
フロントエンドのビルドを改善する
1年前
minify + vendor系をbundleから分ける
plugins: [
// minify
new webpack.optimize.UglifyJsPlugin(),
// node_modules配下をvendor.jsにする
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: module =>
module.resource &&
/\.js$/.test(module.resource) &&
~module.resource.indexOf('node_modules')
}),
]
上記のようにすることでminifyとbundle.jsからvendor系を別ファイル(vendor.js)として出力していた
このやり方だとbundle.jsは軽くなるが、フロントエンドのビルドが速くなるわけでない
現在
minify + DllPlugin
DllPluginとは
The DllPlugin and DllReferencePlugin provide means to split bundles in a way that can drastically improve build time performance.
この機能を使ってできることは、node_modules配下など開発中に変更があまり入らないモジュールを予めバンドルしておく(例えばvendor.jsとして)
そしてbundle.jsからは上記のバンドル済みのvendor.jsを参照することで、bundle.jsの軽量化とバンドル時間の短縮を実現する
vendor.jsとの依存関係はmanifestファイルを元にマッピングする
entry: {
vendor: ['axios', 'vue', 'vue-router', 'vuex', 'vuex-router-sync']
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
library: '[name]_library' // vendor_libraryという変数名でグローバルスコープに入れる
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new webpack.DllPlugin({
path: path.join(__dirname, 'dist', '[name]-manifest.json'), // manifestファイル出力先
name: '[name]_library'
})
]
// bundle.js用設定
plugins: [
// minify
new webpack.optimize.UglifyJsPlugin(),
// DllPlugin
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./dist/vendor-manifest.json') // manifestファイルへのパス
})
]
unit testの方もvendor.jsを読み込むのを忘れずに、、
以下はkarmaの場合の設定です
files: [
'./dist/vendor.js'
]
パフォーマンス検証
まだスタートアップしたばかりでコードが少なく、速度面は効果が見えづらいのですが、、
bundle.jsから丸々vendor系ライブラリが除かれるので、だいぶ軽くなりました
メリット
bundle.jsを軽くできる
フロントエンドのバンドルする速度を上げれる
デメリット
vendor系ライブラリを追加・更新した際に、予めvendor.jsをバンドルする手間が増える
vendor専用のwebpack.configを用意する必要がある
vendor専用のwebpack.configのentryに都度追加・削除する必要がある
チーム内でデメリットが許容できるなら、やってみても良いのではないでしょうか
TypeScriptで書いてみる
やってて解決に困った点とかは以下にまとめてます
https://qiita.com/kurosame/items/3c28f45c8b2e65f5c69d
メリット:
JavaScriptと書き方がほとんど変わらず書ける(Vue.js 2.5以降)
ランタイムエラーになっていたものがコンパイルエラーで検知できるようになった
IDEの補完やエラー検知がJavaScriptより優れている
デメリット:
TypeScript用の環境構築や設定ファイルが必要
バンドル速度がだいぶ落ちた(たぶんTSLintのTypeCheckのせい)
型定義が無いライブラリは型定義を自作するか、他の類似ライブラリを検討する必要がありそう
次やること
・avoriaz使ってUIのテスト書く
もしくはvue-test-utils(現在β版)を使って書く
・E2Eテスト書く
2018/06/22追記
Vue.jsのユニットテストとE2E関連は以下記事にまとめました
https://qiita.com/kurosame/items/8d82ef8d36c106c6e8bc