手把手带你仿照ele-puls实现自己的组件库(二)之rollup打包

573 阅读4分钟

前言

上个章节我们主要是把基本的架子搭建了一下,这节我们主要写一个基础组件,然后用rollup来进行打包,我们一步步来,先打包组件,先讲如何打包组件

下载打包必要的依赖

rollup 这个就不用说了

@vitejs/plugin-vue 解析编译vue单文件组件(.vue文件)

rollup-plugin-esbuild 将 ESBuild 的功能集成到现有的 Rollup 项目中

@rollup/plugin-node-resolve 用于解析Node.js模块,代码中使用 require() 或 import 导入 Node.js 模块时,此插件会解析这些导入并找到对应的文件路径

@rollup/plugin-commonjs 是一个用于将 CommonJS 模块转换为 ES6 模块的 Rollup 插件

我们在internal/build目录下新建modules.ts来写逻辑,build结构如下

├── build
│   ├── package.json
│   └── src
│       ├── index.ts
│       └── tasks
│           ├── index.ts
│           └── modules.ts

在build 目录下执行 pnpm add rollup @vitejs/plugin-vue rollup-plugin-esbuild @rollup/plugin-node-resolve @rollup/plugin-commonjs 来安装这些必要插件。

创建一个基础组件并进行打包测试

在play中搭建项目,以用来引入测试

这里我没有仿element-puls,而是直接使用vite命令来快速搭建一个项目,因为本质上是为了在项目中测试我们写的组件代码,所以我没有去看ele里那套逻辑,就直接一键生成了 我们直接删掉play,在根下执行npm create vite@latest 然后选择Vue+TypeScript

创建组件libTable.vue

├── components
│   ├── index.ts
│   ├── package.json
│   └── table
│       ├── index.ts
│       └── src
│           └── libTable.vue

内容先简单写一点我们主要先测试打包

<script lang="ts" setup>
    import {ref} from 'vue'
    defineOptions({
      name: 'libTable'
    })
    const nowValue = ref(0)

    const add = () => {
        nowValue.value++
    }
</script>
<template>
    <div>
        当前值为{{nowValue}}
        <button @click="add">点击+1</button>
    </div>
</template>
import libTable from './src/libTable.vue'

export const LibTable = libTable

然后在play里的app.vue里先直接引入试了下,其实也可以安装依赖来测试,我这里就先粗暴引入。

<script setup lang="ts">
import {LibTable} from '../../packages/components'
</script>

<template>
  <div>
    <LibTable/>
  </div>
</template>

WechatIMG177134.jpg

这里亲测可以用,然后我们开始配rollup来打包这个组件,其实也可以直接打包,但是还是建议大家每次在play测试一下自己的组件,再打包,保证没问题

在modules.ts中配置rollup打包

在build下安装gulp+ @esbuild-kit/cjs-loader两个依赖,@esbuild-kit/cjs-loader 是esbuild 工具的一个加载器插件,用于在esbuild 中支持CommonJS 模块格式的加载,gulp装4版本,装5版本我执行esbuild-kit/cjs-loader会报错,我看ele是4,gulp换4版本确实可以成功。在根下装@types/gulp。打包配置如下

import { rollup } from 'rollup'
import { resolve } from 'path'
import vue from '@vitejs/plugin-vue'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import esbuild from 'rollup-plugin-esbuild'
import commonjs from '@rollup/plugin-commonjs'
import glob from 'fast-glob'

import type { TaskFunction } from 'gulp'
import type { Plugin } from 'rollup'

//项目根目录
const projRoot = resolve(__dirname, '..', '..', '..','..')
//包目录
const pkgRoot = resolve(projRoot, 'packages')
//输出目录
const epOutput = resolve(projRoot,'dist')

//打包入口文件过滤
export const excludeFiles = (files: string[]) => {
  const excludes = ['node_modules', 'mock', 'gulpfile', 'dist']
  return files.filter(path => !excludes.some(exclude => path.includes(exclude)))
}


export const buildModules:TaskFunction = async () =>{
    const input = excludeFiles(
        await glob('**/*.{js,ts,vue}', {
          cwd: pkgRoot,
          absolute: true,
          onlyFiles: true
        })
      )
    const plugins: Plugin[] = [
        nodeResolve({
          extensions: ['.mjs', '.js', '.json', '.ts']
        }),
        esbuild(),
        commonjs(),
        vue()
      ]

      const bundle = await rollup({
        input,
        plugins,
        external: ['vue',/@vue/g] //这里我们先写死,因为我们组件目前比较简单
      })
      bundle.write({
        format: 'esm', //输出的模块格式
        dir: resolve(epOutput, 'es'), //输出的目录
        preserveModules: true, //保持原模块的目录结构,而不是打包成一个文件
        preserveModulesRoot: pkgRoot, //指定根目录,这里我们先指定我们的组件目录,
        entryFileNames: `[name].mjs` //输出为 `.mjs`,name是入口
      })
}

简单介绍gulp的任务

gulp中,我们可以这样理解,每个task就是一个函数。

任务(tasks)可以是 public(公开) 或 private(私有) 类型的。

公开任务(Public tasks) 从 gulpfile 中被导出(export),可以通过 gulp 命令直接调用。

私有任务(Private tasks) 被设计为在内部使用,通常作为 series() parallel() 组合的组成部分。

后面具体用到,我们再深入介绍,现在我们简单用下,想了解更多的可以去官网学习。

现在我们gulpfile.ts可以这样写

import { buildModules } from './src/index'
export default buildModules

我们把打包任务导出,然后在package.json里配置start命令

"start": "gulp --require @esbuild-kit/cjs-loader -f gulpfile.ts" 这样我们在build目录下,执行 pnpm run start 就可以执行打包命令。

执行,可以打包成功

img_v3_02e3_1065642c-0e6f-4154-a814-b249a931388g.jpg

打开打包出来的内容看下,理论上是没问题了。

img_v3_02e3_9814f74a-5088-4ee7-8982-c3c2ef75411g.jpg

写在最后

这节大概介绍了一下,打包的流程,里面有很多地址其实一开始是可以整合出来的,很多东西看起来比较糙,是因为我基于复现我当时自己学习的一个思路,从无到有,从有到优。欢迎大家批评指正