Gulp4 x webpack で Vue.js の開発環境を作る

Gulp4 x webpack で Vue.js の開発環境を作る

Vue.jsGulpWebpack

Vue.js を必要に迫られて久々に触りましたが、拡張性の高さと柔軟性にビビりまくってます笑

最近さらにコンポーネント化し、あれこれ拡張しなければなりませんでした。結構タスクランナーなどに頼らずに制作するのは限界があるなぁと思い、Gulp と webpack を使って改めて開発環境を作りました。

今回は Gulp と webpack を使った Vue.js の実務で使える実践的な開発環境の作り方をご紹介します。

手軽にVue.jsを導入する方法はこちらです。

Vue.js で絞込み&ソート機能を部分的に組み込む

Vue.js はちょっとした動的機能をHTMLやPHPに組み込むのに最適。Vanilla JS に比べると簡潔に書けるし...

この記事を書いた人

かみーゆ/フロントエンドエンジニア

資金ゼロからフィリピンで起業した海外ノマドエンジニア。IT業界10年以上でテクニカルディレクター(技術責任者)・エンジニア講師・ブリッジSEを経てLenzTechnologies Inc.を設立し、代表を務める。CMS concreteCMSエバンジェリスト。テックブログ以外も「磨耗しない人生」や「海外ノマド」のライフスタイルについて発信。好きなものは肉とハイボール。

前提条件

  • Gulpの使い方がわかる
  • Webpackを使ってVue.jsのファイルをバンドル(まとめる)したい
  • Vue.jsのコンポーネントを使いたい
  • Node や npm をインストールしていて、コマンドが使える状態
  • コマンドの使い方がある程度わかっている
  • Compostion API を使いたい

今回は丁寧に順を追って説明します。「そんなの知ってるよ」って方は目次から必要な項目をすっ飛ばしてお読みください。

Gulp で webpack を使った環境を準備する

今回は Gulp を使った開発方法のご紹介です。webpack-stream を使って webpack を読み込む方法をご紹介です。

まずはディレクトリを作成し、そこでコマンドで package.json を新規で作ります。

コマンド
npm init -y

-y オプションを付けることで、対話せずに package.json が作成されます。

作成したら、いくつか node module をインストールします。

コマンド
npm -D gulp browser-sync

それぞれの node module の役割です。

モジュール名役割
gulpJavaScriptで記述できるビルドシステム。SassやJSをリアルタイムでコンパイルできるようになる
browser-sync仮想サーバーを立てたり、コード更新とともにブラウザをリロードできるので作業効率化できる

今回はディレクトリ構造は以下のようにします。

vue-sample/(ルートディレクトリ)
  ├ node_modules/(自動生成)
  ├ gulpfile.js(新規作成)
  ├ package.json(自動生成)
  ├ package-lock.json(自動生成)
  └ public/
    └ index.html(とりあえず空でオッケー)

gulp コマンドが使えるように package.json を編集します。scripts にコマンドを追加します。

package.json
{
  "name": "vue-practice",
  "version": "1.0.0",
  "description": "Sample for VUE sort Articles.",
  "main": "index.js",
  "scripts": {
    "start": "gulp"  },
  "devDependencies": {
    "browser-sync": "^2.27.11",
    "gulp": "^4.0.2",
    "webpack": "^5.75.0",
    "webpack-stream": "^7.0.0"
  }
}

browserSync で心地よい開発環境を作る

gulpfile.js を追加し、まずはローカルにサーバーを立てます。

gulpfile.js
const { parallelh } = require("gulp");

const browserSync = require("browser-sync").create();

const paths = {
  root: "public/",
};

const serverTask = () => {
  browserSync.init({
    server: {
      baseDir: paths.root,
    },
    reloadDelay: 1000,
    open: false,
    startPath: '/',
  });
}

exports.default = parallel(serverTask);

空でいいのでHTMLファイルを作ります。以下コマンドで http://localhost:3000/ にアクセスできたら成功です。

コマンド
npm start

