Element Plus 源码分析——构建与代码风格

项目概述

本文章基于 Element Plus v2.1.4。如有错误之处,欢迎指正。

构建

  • Keywords: Vue SFC, Rollup, Bundleless, TypeScript, ESM, CommonJS/CJS, UMD

这部分在一个单独的包 @element-plus/build,代码位于 /internal/build

使用到的工具有:rollupunbuildesbuildgulpts-morphfast-glob 等。如需深度理解,建议先自行了解这些包后阅读本章节。

目录结构

源码

internal/build
├── build.config.ts            # unbuild 配置文件
├── dist                    # 构建产物
├── gulpfile.ts             # 构建脚本
├── package.json
├── src
│   ├── build-info.ts       # 构建信息
│   ├── constants.ts        # 一些常量
│   ├── index.ts            # 入口文件
│   ├── plugins             # 插件
│   │   └── element-plus-alias.ts  # 导入别名
│   ├── tasks
│   │   ├── full-bundle.ts  # 构建完整产物
│   │   ├── helper.ts       # 生成 WebStorm 提示文件
│   │   ├── index.ts
│   │   ├── modules.ts      # 构建 bundleless 产物
│   │   └── types-definitions.ts # 生成 d.ts 文件
│   ├── type-safe.json      # 「类型安全」列表
│   └── utils               # 工具函数
│       ├── gulp.ts
│       ├── index.ts
│       ├── log.ts
│       ├── paths.ts
│       ├── pkg.ts
│       ├── process.ts
│       └── rollup.ts
├── tsconfig.json
└── vue-jest-transformer.js

构建产物

在线预览

dist/
├── element-plus         # 最终构建产物
│   ├── README.md
│   ├── attributes.json
│   ├── dist             # 完整构建产物
│   ├── es               # bundleless 构建产物,ESM 格式
│   ├── global.d.ts      # 供 Volar 使用的全局组件类型
│   ├── lib              # bundleless 构建产物,CJS 格式
│   ├── package.json
│   ├── tags.json
│   ├── theme-chalk      # 样式产物
│   └── web-types.json
└── types                # 类型声明产物

构建流程

首先可以看到在 package.json 文件中的 start 脚本,启动 Gulp 运行 gulpfile.ts 文件。这将运行 gulpfile 的默认导出。在 gulpfile.ts 文件中找到 export default 相关代码就是构建流程了。

0. clean 清理产物

调用一个 run 函数,将会在项目根目录运行 pnpm run clean,其作用为删除根目录下的 dist 文件夹,并且运行 /packages 目录下每个包的 clean 脚本。

1. createOutput 创建构建产物的目录

创建 /dist/element-plus 文件夹。在上一步中,我们把 dist 目录整个删掉了,为了保证目录存在,需要把之前的 dist 目录创建回来。

2. parallel

这是多个并行的任务,因为构建每种不同类型的产物是可以同时进行的。

2.1 buildModules 构建 Bundless 产物

将开启一个新进程开始执行 ./src/tasks/modules.ts 中的 buildModules 函数。最后将在 /dist/element-plus 下生成 eslib 两个文件夹,分别为 ESM 与 CJS 两种格式。

2.2 buildFullBundle 构建完整产物

与上一步类似,将执行 ./src/tasks/full-bundle.ts 中的 buildFullBundle 函数。但这步比上一步多一个构建 locale,因为需要考虑在 CDN 场景下导入不同语言。另外,用户导入完整包可以不需要使用构建工具 (Vite、Webpack 等),需要我们需要还需要提供压缩版本,以便能够节省加载时间。

buildFull 函数就提供了一个参数 minify,以便可以并行执行两个任务——一个压缩版本和一个不压缩的版本。

buildFullEntry 函数就是构建完整产物的函数。除了没有使用 preserveModules 选项,与 buildModules 基本一致。提供了 UMD 与 ESM 两种格式。

buildFullLocale 函数用来构建语言包。为 packages/locale/**/*.ts 下的每个文件同时构建 UMD 与 ESM 两种格式的产物。

同时,开启 minify 参数时会开启 sourceMap 选项,为开发时提供原始源码用来调试。

2.3 generateTypesDefinitions 生成 .d.ts 文件

为了用户开发时提供类型支持,还需要同时生成 .d.ts。将执行 ./src/tasks/types-definitions.ts 中的 generateTypesDefinitions 函数。最后将 .d.ts 写入到 /dist/types 目录中。

2.4 buildHelper 生成 IDE 支持

对于 WebStorm 与 Vetur,需要生成 web-types.jsontags.jsonattributes.json 文件供插件分析,最终提供代码提示。使用了 components-helper 分析文档 Markdown 生成。

开发 Vue 3 应用还是推荐使用 VSCode + Volar,这部分可能以后会被移除。因为用文档生成上述文件并不可靠。

2.5 buildThemeChalk copyFullStyle 构建并复制样式

buildThemeChalk:这步将先执行 buildThemeChalk,从 Sass 源代码构建为 CSS 产物。相关代码位于 packages/theme-chalk/gulpfile.ts。最终把产物从 packages/theme-chalk/dist 复制到 dist/element-plus/theme-chalk

copyFullStyle:将复制 dist/element-plus/theme-chalk/index.cssdist/element-plus/dist/index.css。把完整的 CSS 样式复制到「完整构建产物」的目录中,方便 CDN 引入。

3. copyTypesDefinitions 复制 .d.ts 文件

因为有 ESM 与 CJS 两种格式都需要类型声明文件,所以没有一开始就生成到「最终构建产物」目录。最后将「类型声明产物」的所有文件复制到 dist/element-plus/esdist/element-plus/lib 中即可。

以上就是所有流程。

Rollup 插件

「完整构建产物」与「bundleless 构建产物」都使用到了 Rollup。

Rollup 是不能解析像 TypeScript、Vue SFC 这些非 JavaScript 的代码,所以需要借助各种插件,来帮助 Rollup 将其转换为 JavaScript 代码。Rollup 也不能解析 CommonJS 格式的代码,还需要插件来帮助 Rollup 解决这些问题。

unplugin-vue-define-options

这是我个人写的一个插件。通过这个插件就可以在 Vue 的

你可能感兴趣的:(Element Plus 源码分析——构建与代码风格)