当前位置: 首页 > Web前端 > vue.js

ElementPlus源码分析——构建与代码风格

时间:2023-03-31 19:38:28 vue.js

项目概况官网:https://element-plus.org/GitHub仓库:https://github.com/element-pl...包管理:pnpmworkspace组件代码:TypeScript、VueSFC(Vue单文件组件)风格:Scss、CSSvar单元测试:Jest、Vitest构建:Rollup、esbuild、[TypeScript](https://www.typescriptlang.org/)、Gulp代码风格:ESLint,Prettier本文基于ElementPlusv2.1.4。如有错误,请指正。构建关键字:VueSFC,Rollup,Bundleless,TypeScript,ESM,CommonJS/CJS,UMD这部分在单独的包@element-plus/build中,代码位于/internal/build。使用的工具有:rollup、unbuild、esbuild、gulp、ts-morph、fast-glob等,如果要深入理解,建议自己理解这些包后再阅读本章。目录结构源码internal/build├──build.config.ts#unbuild配置文件├──dist#buildproduct├──gulpfile.ts#buildscript├──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#构建无捆绑产品││└──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#无捆绑构建产品,CJS格式│├──package.json│├──tags.json│├──theme-chalk#Styleartifacts│└──web-types.json└──types#typedeclarationartifact构建过程首先可以看到package.json文件中的启动脚本,启动Gulp运行gulpfile.ts文件这会运行默认导出的gulpfile。在gulpfile.ts文件中找到exportdefault相关代码就是构建过程。0.clean清理产品调用一个run函数,会在项目根目录运行pnpmrunclean。它的作用是删除根目录下的dist文件夹,运行/packages目录下各个包的clean脚本。1.createOutput创建构建产品的目录,创建/dist/element-plus文件夹。在上一步中,我们删除了整个dist目录。为了保证目录的存在,我们需要把之前的dist目录创建回来。2.并行这是多个并行任务,因为构建每个不同类型的产品可以同时完成。2.1buildModules构建Bundless产品会启动一个新进程,开始执行./src/tasks/modules.ts中的buildModules函数。最后会在/dist/element-plus下生成es和lib两个文件夹,分别是ESM和CJS格式。2.2buildFullBundle构建完整产品与上一步类似,会执行./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.3generateTypesDefinitions生成.d.ts文件为了给用户开发提供类型支持,还需要同时生成.d.ts。./src/tasks/types-definitions.ts中的generateTypesDefinitions函数将被执行。最后将.d.ts写入/dist/types目录。2.4BuildHelper生成IDE支持对于WebStorm和Vetur,需要生成web-types.json、tags.json、attributes.json文件进行插件分析,最后提供代码提示。components-helper用于分析文档Markdown生成。仍然推荐使用VSCode+Volar来开发Vue3应用,以后可能会去掉这部分内容。因为用文档生成上面的文件是不靠谱的。2.5buildThemeChalkcopyFullStyle构建并复制样式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.css复制到dist/element-plus/dist/index.css。将完整的CSS样式复制到“CompleteBuildProduct”目录下,方便CDN导入。3.copyTypesDefinitions复制.d.ts文件,因为ESM和CJS格式都需要类型声明文件,所以不会一开始就生成到“finalbuildproduct”目录下。最后将“类型声明产品”的所有文件复制到dist/element-plus/es和dist/element-plus/lib。这就是所有流程。Rollup插件“完整构建产品”和“无捆绑构建产品”都使用Rollup。Rollup无法解析TypeScript和VueSFC等非JavaScript代码,因此需要各种插件帮助Rollup将其转换为JavaScript代码。Rollup也无法解析CommonJS格式的代码,需要插件来帮助Rollup解决这些问题。unplugin-vue-define-options这是我个人写的一个插件。通过这个插件,你可以在Vue的中使用OptionsAPI。ElementPlus需要定义componentname属性,可以避免两个script标签。@vitejs/plugin-vueVite官方插件,将VueSFC编译成JavaScript代码。@vitejs/plugin-vue-jsxVite官方插件,支持VueJSX语法。@rollup/plugin-node-resolveRollup官方插件,让Rollup支持Node.js解析算法解析node_modules。extensions选项:默认不包含.ts后缀,需要手动添加。@rollup/plugin-commonjsRollup官方插件,用于将CommonJS模块转换为ES6,以便它们可以被Rollup解析。rollup-plugin-esbuild是一款功能强大、高效易用的插件!用于将TypeScript转换为JavaScript,可用于压缩代码和转换语法。基于ESBuild,速度极快。minify选项:是否压缩代码。目标选项:向后兼容低版本浏览器。ElementPlus至少兼容ES2018,但是在开发中会用到一些新的语法(比如Optionalchaining等),所以需要借助ESBuild的语法糖转换成ES2018兼容代码的能力。loaders选项:使用@vitejs/plugin-vue插件编译后,VueSFC只是普通的JavaScript代码,但其后缀仍然是.vue。所以你需要添加'.vue':'ts',将.vue文件视为普通的.js文件。Rollup配置外部以在构建捆绑包时从构建工件中排除依赖项和peerDependencies。构建完整产品时,从构建产品中排除peerDependencies(akavue)。启用preserveModules后,构建产品将保持与源代码相同的文件结构。可以这样理解,只有VueSFC、TypeScript等转换成JavaScript代码,其他不变。其他代码build.config.ts在开发时使用unbuild生成stub,用于开发和调试。这样就不需要watch一直监控文件的构建了。src/type-safe.json因为ElementPlus的代码还是有TypeScript类型的产品,只是重构了一些文件。该文件是已重构的记录列表。为了在生成.d.ts时对这部分文件做异常处理。src/build-info.ts在这个文件中写入构建配置,包括路径、构建格式、后缀名等。src/constants.ts一些常量。如果想自己搭建,修改一些参数,可以修改这个文件。src/plugins/element-plus-alias.ts解析样式导入的路径。将“@element-plus/theme-chalk”替换为“element-plus/theme-chalk”。生成.d.ts类型定义的代码在generateTypesDefinitions步骤中。这里使用ts-morph来简化TypeScript编译调用。首先创建一个Project并指定配置覆盖tsconfig.json中的配置。将skipAddingFilesFromTsConfig设置为true的目的是我们需要手动选择文件进入编译器。按glob匹配所有源文件,并仅过滤掉用于测试和开发的源文件。获取文件列表后,您需要将文件添加到TypeScript编译器。值得注意的是,VueSFC不能直接添加到编译器中,因为TypeScript无法解析它。所以需要使用vue/compiler-sfc中的parse和compileScript提取script块中的代码,编译的代码。然后将其添加到编译器中。此外,由于构建产品的目录结构与我们实际的源代码目录结构不同。所以这里做个特殊处理——手动读取文件内容,加入编译器。还需要匹配工具的“类型安全”列表中的文件。如果列表中的文件类型不对,会直接报错。防止意外引起的TypeScript错误。后续将陆续完成代码重构,确保TypeScript零错误。最后就是将编译好的.d.ts文件写入build目录。以后我写了一个新的构建过程,以后可能会用在ElementPlus3中。全程使用ESBuild构建,速度应该会快很多。此外,将来很可能只构建ESM和IIFE格式版本。因此,也可以删除Bundleless构建工件。这部分代码风格在单独的包@element-plus/eslint-config中,代码位于/internal/eslint-config。如果您想向ElementPlus贡献代码,请确保代码风格正确。您可以运行pnpmrunlint来检查问题,并使用pnpmrunlint:fix来自动修复问题。ESLintElementPlus使用ESLint来管理代码风格,并使用多个插件来支持不同的文件类型。支持的文件类型有:JavaScript、TypeScript、JSX/TSX、VueSFC、Markdown、JSON、JSON5,??详见.vscode/settings.json中的配置项eslint.validate。Prettier一般使用Prettier来约束代码风格,详见Prettier配置文件。并使用Prettier插件和预设规则与ESLint集成。其他代码部分稍后更新。