Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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()],
INOUEMASA
Web系エンジニア。GPT-3で遊んでいます。PHP、Laravel、JavaScript、IoTを経て、現在はTypeScript、Vue/Nuxt、Pythonでお仕事しています。 https://gpt-startup.netlify.app/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away