STEP15：Laravel5.7 + Vue2.5 でVueコンポーネント（ページ）毎にJSファイルを分割する

Laravel-mix と Webpackと vue-router でVueコンポーネント（ページ）毎にJSファイルを分割する

通常ではVueコンポーネントをコンパイルすると複数のVueファイルが app.js に集約されます

これだと一般ユーザに不要な管理者ソースを見せることになるし
そもそもファイルがでかくなって読み込みも遅い
使わないソースを最初に一気に読み込むのは効率が悪いってことで
必要になった時に必要なページのJSファイルを読み込むように設定しておきます

具体的にはVueコンポーネント毎にJSファイルを作成するようにLaravel-mix(Webpack)を設定
Vue-Routerが必要になった時に必要なJSファイルを読み込むようにします




環境設定他関連記事はこちら
[Laravel + Vue + Vuetify で業務サイト作ってみる](https://qiita.com/nobu-maple/items/d1e7170d62ab07890a7a)





# vue-router の設定

必要になった時に読み込むように設定

### 変更前

routes にあらかじめ定義しておいたvue コンポーネントを定義しているだけです

```javascript:resources/js/router/index.js
～～～

import home              from '../components/HomeComponent.vue'
import admin_user        from '../components/Admin/UserComponent.vue'
import admin_payslip     from '../components/Admin/PayslipComponent.vue'
import admin_actlog      from '../components/Admin/ActlogComponent.vue'

export default new Router({
  mode: 'history',
  routes: [
    { path: '/admin/user',   name: 'admin_user',    component: admin_user,    meta: {name: '社員管理', icon: 'supervisor_account'}},
    { path: '/home',         name: 'home',          component: home,          meta: {name: 'ホーム',   icon: 'home'}},
    { path: '/admin/payslip',name: 'admin_payslip', component: admin_payslip, meta: {name: '給与明細', icon: 'fa-file-invoice-dollar'}},
    { path: '/admin/actlog', name: 'admin_actlog',  component: admin_actlog,  meta: {name: '操作履歴', icon: 'list'}},

～～～

```

### 変更後

動的に読み込むように [webpack require.ensure](https://webpack.js.org/guides/code-splitting/#dynamic-imports) して [vue-router.resolve](https://router.vuejs.org/ja/api/#router-resolve) しときます
　こちらを参考にさせていただきました
　Qiita - [webpackのrequire.ensureでDynamic Loadingをして大規模アプリケーションを作る](https://qiita.com/RyotaSugawara/items/0effa7ce42adfcb66a35)
　[vue-router webpackでページごとにファイルを分割する](https://zukucode.com/2017/04/vue-router-webpack-chunk.html)
　ありがとございます




```javascript:resources/js/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

//
import example_component from '../components/ExampleComponent.vue'
import admin_component   from '../components/AdminComponent.vue'
import r_link            from '../components/RouterLink.vue'

//
Vue.component('example-component', example_component)
Vue.component('admin-component', admin_component)
Vue.component('r-link', r_link)

//
import home              from '../components/HomeComponent.vue'

export default new Router({
  mode: 'history',
  routes: [
    { path: '/home',          name: 'home',          component: home,          meta: {name: 'ホーム',   icon: 'home'}},

    { path: '/admin/actlog', name: 'admin_actlog',   meta: {name: '操作履歴', icon: 'list'},
      component: resolve => { require.ensure(['../components/Admin/ActlogComponent.vue'], () => {
                              resolve(require('../components/Admin/ActlogComponent.vue'))
                            }, 'js/admin_actlog') }},
    { path: '/admin/user',    name: 'admin_user',   meta: {name: '社員管理', icon: 'supervisor_account'},
      component: resolve => { require.ensure(['../components/Admin/UserComponent.vue'], () => {
                              resolve(require('../components/Admin/UserComponent.vue'))
                            }, 'js/admin_user') }},
    { path: '/admin/payslip', name: 'admin_payslip', meta: {name: '給与明細', icon: 'fa-file-invoice-dollar'},
      component: resolve => { require.ensure(['../components/Admin/PayslipComponent.vue'], () => {
                              resolve(require('../components/Admin/PayslipComponent.vue'))
                            }, 'js/admin_payslip') }},

    { path: '*',             redirect: '/home' },
  ],
})

```



# Webpack(Laravel-mix) の設定


### 変更前

```javascript:webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');
```


### 変更後

chunk の名前設定をしてあげる

```javascript:webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css')
   .webpackConfig({
     output: {
       chunkFilename: '[name].chunk.js',
       publicPath: '/',
     },
   });
```


# コンパイル

ファイルがコンポーネント毎に分割された

```
$ npm  run  prod
 DONE  Compiled successfully
                                   Asset      Size  Chunks                    Chunk Names
                            /css/app.css   139 KiB       1  [emitted]         /js/app
                              /js/app.js  1.27 MiB       1  [emitted]  [big]  /js/app
                js/admin_actlog.chunk.js  5.29 KiB       2  [emitted]         js/admin_actlog
               js/admin_payslip.chunk.js  20.3 KiB       3  [emitted]         js/admin_payslip
 js/admin_payslip~js/admin_user.chunk.js  11.7 KiB       0  [emitted]         js/admin_payslip~js/admin_user
                  js/admin_user.chunk.js    11 KiB       4  [emitted]         js/admin_user

```

admin_payslip と admin_user で同じ子コンポーネント（components/Admin/CsvUpload.vue）を使っているため、共有JSができているようです


---

以上
Vueコンポーネント（ページ）毎にJSファイルの分割ができました



今回ついでにMixのextractメソッドでアプリとベンダーとも分けようかと
　※こんな感じ
　public/js/manifest.js: Webpackマニフェストランタイム
　public/js/vendor.js: ベンダーライブラリ
　public/js/app.js: アプリケーションコード


```javascript

mix.js('resources/js/app.js', 'public/js')
   .extract(['vue'])
```

なことをしてみたところ、app.css ファイルが ０バイトになってしまうという事象に遭遇しました

```
$ npm  run  dev
  /css/app.css   0 bytes
```


調べてみましたがちょっとすぐには解決できなそうだったので、.extract(['vue']) は今回見送りです。。
ちゃんとドキュメントやソースを読んで .extract(['vue']) が何をしているのか勉強しないとな。。




今回もソースはこちら
https://github.com/u9m31/u9m31/tree/step15