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 コンポーネントを定義しているだけです
~~~
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でページごとにファイルを分割する
ありがとございます
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) の設定
変更前
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
変更後
chunk の名前設定をしてあげる
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