vuetify-loader 不止用在vuetify,在其他vue工程中,一样好用
参考地址 用 vuetify-loader 提升 Vue 开发体验
好久沒寫文章,心血來潮發一篇
重點先放三遍
不用 Vuetify 也可以用 vuetify-loader 哦
不用 Vuetify 也可以用 vuetify-loader 哦
不用 Vuetify 也可以用 vuetify-loader 哦
const vuetify = 'vue' + 'buetify'
現在已經有許多基於 Vue 的 UI 框架、元件庫都提供方便易用且客製化的方案,
從 Vuetify 的命名可以看到是為了美化 Vue 而存在,美化範圍不只限於 UI,也包含程式碼和開發體驗。
今天主要和大家分享 vuetify-loader
如何提升 SFC
開發體驗。
如果你也思考過以下問題,你可以考慮使用 vuetify-loader
來少寫一些程式碼。
你寫了很多共用的元件,且在專案中被頻繁地使用
該如何確保被棄用的元件,在建置時不會被打包
如何用命名規範來管理元件
重複且頻繁的在專案各處引入相同的元件
舉例來說,專案中有一個 BaseButton
這個基本的按鈕元件,當我在不同的元件中使用時會是這樣:
PageA.vue
<template> <base-button>Click me!</base-button> </template>
import BaseButton from '@/components/BaseButton' export default { components: { BaseButton } }
這個作法很普通,但是當有十個頁面時就需要引入 10 次 BaseButton
,並且加入到 components
物件中
隨著這樣的 UI 元件慢慢變多,一個頁面就需要引入一堆基礎元件,犧牲的就是前端工程師的開發體驗,下面舉個例:
PageB.vue
<template> <base-button>Click me!</base-button> <base-tooltip></base-tooltip> <base-input></base-input> <base-alert></base-alert> <base-container> <base-layout> <base-flex> ... </base-flex> </base-layout> </base-container> </template>
import BaseButton from '@/components/BaseButton' import BaseTooltip from '@/components/BaseTooltip' import BaseInput from '@/components/BaseInput' import BaseAlert from '@/components/BaseAlert' import BaseContainer from '@/components/BaseContainer' import BaseLayout from '@/components/BaseLayout' import BaseFlex from '@/components/BaseFlex' export default { components: { BaseButton, BaseTooltip, BaseInput, BaseAlert, BaseContainer, BaseLayout, BaseFlex } }
同樣的道理,有十個以上的頁面,每個頁面都要引入這麼多基礎元件時,犧牲的就是前端工程師的開發體驗。
這也衍生一個問題,當我要移除 BaseButton
這個元件時,不只要移除在 template 中的
<base-button>Click me!</base-button>
同時也要移除 script 中的
import BaseButton from '@/components/BaseButton'
components: { BaseButton }
如果我忘了移除 js 中的引用,
此時專案若有使用 Eslint,他可能會好心的提醒你:
The "BaseButton" component has been registered but not used.eslint(vue/no-unused-components)
萬一不幸的事情發生了,我沒有使用 Eslint,又忘了移除 script 中的引用,就「可能」會在無形中增加了專案的 bundle size。
看到這裡有些人可能想到不錯的解決辦法
將共用元件註冊為全域元件,避免不斷重複引入元件
時常看到的解決範例:
main.js
import Vue from 'vue' import BaseButton from '@/components/BaseButton' import BaseTooltip from '@/components/BaseTooltip' import BaseInput from '@/components/BaseInput' import BaseAlert from '@/components/BaseAlert' import BaseContainer from '@/components/BaseContainer' import BaseLayout from '@/components/BaseLayout' import BaseFlex from '@/components/BaseFlex' Vue.component('BaseButton', BaseButton) Vue.component('BaseTooltip', BaseTooltip) Vue.component('BaseInput', BaseInput) Vue.component('BaseAlert', BaseAlert) Vue.component('BaseContainer', BaseContainer) Vue.component('BaseLayout', BaseLayout) Vue.component('BaseFlex', BaseFlex)
這方法相比在各處不斷地引用基礎元件有更好的開發體驗,也讓開發專案時可以更多的專注在商業邏輯上
但是這並沒有辦法主動
避免棄用的元件在建置時不小心被打包的問題
如果 BaseButton
是一個被棄用的元件,我需要在專案中透過全域搜尋 BaseButton
或 base-button
,確認沒有任何地方用到這個元件後,回到 main.js 移除以下兩行代碼:
import BaseButton from '@/components/BaseButton' Vue.component('BaseButton', BaseButton)
同樣的問題是如果我忘了移除,那 BaseButton
元件就「肯定」會增加專案的 bundle size,並且不會有 Eslint 的提示。
那有沒有方法或工具能同時兼顧開發體驗、專注開發商業邏輯,又能避免棄用元件建置時被打包呢?
本文的重點 vuetify-loader
vuetify-loader 是一個 webpack 的套件,用於自動引用 Vuetify 的元件
可以參考 vuetify-loader 文件的 Automatic Imports。
很少有 UI 框架自帶 tree shaking 功能的,這也是我喜歡 Vuetify 的原因之一
你可以在設置 webpack plugins new VuetifyLoaderPlugin
時,帶入 match
函式,
所有的元件中的每一個 tag 會執行一次 match
函式,參數有:
originalTag: tag 如何被使用的,例如
<base-button>Click me!</base-button>
就會是base-button
kebabTag : 將 originalTag 轉為 kebab-case
camelTag : 將 originalTag 轉為 PascalCase
path : SFC 的相對路徑
component : 該 tag 所在的那個元件被解析後的物件,主要包含 SFC 的三個區塊 (template, script, style)
可以根據這些參數組合出適合專案的自動引入元件功能
match
需要回傳一個長度為 2 的陣列:
第一個元素會被插入在該元件的 components
屬性中
第二個元素為自動引用該元件的路徑
以下用 Vue CLI 3 建立的專案做為範例:
vue.config.js
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin') module.exports = { configureWebpack: { plugins: [ new VuetifyLoaderPlugin({ match (originalTag, { kebabTag, camelTag, path, component }) { if (kebabTag.startsWith('base-')) { return [camelTag, `import ${camelTag} from '@/components/${camelTag}.vue'`] } } }) ] } }
這邊解釋一下上面這段程式碼的效果
我用 BaseButton
做舉例:
如果在 PageA.vue 中使用
<template> <BaseButton>Click me!</BaseButton> 或 <base-button>Click me!</base-button> </template>
在 script 中不必
再寫:
import BaseButton from '@/components/BaseButton' export default { components: { BaseButton } }
在每一個元件中,若有 tag 的使用為 BaseButton
或 base-button
皆符合 kebabTag.startsWith('base-')
的這個條件。
此時回傳長度為 2 的陣列
return ['BaseButton', `import BaseButton from '@/components/BaseButton.vue'`]
vuetify-loader
接著自動在 PageA.vue
元件中,引用 BaseButton
當有天 BaseButton
被棄用時,我只需要直接移除 PageA 中的
<BaseButton>Click me!</BaseButton>
或
<base-button>Click me!</base-button>
我甚至不需要意識到 BaseButton
已經被棄用,也不會造成多餘的引入
因為刪掉 template 中的 tag,同時 vuetify-loader 也移除了對 BaseButton
元件的引入
注意:這個範例的 import 條件判斷只有以 PascalCase 方式命名,且放在 @/components/ 底下的元件才會被正確引入,當然你也可以寫適合自己專案的客製化條件
總結:
vuetify-loader
的 match
函式提供自動引入元件的功能,伴隨兩項優點:
避免頻繁引入相同的基礎元件,使專案開發能專注在商業邏輯,並提升開發體驗
避免棄用元件在建置時被打包
最後,很重要說三次
不用 Vuetify 也可以用 vuetify-loader 哦
不用 Vuetify 也可以用 vuetify-loader 哦
不用 Vuetify 也可以用 vuetify-loader 哦
你心動了嗎? 快去使用看看 vuetify-loader
歡迎留言提問、補充或一起討論,
如果我的分享對你有幫助,可以順手按個讚,我會更有動力。