用 vuetify-loader 提升 Vue 开发体验

2021-09-14 14:50:01

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 來少寫一些程式碼。

  1. 你寫了很多共用的元件,且在專案中被頻繁地使用

  2. 該如何確保被棄用的元件,在建置時不會被打包

  3. 如何用命名規範來管理元件

重複且頻繁的在專案各處引入相同的元件

舉例來說,專案中有一個 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

歡迎留言提問、補充或一起討論,
如果我的分享對你有幫助,可以順手按個讚,我會更有動力。


  • 2017-02-09 09:02:26

    两列布局——左侧宽度固定,右侧宽度自适应的两种方法

     关于左侧宽度固定,右侧宽度自适应两列布局的一种很常用的方法我相信大家都知道。就是利用左侧元素浮动,或者绝对定位的方式使其脱离常规文档流,让两个块级元素能够在同一行显示。然后右侧元素 margin-left 的值等于左侧元素宽度,这时右侧元素将紧挨着左侧元素

  • 2017-02-10 15:19:51

    Git:代码冲突常见解决方法

    如果系统中有一些配置文件在服务器上做了配置修改,然后后续开发又新添加一些配置项的时候, 在发布这个配置文件的时候,会发生代码冲突:

  • 2017-02-10 15:24:14

    linux学习之——vim简明教程

    学习 vim 并且其会成为你最后一个使用的文本编辑器。没有比这个更好的文本编辑器了,非常地难学,但是却不可思议地好用。 我建议下面这四个步骤: 存活 感觉良好 觉得更好,更强,更快 使用VIM的超能力

  • 2017-02-10 16:22:13

    git历史记录查询

    查看提交历史:git log 查看提交历史并显示版本间的差异:git log -p 查看指定历史:git log xxx(sha1值) -p 查看提交历史(指定时间):

  • 2017-02-13 17:50:05

    cURL error 60: SSL certificate problem: unable to get local issuer certificate

    Drupal 8 version uses Guzzle Http Client internally, but under the hood it may use cURL or PHP internals. If you installed PHP cURL on your PHP server it typically uses cURL and you may see an exception with error Peer certificate cannot be authenticated with known CA certificates or error code CURLE_SSL_CACERT (60).