哈喽咱们好,我是广州小井。最近分享了一篇关于Vue3组件库打包的文章,其间有说到我将组件代码跟款式代码进行了分离,这样为了更好的组织款式,根源处理组合组件款式引进的问题。具体是怎样做的?听我渐渐道来~

前情回忆

其间相关联的文章有以下,具体了解能够点进去看看:

这儿我就简略地介绍一下之前的情况。其实做组件库的打包晋级、拆分CSS款式代码的意图就是为了处理之前经过 unplugin 类插件完成组件主动按需引进的问题,这一点上一篇文章也多次强调了。为了让不清楚的同学了解到当时的问题,我仍是再次简略地描述一下问题所在,当然具体的话看 组件库实战——按需加载工程化 这篇文章会有更好的了解。

回到正题,之前为了推行组件库的落地运用,我开端往组件库的生态建设上做了点事情,意图就是为了让其他的开发者更低成本、更轻松地接入组件库到目前的项目中。所以我就着手在 unplugin-vue-components 的基础上扩展了一个自己组件库的 resolver 函数来完成主动按需引进。

终究的作用能够达到以下代码块的作用:

<template>
  <div>
    <vc-table />
  </div>
</template>
<script>
export default {
  name: 'App'
}
</script>

如上代码块,咱们直接能够运用 vc- 开头的组件,而且无需手动引进其组件和款式代码。当咱们不运用该类插件时,咱们需求这样做才干达到正常运用的作用:

<template>
  <div>
    <vc-table />
  </div>
</template>
<script>
// 引进组件
import { VcTable } from '@xxx/vc-element-plus'
// 引进款式
import 'element-plus/es/components/table/style/css'
import '@xxx/vc-element-plus/es/components/table/style/css'
export default {
  name: 'App',
  components: {
    VcTable // 注册组件
  }
}
</script>

如上所示,当咱们要按需运用一个 vc- 类组件的时分,要手动引进 vc组件element-plus的款式代码vc组件的款式代码,还要注册组件,十分的繁琐。假如说你需求向运用了 unplgin 做主动按需引进组件和款式的团队推行你的组件库,不处理这个问题大概率是不会有人理你的。

所以之前我的处理计划很简略,写了个 resolver 函数:解析 Vc 开头的组件,引进 Vc的组件代码element-plus的款式代码。由于当时的组件数很少,而且都是依据 element 扩展的,所以这样做现已处理了当时 99% 的问题了。

但随着组件库的开展,组件数增多了,也有一些自己内部完成的组件了,上述的计划就行不通了。比方当我门的 vc-table 中还运用了 el-selectel-tag 等其他组件时,上述计划的款式引进就有问题了,这也就是我老说的组合组件的款式引进问题

光说不清晰,咱们仍然经过代码来演示。当 vc-table 组件组合运用了其他 element 组件时,即使运用了 unplugin 的主动导入功能,咱们还需求手动导入其他款式。代码如下:

<template>
  <div>
    <vc-table />
  </div>
</template>
<script>
import 'element-plus/es/components/select/style/css'
import 'element-plus/es/components/tag/style/css'
export default {
  name: 'App'
}
</script>

没错,假如照这样开展,开发者的心智负担就十分重了。他得知道你的 vc-组件 中运用了什么其他的组合组件,而且每次运用都需求主动手动把 element 的款式引进进来…别说了,组件库做成这样别人必定不会接的。

依据上面的种种问题,上一篇文章咱们进行了组件库的代码和款式拆分,而且晋级了打包计划,志在处理这个扎手的问题。接下来就来看看我是怎样处理问题的吧。

丝滑按需引进的前置作业

前文铺垫了很长篇幅的前情回忆、问题介绍,意图就是为了让咱们深刻感受到当时组件库开展遇到的问题。根本问题就是现已运用了主动按需引进插件的项目再接入咱们组件库的时分成本会十分高。

