webpackでvueを使ったプロジェクトの作成

#webpackでvueを使ったプロジェクトの作成

Vue cliでプロジェクトを作成していたが、vuetifyを扱うにはlintのエラーが出るなど不具合があるため、webpackでvueを使ったプロジェクトを立ち上げる。


**＜目標＞**
vueテンプレートを使ったページをブラウザで開く。


<br>
##目次

1. [webpackのインストール](#webpackのインストール)
2. [VueとVue Loaderのインストール](#vueとvue-loaderのインストール)
3. [style-loaderとcss-loaderのインストール](#style-loaderとcss-loaderのインストール)
4. [必要なファイルの作成](#必要なファイルの作成)
    5. [distディレクトリとsrcディレクトリ](#distディレクトリとsrcディレクトリ)
    6. [dist/index.htmlの編集](#distindexhtmlの編集)
    7. [src/App.vueの編集](#srcappvueの編集)
    8. [src/index.js](#srcindexjs)
    9. [Vue.extendとは？](#vueextendとは)
    10. [webpack.config.jsの設定](#webpackconfigjsの設定)
11. [webpackのbuild](#webpackのbuild)
12. [開発サーバーの立ち上げ](#開発サーバーの立ち上げ)
13. [補助機能の作成と適用（utilファイル）](#補助機能の作成と適用utilファイル)



<br>
##webpackのインストール

```
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
```

<br>
この時点でツリーは以下のようになっている。

```:ツリー
  webpack-demo
  |- package.json
```


<br>
##VueとVue Loaderのインストール

```
#vueが未インストールの場合(最新の安定版)
$npm install vue

#vue-loaderのインストール
$npm install -D vue-loader vue-template-compiler
```

-g: グローバル
-D: devDependenciesでインストール（開発用）


・**vue-loader**
VueファイルをJSに変換するwebpackのloader。
webpackでVueを使うために必須。


・**vue-template-compiler**
vue2.0のテンプレートを描画するときに余計な処理を省き効率化するためのツール。vue-loaderと一緒に使う。

>[vue-template-compiler公式](https://www.npmjs.com/package/vue-template-compiler)
Vue2.0をrender関数に渡す際のプリコンパイルツール。コンパイルのオーバーヘッド（付随処理）や CSP restrictions(セキュリティによる余計な制限)を避ける。



<br>
##style-loaderとcss-loaderのインストール
webpackでcssの記述を読み込むためのパッケージをインストールする。

```
npm install -D style-loader css-loader
```

**・style-loader**
スタイルタグを読み込む。


**・css-loader**
cssファイルをJSにコンパイルする。


>※注 vue-style-loaderについて
style-loaderと似た機能で、vue-style-loaderが使われていたが、css-loader v4.0以降はサポートされていないためスタイルが適用されない。



<br>
##必要なファイルの作成

- dist > index.html
- src > components > App.vue
- src > index.js
- webpack.config.js

```:ツリー
├── dist
│   └── index.html
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── components
│   │   └── App.vue
│   └── index.js
└── webpack.config.js
```

###distディレクトリとsrcディレクトリ

**・srcディレクトリ**
編集用のファイル。ブラウザに表示したい内容をここのファイルに書き込んでいく。


**・distディレクトリ**
ブラウザ表示用のファイル。基本的に編集しない。
webpackのloaderがsrcのファイルを読み込んで自動出力する。


<br>
###webpack.config.js
大きく２つの役割がある。

**(1)読み込みファイルと出力ファイルの指定**
srcのどのファイルを読み込み、なんというファイル名でdistに出力するかを指定。

**(2)ツールやloaderの読み込み**
webpackにこのツールやloaderを使用しますと伝える。



<br>
##dist/index.htmlの編集
出力用のindex.htmlを編集して、vueテンプレートを表示できるようにする。

```html:index.html
<!doctype html>
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="main.js"></script>
  </body>
</html>
```




<br>
##src/App.vueの編集
Vueの一番のメインとなる単一ファイルコンポーネント（template、js、cssが一つになったもの）。

確認のため、dataとcomputedプロパティを設定し、データバインディングでブラウザに表示する設定にする。

```vue:App.vue
<template>
  <div class="app">
    Hello {{vue}} <br>
    {{myVar}}
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return{
        vue: "---This is Vue---"
    }
  },
  computed: {
    myVar() {
      console.log('MyVar')
      return 'This is my var'
    }
  },
}
</script>

<style scoped>
.app {
  font-size: 40px;
  color: blue;
}
</style>
```


styleにscopedをつけると、設定したCSSがこのファイルでのみ有効となる。



<br>
##src/index.js
編集内容を読み込む大元のファイルを編集する。
vueと、App.vueファイルをインポートする。


```js:index.js
import Vue from "vue"
import App from "./components/App.vue"

const VueApp = Vue.extend(App)

console.log('Hello!')

const app = new VueApp({
  el: '#app',
})
```


###Vue.extendとは？
コンポーネントを使えるようにする。（Vueを拡張して、サブクラスのコンストラクタを作成する[(公式)](https://012-jp.vuejs.org/guide/components.html)）

・`Vue.extend()`
カッコの中には、単一ファイルコンポーネントのソースコードが入る。

ここでは、コンポーネントファイルをimportで読み込んだものを使用。



<br>
##webpack.config.jsの設定

・読み込みファイルと出力先の指定
　┗ エントリーポイントとアウトプットの設定

・インストールしたloaderを使うことをwebpackに明示する。
vue loaderを使うためにはloaderの指定の他に、pluginの指定も必要。


```js:webpack.config.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // this will apply to both plain `.css` files
      // AND `<style>` blocks in `.vue` files
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    // make sure to include the plugin!
    new VueLoaderPlugin()
  ]
}
```

※注
style-loaderとcss-loaderの記述順序はとても重要。style-loaderが先にくること。（css読み込みして、コンパイルする流れのため）


記述は以下に従っている。
・[webpack公式 getting started](https://webpack.js.org/guides/getting-started/#using-a-configuration)



<br>
##webpackのbuild
ここまで作ってきたファイル群をリロードする。
`npx webpack`でも再構築できるが、よりわかりやすくするため、package.jsonにaliasを記述する。

```
  "scripts": {
    "build": "webpack --config webpack.config.js",
   },
```

・`--config ファイル名`
設定ファイルを指定してwebpackを再構築（ビルド）する。

```:buildの実行
npm run build


#実行結果（一部）
Entrypoint main = main.js
 [1] (webpack)/buildin/global.js 472 bytes {0} [built]
 [9] ./src/index.js + 6 modules 5.06 KiB {0} 
[10] ./node_modules/vue-style-loader/lib/addStylesClient.js + 1 modules 6.71 KiB {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
```

WARNINGが出るがここではOK。事項で設定する。


<br>
##開発サーバーの立ち上げ
localhostでページを起動するため、開発サーバーの設定をする。


###開発サーバーのインポート

```
npm install -D webpack-dev-server
```

`-D` = `--save-dev`　　
devDependenciesでインポート。 



<br>
###webpack.config.jsの編集
以下3点を追記する。

**(1) mode: 'development'**
開発モードであることを明示。誤って本番公開することを防ぐ。


**(2) devtool: 'inline-source-map'**
エラー発生時にファイルの詳細をconsoleに表示する。
これがないとbundleファイルでエラーが発生した場合にファイルの特定が難しい。

**(3) devServer:**
どのファイル群で開発サーバーを立ち上げるか指定する。公開用のファイルはdist配下。

```
   devServer: {
     contentBase: './dist',
   }
```



<br>
**▼設定内容（フル）**

```js:webpack.config.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist'
  },
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // this will apply to both plain `.css` files
      // AND `<style>` blocks in `.vue` files
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    // make sure to include the plugin!
    new VueLoaderPlugin()
  ]
}
```



###aliasの設定
package.jsonに開発サーバー立ち上げ用のコマンドを記載する。
環境設定ファイルを複数用いることも想定して、オプションでファイル名を指定する。

```json:package.json
    "scripts": {
        "serve": "webpack-dev-server --config webpack.config.js --open",
    }
```



###サーバーの立ち上げ
`npm run serve`で開発サーバーが立ち上がる。
localhost:8080

以下が表示されればOK。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/0a0ad501-5b99-a7d7-5af2-d1d6c25ec500.png)|
|:--|




<br>
##補助機能の作成と適用（utilファイル）
ここまでで表示ができたので、応用として別途作成したファイルを読み込んで適用させる。

src > lib > util.js　というファイルを作成して読み込む。

###ファイルの作成

```:tree
├── src
│   ├── components
│   │   └── App.vue
│   ├── index.js
│   └── lib
│       └── util.js
```

console.logに簡単な内容を表示するプログラムを記述。

```js:util.js
console.log('util.js!!')
```


###App.vueの編集
App.vueファイルでこのファイルを読み込む。
読み込むタイミングは適用したいvueのライフサイクルを指定する。

今回はmountedを使用して遅延ロードを行う。
定数を指定してファイルをインポートする。5秒後に実行させるためsetTimeoutを使用。（setTimeoutなしの場合は指定ファイルをすぐに実行）

```js:
mounted(){
      setTimeout(() => {
      const util = import('../lib/util')
    }, 5000)
  },
```

[vueにおける遅延ロードの方法](https://router.vuejs.org/ja/guide/advanced/lazy-loading.html)



**▼script(フル)**

```vue:App.vue
<script>
export default {
  name: "App",
  data(){
    return{
        vue: "---This is Vue---"
    }
  },
  mounted(){
      setTimeout(() => {
      const util = import(/* webpackChunkName: "my-util" */'../lib/util')
    }, 5000)
  },
  computed: {
    myVar() {
      console.log('MyVar')
      return 'This is my var'
    }
  },
}
</script>
```

5秒後にconsoleに表示されればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/8661fbce-e90c-0d1d-fe87-267615379492.png)



<br>
##参考リンク
以下の内容を参考にプロジェクトを作成する。

・webpack：[公式ページのgettig started](https://webpack.js.org/guides/getting-started/)
・Vue Loader: [公式ページのマニュアルインストール](https://vue-loader.vuejs.org/guide/#vue-cli)