browserSync のオプション open ですが、サンプルコード通り false を付与することをおすすめします。付与しないと初期値は true になっており、gulp を起動するたびにブラウザが開くので鬱陶しいです。

webpack でコードをバンドル(まとめる)できる環境を作る

次にコードをまとめる環境を作ります。コードをまとめる方法は、直接 gulpfile.js に書く方法もありますが、今回は別ファイル webpack.config.js を新たに作成します。

vue-sample/(ルートディレクトリ)
  ├ node_modules/
  ├ gulpfile.js(編集)  ├ webpack.config.js(新規作成)  ├ package.json
  ├ package-lock.json
  ├ js/
  | └ index.js(新規追加)  └ public/
    ├ js/
    | └ index.min.js(index.jsがバンドルされて自動生成)
    └ index.html

Vue.js を npm 経由でインストールします。

コマンド
npm i vue webpack webpack-stream path -D
モジュール名役割
vueVue.js を使えるようにする
webpack複数のファイルを1つにまとめて出力してくれるツール。gulp に近い機能がたくさんあるので webpack 単独でも使える
webpack-streamgulp で webpack を使うためのモジュール
pathディレクトリやファイルのパス(場所)の問題を解決するモジュール

gulpfile.js に Vue.js をコンパイルするためのコードを追加。

gulpfile.js
const { dest, parallel, watch } = require("gulp");
// 省略
const path = require("path");const webpack = require("webpack");const webpackStream = require("webpack-stream");
const paths = {
  root: "public/",
  js: "public/js/",  webpackConfig: "./webpack.config.js",};
// 省略
const vueCompile = () => {  const webpackConfigPath = path.resolve(__dirname, "webpack.config");  delete require.cache[webpackConfigPath];  const webpackConfig = require(webpackConfigPath);  return webpackStream(webpackConfig, webpack).on("error", function() {    this.emit("end");  })  .pipe(dest(paths.js));  .pipe(browserSync.stream())}// ファイルの変更をウォッチ
const watchTask = ()=> {
  return watch([paths.js+ '*.js', paths.js+ 'components/*.vue'], vueCompile);}
exports.default = parallel(serverTask, vueCompile);

webpack.config.js で node module にインストールした Vue.js を使えるようにし、JS をバンドルして出力できるようにします。

webpack.config.js
module.exports = {
  entry: "./js/index.js",
  mode: "development",
  output: {
    filename: "index.min.js"
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm-browser.prod.js'
    }
  }
}

コードをバンドル(まとめる)するメリット

この記事では.veu形式のファイルを分解して、JSにまとめるためにファイルをバンドルする方法を紹介していますが、バンドルするメリットは他にもあります。

JSのコードをバンドルすると、単純に一回のリクエストで1つのJSファイルを読み込めるので、読み込みコストを減らすことができます。

js/index.js では webpack 経由で vue を呼び出し、module 形式でコードを書く。

js/index.js
import {
  createApp,
  ref,
  onMounted,
} from 'vue';
// 省略

ファイルは type="module" で呼び出す。

public/index.html
<script src="./js/index.min.js" type="module" defer></script>

これで Vue.js とバンドルされたJSが生成されるようになります。

拡張子、.vue形式のコンポーネント(部品)を使えるようにする

Vue.js の素晴らしいところはコンポーネント(部品)化して管理できるところです。

Vue.js のコンポーネントは一般的に **.vue という拡張子のファイルに分けて管理します。

コンポーネントファイルの構成は出力したいテンプレートのコードと、それに関する設定といった感じになります。

コンポーネント
<template>
<!-- 部品の構成 -->
</template>
<script>
//コンポーネントに関する設定
</script>

せっかくなので Gulp の開発環境で便利なコンポーネントを使えるようにしましょう。

**.vue を分解して、jsコードとバンドルできるよう、vuebabel のローダー用 node module をインストールします。

