14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

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

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

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

環境設定他関連記事はこちら
Laravel + Vue + Vuetify で業務サイト作ってみる

vue-router の設定

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

変更前

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

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 して vue-router.resolve しときます
 こちらを参考にさせていただきました
 Qiita - webpackのrequire.ensureでDynamic Loadingをして大規模アプリケーションを作る
 vue-router webpackでページごとにファイルを分割する
 ありがとございます

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) の設定

変更前

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

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

変更後

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

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: アプリケーションコード


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

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

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

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

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

14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?