当然,假如你说将 element 的组件和 vc-xx 的组件都大局引进不就完美处理了?没错,话是这么说,假如组件、款式都是大局引进的话就不会有这么多的问题了,直接一把梭哈。但不巧的是,我这边的项目 90% 的都是用了 unplgin 插件的主动按需引进方法来开发的。所以,你总不能要求每一个事务线的团队都依照你的要求来开发项目吧…(首要是没人愿意听)

所以,该下功夫的地方仍是得下功夫,接下来直接开干吧。首先看看上一篇文章往后,咱们组件库打包出来的款式代码是怎样样的了:

怎样让开发者丝滑地接入你的组件库

如上图所示,每个组件的款式都被打成了一个 css 文件了。所以咱们只需求将每个款式,经过给组件中的一个索引文件去引进就好了。比方说 button 的组件,他的 style 目录下有一个 index.js 的索引文件。咱们来看看这个文件怎样用:

怎样让开发者丝滑地接入你的组件库

如上图所示,能够看到榜首行代码中引进了一个 scss 的文件。没错,这就是引进 vc-button 款式的地方。咱们或许发现怎样是 scss 文件而不是 css 文件呢?其实这个上文也有讲到,首要是为了组件的开发环境中运用的,在打包阶段,我现现已过 rollup 插件对其进行了修正,终究输出的会是一个 css 的途径。(感兴趣的能够看上一篇组件的文章)

好了,这下咱们或许也发现了,代码的第二行就是引进了 element 的款式了。也就是说我把 el-button 的款式代码也在这个索引文件中引用了。此刻或许你现已明白,我是怎样处理组合组件的款式引进问题的吧?

回到前情回忆中的一个场景,假如此刻我的 vc-table 中运用了其他的 element 组件,那咱们便能够经过这个索引文件进行一致引进。比方以下代码中:

// vc-table 的 style 目录下的 index.js 文件
import '@xxx/vc-element-plus/theme/table.scss'
import 'element-plus/es/components/table/style/css'
import 'element-plus/es/components/popover/style/css'
import 'element-plus/es/components/select/style/css'
import 'element-plus/es/components/tag/style/css'
...

如上代码能够看到,有了索引文件,咱们便能够完成对一切组件款式的管理了,不论你要引进 popper 仍是 tag 仍是其他种种组件的款式都能够。别的,由于我把 vc-类 的组件款式都拆分了,所以即便咱们是要运用 vc-类 的组件来组合,也相同不是问题了。比方我的 vc-table 要组合运用 vc-button,索引文件便能够如下编写:

// vc-table 的 style 目录下的 index.js 文件
import '@xxx/vc-element-plus/theme/table.scss'
import '@xxx/vc-element-plus/theme/button.scss'
import 'element-plus/es/components/table/style/css'
...

好吧,这种用法十分灵活,我就不一一例举了,咱们能get到点就行。大的完成计划定下来后,剩余的作业就是搬运工的角色了。我把整个组件库的一切组件的款式索引文件都做了个收拾,让他们别离引进自己的款式代码依托的 element 的款式代码

改造主动引进函数

由于前面我现已对 vc-类 组件的款式做了一个收拾,所以组件库的一切组件都有一个唯一的款式索引文件,里边有他需求用到的一切款式文件的引进。所以接下来咱们就要改造咱们的 unplugin 插件中的 resolver 函数了,用回前文的图来阐明。

  • 之前他的作用是这样的:

    怎样让开发者丝滑地接入你的组件库

  • 改造后要变成这样:

    怎样让开发者丝滑地接入你的组件库

好吧,其实这个完成比起咱们 1.0 版别的 resolver 函数来得更简略(偷笑.jpg),由于完成起真的比之前还简略。之前为了无痛复用 elementsideEffects(也就是款式代码),我还稍稍思考了2分钟,这次是压根不需求思考!

直接看看我的 resolver 函数 2.0

export const VcElementPlusResolver = () => {
  return async(VcComponentName: string) => {
    if (!VcComponentName.startsWith('Vc')) return
    const componentName = kebabCase(VcComponentName.slice(2))
    const result = {
      name: VcComponentName,
      from: "@xxx/vc-element-plus",
      sideEffects: [
        // 款式引进的中心在这儿,直接引进组件的索引文件
        `@xxx/vc-element-plus/es/${componentName}/style/index`
      ],
    }
    return result
  }
}

