Try   HackMD

Laravel Vue组件分割,動態加載组件

環境

使用 webpackVite

發現問題

laravel 上開發 Vue 時,往往會將所有組件都註冊在 app.js 上,這樣在加載時會一次載入所有組件,導致 client side 網頁加載時間變長,影響使用者體驗。

動態引入

laravel-mix(4.0.16) 開始,開始支援動態引入 (Dynamic Import)。動態引入是一種 code splitting,可以將單一的 bundle 切分成多個塊 chunk,可搭配平行載入或在需要時才載入,或是對一些不常變動的 chunk 個別做快取,以達到載入效能的優化。這是 Lazy Loading(等用到的時候再載入)的一種實現。

解法

Vue2解法

配置

可以選擇設定webpack.mix.js.babelrc檔案擇一即可

webpack.mix.js配置

webpack.mix.js加上以下這行程式碼,laravel-mix必須是4.0.16版本以上

mix.babelConfig({ plugins: ['@babel/plugin-syntax-dynamic-import'], });

.babelrc檔案設置

根目錄新增.babelrc 檔案或是修改,將 @babel/plugin-syntax-dynamic-import 加到 「plugins」 這個array裏面,在啟用laravel-mix時就會自動引入

{ "plugins": [ "@babel/plugin-syntax-dynamic-import" ] }

使用動態引入

原先引入Vue組件是使用static import方法引入

import ExampleComponent from "./components/ExampleComponent.vue"; Vue.component("example-component", ExampleComponent);

將其更改為Dynamic Import

寫法一

通過使用特殊註釋語法提供塊名稱來使用命名塊(需要 webpack > 2.4),加入/* webpackChunkName: "example" */,為塊命名,不然在run devrun prod檔案名稱會不相同。

const ExampleComponent = () => import(/* webpackChunkName: "example" */ "./components/ExampleComponent.vue"); Vue.component("example-component", ExampleComponent);

寫法二

Vue.component("example-component", () => import(/* webpackChunkName: "example" */ "./components/ExampleComponent.vue"));

vue router

const routes = [ { path:"/home", component: ()=>import(/* webpackChunkName: "example" */ './components/ExampleComponent'), }, ];

更改塊存放位置

可以設置webpack.mix.js更改塊(chunks)存放的位置

mix.webpackConfig({ output:{ chunkFilename: 'js/chunks/[name].js', publicPath: '/', } });

編譯

npm run dev 或是 npm run watch

後記

可以看到在還未分割檔案前app.js的容量較大,分割後多了其他組件的jsapp.js也縮水了

切割前:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

切割後:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

也只需要加載app.jslaravel-mix會去解決按需要才載入問題

Vue3 and inertia解法

動態引入Page vue

修改app.js

import { createApp, h } from 'vue'; import { createInertiaApp } from '@inertiajs/inertia-vue3'; const app = createInertiaApp({ title: (title) => `${title} - ${appName}`, // 原先寫法 // resolve: (name) => require(`./Pages/${name}.vue`), // 更改後 resolve: (name) => import(/* webpackChunkName: "[request]" */`./Pages/${name}.vue`), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .mixin({ methods: { route } }) .mount(el); }, });

結果

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →