【2018年】Webpack4でVue.js単一ファイルコンポーネントの作り方

2019/05/12

現在の所、以下の内容はすでに時代遅れの可能性があるので、実際にコンパイル可能か保証出ません。



tl;dr

vue単一ファイルコンポーネント用の環境を用意しました。

サンプルをgithubにアップしていますので、git cloneなどして中身などを御覧ください。

(個人的には)最低限の構成をしています。

devinoue/webpack-vue-sample


やりたかったこと

Vue.jsでアプリケーションを作っていたところ、あまりにmethodsプロパティに多くを詰め込みすぎたため、そろそろ1ファイルに書き出すのは無理だと判断。フロントエンド界隈では標準ツールと言われるWebpackに手を出してみました。

自分は普段はPHPを中心に仕事をしているため、Webpackのようなファイルバンドラの経験がなく、せいぜいLaravel経由でMixを利用するぐらい。

Laravel使わなきゃバンドラを使えないんじゃダメなので、ひとまず以下のページを参照しながらWebpackをインストールしました。

最新版で学ぶwebpack 4入門 – JavaScriptのモジュールバンドラ

こちらのページであっさりとバンドルできました。便利ですね。

あとはVueもちょっと検索かければ簡単でしょう。


Vue-loaderを使えばいい……というわけではない。

「Vueはドキュメント多いよ」みたいな話をたくさん聞いていたので、あっさりとVueの単一ファイルコンポーネントをバンドルする方法のページが見つかりました。

たしかにドキュメントはたくさんあるのですが、動かない。エラーが出る。


エラー1 プラグインが設定されてない

エラーメッセージは以下の通りです

ERROR in ./src/components/App.vue

Module Error (from ./node_modules/vue-loader/lib/index.js):
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

 

エラーがでる理由はvue-loader使用するに当たり、新たにプラグインが必要になったから。

過去の記事ではそれが記述されていないので、コピペではダメでした。

これはvue公式ページでも書かれています。

https://vue-loader.vuejs.org/migrating.html#a-plugin-is-now-required

ということで、プラグインの記述を追加


webpack.config.js


const { VueLoaderPlugin } = require('vue-loader');
//(省略)
plugins: [new VueLoaderPlugin()],



エラー2 Babelが動かない


ERROR in ./src/index.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module '@babel/core'
babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'd like to use Babel 6.x ('babel-core'), you should install 'babel-loader@7'.

 

もう一度npm runしてみるも、またエラーが出ます。

どうもbabel-loaderとBabel coreのパッケージのバージョンが合ってない、と言いたいようです。

babel-loaderのバージョンとBabelのバージョンは揃って開発されているわけではなく、

loader 8 と Babel6では互換性がありません。

一方loader 8とBabel7ならイケると。

Module build failed (from ./node_modules/babel-loader/lib/index.js)

そして、Babel7がリリースしたのは2018年8月になってからなので、去年の記事はもう古くなっているかも、ということになってしまいます。

一番大きな変更点は、パッケージ名が変更されたことで、npmによるインストールも変わったということです。

旧・npm install babel-core babel-preset-es2015 -D

新・npm install @babel/core @babel/preset-env -D

これによりpackage.jsonや.babelrcの表記も変わってしまう。

参考 Babel 7 リリースプレビュー


ちょっとしたまとめ

vueのバンドルは簡単かなぁなどと思っていましたが、色々とバージョンアップのため予想以上に時間がかかりました。

ただ今まで使っては来ませんでしたが、こんな便利なものがあるんだなぁという発見にも繋がりました。

今回インストールしたパッケージをまとめておきます。

■WEBPACK関連

npm i -D webpack webpack-cli webpack-dev-server

■Babel関連

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

■vue.js関連

npm i -S vue

npm i -D vue-loader vue-template-compiler

■スタイルシート、SASSなど

npm i -D sass-loader node-sass style-loader css-loader

■もし万一すでにBabel関連をインストールしていたら事前にアンインストールしたほうがいいかもしれません。

npm uninstall -D babel-core babel-preset-env babel-loader webpack @babel/polyfill

なお、Babel関連も色々書き換え必須です。

以下重要そうな部分だけ書き出しますが、詳細はgithubからクローンして見た方が早いかもしれません。


.babelrc

{

"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
}


webpack.config.js

    module: {

rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(scss|css)/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// オプションでCSS内のurl()メソッドの取り込みを禁止する
url: false,
// ソースマップ
sourceMap: true,

// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader
importLoaders: 2
},
},
{
loader: 'sass-loader',
options: {
// ソースマップ
sourceMap: true,
}
}

]
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
plugins: [new VueLoaderPlugin()],