假如你看过 组件库实战——按需加载工程化,那么必定能感觉到 2.0 版别的代码跟完成更简略!一切都是依着 unplugin 的插件规范开发,在 sideEffects 属性中,咱们不需求再复用 element 的款式索引文件了,由于咱们现已有了自己的一个索引文件(也就是有注释的那一行)。这样一来,咱们便能够比较丝滑地借助 unplugin 的能力,完成真正的按需、主动导入组件、款式代码的功能了。

如此一来,咱们也顺利处理了之前一直遗留下来的痛点问题,事务方能够丝滑的接入了。比方看看一些实战的接入:

<template>
  <vc-card header="制品">
    制品
  </vc-card>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'Products'
})
</script>

啊,真的十分的丝滑,跟用原生的 element-plus 相同,这下开发者接入也没有任何的心智负担了。

一些装备和留意点

package.json的导出装备

为了使接入的时分一些 import 的途径愈加优雅,咱们能够按需装备这些吧,也不是必要的。不过装备的时分要留意,依据自己当时项意图打包成果来写装备关系,特别是一些产品的途径关系。

  "exports": {
    ".": {
      "import": "./dist/es/index.js",
      "require": "./dist/lib/index.cjs"
    },
    "./es/*": "./dist/es/*.js",
    "./theme/*": "./dist/theme/*"
  },

如上装备,我更多是希望经过 /es/theme 这种途径来引进。比方这样装备后,我就能够在事务项目中这样引进 vc-类 的款式文件。以 button 为例:

import '@xxx/vc-element-plus/theme/button.css'

如上装备,打包东西就会依据你的装备,到 dist/theme 下面去找 button.css 这个文件了。这一点看个人喜好吧,横竖不是非必需的装备。

external的装备

由于做组件库,所以咱们一般会把 element-plusvue 等库都 external 调,然后在 pkjpeerDependencies 声明这些库和版别,要求接入项目按要求装置。好吧,扯远了,接着回来,那 external 是要处理什么问题呢?

咱们首先看看不别的装备 external 的情况下,打包出来的产品有什么问题。当时的 external 装备:

external: ['element-plus', 'vue', 'vue-router', '@element-plus/icons-vue']

这样打下来的产品基本都没问题,可是款式索引文件呈现了一个现象:

怎样让开发者丝滑地接入你的组件库

好吧,目测是把本来引进的 element-plus 的途径给解析了,不是说好的 external 了吗。。。好吧,已然有问题,那就得处理,究竟都走到终究一公里了。这样的款式索引文件,假如发包后在事务项目中运用是有问题的。当然,我的处理思路也很简略,只需确保我的索引文件中的 element-plus 的款式途径不被处理就行了。

怎样让开发者丝滑地接入你的组件库

也就是说我要确保这个款式索引文件在事务项目中也是这样引进 element-plus 的款式文件就行了,由于只需事务项目中按要求装置了对应版别的 element-plus,这行款式代码就能收效了!

一开端我还想着写个插件来处理这个问题,可是我一想,为什么装备了 external 也没起作用呢?后来查了查资料,加上自己的猜想(由于这个装备里边是能够写正则),猜想 external 是一个全等匹配的方法来判别要不要 external 的。比方:

import { xx } from 'element-plus' // 射中 external 的 'element-plus' 装备
import { xx } from 'element-plus/es/xxx' // 未射中

上面的 'element-plus/es/xxx' 不会射中 external 规矩,所以也就会被打包东西正常处理了。所以这儿我打算写个正则去验证一下,搞一个 'element-plus/es/components/' 开头,以 'style/css' 结束的正则。写正则的确不是我的强项,所以我用 GPT 几秒钟写了个:

// 省掉其他的装备
external: [/^element-plus/es/components.*/style/css$/]

这样一下来,咱们再打包一次看看作用:

怎样让开发者丝滑地接入你的组件库

完美,发包!今晚就上线!