コマンド
npm i babel-loader vue-loader -D
webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  entry: "./js/index.js",
  output: {
    filename: "index.min.js"
  },
   module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        exclude: /node_modules/,
        options: {
          loaders: {
            js: 'babel-loader'
          }
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm-browser.prod.js'
    }
  },
  plugins: [
    // make sure to include the plugin!
    new VueLoaderPlugin()
  ]
}

たとえば components/Label.vue ファイルを追加してコンポーネントとして使う場合、以下のような形で呼び出せるようになります。

js/index.js
import {
  createApp,
  ref,
} from 'vue';

import Label from './components/Label.vue'
const app = createApp({
  components:{ Label },  setup() {
    // 省略
  }
})

これで、 **.vue 形式のコンポーネントを使えるようになります。

詳しいテンプレートの実装方法に関しては以下記事で紹介しています。

コンポーネント(部品)間で、複雑なデータの受け渡しをする【Vue3】

Vue.js でコンポーネント(部品)を作成する方法をご紹介します。開発環境準備、親から子、子から親へのデータ受け渡し方...

vueファイルのコンパイルでコケる

.vue拡張子のついたファイルのコンパイルでコケる場合は、ファイルパスそのものの記述が間違っていたり'./components/Label'のように、拡張子を省略してい可能性があります。拡張子を省略したい場合は webpack.config.js 側に記述を足すだけで解決できます。


module.exports = {
  resolve: {
    extensions: ['.vue', '.js', '.json']
  }
}

プロダクション(製品版)とディベロップメント(開発版)で出力を分ける

webpack では mode を設定することで、 production(リリースモード)development(開発モード) とコンパイルしたファイルを出し分けることができます。

もちろん 開発モード のほうが遥かにエラー箇所を見つけやすくデバッグに適しリリースモード になるとソースはぐっとコンパクトに圧縮 することができます。

今回は、せっかくなので開発モードとリリースモードで分けて開発できるようにします。

コマンドに引数を渡せる minimist という node module をインストールします。

コマンド
npm -D minimist
webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')

const minimist = require("minimist");const envSettings = {  string: "env",  default: {    env: process.env.NODE_ENV || "development", // NODE_ENVに指定が無い場合のデフォルト  },};const options = minimist(process.argv.slice(2), envSettings);const isProduction = options.env === "production" ? true : false;
module.exports = {
  mode: isProduction ? "production" : "development",  entry: "./js/index.js",
  output: {
    filename: "index.min.js"
  },
   module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        exclude: /node_modules/,
        options: {
          loaders: {
            js: 'babel-loader'
          }
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm-browser.prod.js'
    }
  },
  plugins: [
    // make sure to include the plugin!
    new VueLoaderPlugin()
  ]
}

package.json にリリースモードに切り替えるコマンドを追加します。

package.json
{
  "name": "vue-practice",
  "version": "1.0.0",
  "description": "Sample for VUE sort Articles.",
  "main": "index.js",
  "scripts": {
    "start": "gulp",    "prod": "gulp --env production"  },
  // 省略
}

状況に応じてコマンドを出し分けます。

コマンド
# 開発者モード
npm start
# プロダクション
npm run prod

ソースサンプル

すべてのソースサンプルはこちらになります。

vue-sourt-sample Git

まとめ・少し複雑なVue.jsの実装をするためには開発環境の用意が必要

Vue.js はちょっとした機能を追加するにはめちゃ適しています。

が、その気軽に導入できるVue.jsですが少し手の混んだ実装をするためにはやはり開発環境の準備は必要と思いました。

必要に応じて、ある程度の開発環境は作れたほうがいいと思いその方法をまとめました。

この記事が皆さんのコーディングライフの一助となれば幸いです。

最後までお読みいただき、ありがとうございました。

コンポーネントを使ったデータバインドについてはこちらをお読みください。

コンポーネント(部品)間で、複雑なデータの受け渡しをする【Vue3】

Vue.js でコンポーネント(部品)を作成する方法をご紹介します。開発環境準備、親から子、子から親へのデータ受け渡し方...