EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

webpackを使ったVue.jsのモジュール開発

前回の続きで、今度はクライアント側でVue.jsを使い、前回作ったNode.jsのAPIからデータを取得して表示するページを作りたいと思います。

eatsmart.hatenablog.com

インストール

まず、プロジェクトのフォルダを作り、初期化します。

$ npm init

次に、webpack系のライブラリをインストールしました。

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

その次に、Vue.jsをインストールしました。

$ npm i --save vue

その後、css系のライブラリと、js系のライブラリをインストールしました。 vue-loaderは最新版をインストールすると、

vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

というエラーが出て、こちらhttps://github.com/symfony/webpack-encore/issues/311を参考に、ver14を使うようにしました。

# vue
$ npm i -D vue-loader@14 vue-template-compiler css-loader sass-loader
# babel
$ npm i -D babel-loader @babel/core @babel/preset-env babel-preset-es2015
# ajax通信用
$ npm i -D axios

設定

まず、開発用サーバーとビルドの設定をpackage.jsonに追加します。

  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "dev": "webpack-dev-server --hot",
+    "build": "webpack -p"
  },

次に、webpack用の設定ファイル(webpack.config.js)を作成します。

module.exports = {
    // エントリポイントとなるファイル
    entry: './src/index.js',
    // ビルド先設定
    output: {
        filename: 'bundle.js',
        path: `${__dirname}/dest`,
    },
    module: {
    // ローダー設定
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.(css|sass|scss)$/,
        loader: 'sass-loader',
      },
    ]
  },
  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
    },
  },
  // 開発サーバ設定
  devServer: {
    contentBase: 'dest',
  },
}

実装

いよいよVue.jsでの実装ですが、まずエントリポイントとしてsrcフォルダのindex.jsを以下のようにしました。 componentsフォルダのTimeineの内容を#appに出力します。

import Vue from 'vue'
import Timeline from './components/Timeline'

new Vue({
    el: '#app',
    components: { Timeline },
})

次に、src/componentsフォルダのTimeline.vueファイルに実体を実装します。

Vue.jsではHTMLのtemplateとjsの処理を同一ファイルに記述します。 jsの処理としては、APIサーバーからtimelineの一覧を取得し2件表示し、「もっと見る」で2件づつ追加するようにします。

  • はじめにAPIサーバーから一覧を取得する
  created:function(){
    var items = this.items;
    axios.get(ENDPOINT_TIMELINE_LIST+'?name='+this.name)
    .then(function(res) {
      for(var i=0;i<res.data.length;i++){
        items.push(res.data[i]);
      }
    });
  },
  • 「もっと見る」の処理
  computed:{
    showCount:function() {
      return this.first + this.count * this.step;
    },
    hasMore:function() {
      return (this.showCount < this.items.length);
    }
  },
  methods: {
    more:function() {
      this.step++;
    }
  }
}
  • 処理をバインドするテンプレート
<template>
<div class="snsWrap">
  <div class="feedBox" v-for="(item, index) in items">
    <span v-show="index < showCount" v-html="item"></span>
  </div>
  <button v-if="hasMore" v-on:click="more">もっとみる</button>
</div>
</template>

確認

開発サーバーはnpm run devで起動できます。

$ npm run dev

> timeline@1.0.0 dev /XXXXX/XXXX
> webpack-dev-server --hot

ℹ 「wds」: Project is running at http://localhost:8081/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from dest
⚠ 「wdm」: Hash: 8fa2fd3d7a6fca1710e3
Version: webpack 4.20.2
Time: 1760ms
Built at: 2018-10-06 17:20:11
    Asset     Size  Chunks                    Chunk Names
bundle.js  254 KiB       0  [emitted]  [big]  main
Entrypoint main [big] = bundle.js

・・・

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
  bundle.js (254 KiB)

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
  main (254 KiB)
      bundle.js

と起動でき、ブラウザでhttp://localhost:8081/にアクセスする事で、動作の確認ができました。

ビルド

jsファイルのビルドは、npm run buildでできます。

$ npm run build

> timeline@1.0.0 build /XXXXX/XXXX
> webpack -p

Hash: d77cd19e816f5c62ca5c
Version: webpack 4.20.2
Time: 3393ms
Built at: 2018-10-06 18:33:39
    Asset     Size  Chunks             Chunk Names
bundle.js  104 KiB       0  [emitted]  main
Entrypoint main = bundle.js
 [1] (webpack)/buildin/global.js 509 bytes {0} [built]
[31] ./src/index.js + 4 modules 5.5 KiB {0} [built]
     | ./src/index.js 129 bytes [built]
     |     + 4 hidden modules
    + 30 hidden modules

となり、destフォルダにbundle.jsが出力されます。

最終的に、コンテンツのHTMLにbundle.jsを組み込む事で、以下のページができました。

mognavi.jp

まだ理解できていなくてオマジナイ的な所も多いですが、とりあえずシンプルな形での実装ができました!