San CLI 历经多个版本迭代,目前已经进入 4.0 版本,增加 webpack5 支持、优化配置机制等,本文会对升级经验做出总结,期望给读者带来一些启发。

前言

San CLI 更新到 3.0 版本时,已从最初的简单脚手架功能逐步增加了构建命令、插件化、图形化的能力,其功能已经可以满足大部分的业务需求。但在一些特殊场景,其表现仍有待提升,例如配置的修改:San CLI 默认对 CSR 的工程支持较好,但在业务中遇到 SSR 架构的工程时,则需要在 San CLI 默认配置的基础上增加较多配置,3.0 提供的配置修改能力需要对默认规则逐一进行覆盖,对于业务来说还是比较繁琐且不够灵活的。在实际的使用过程中,我们也发现对于一些内置的命令,如 command、 plugin 等命令,使用频率较低,无法达到按需安装,同时新增命令时,使用方式略显复杂。随着社区工具的升级,San CLI 内部也需要不断的更新升级,基于此我们在 4.0 版本对 San CLI 进行了整体功能架构的调整,主要的目标就是提升工具的灵活性及构建性能。

关于 San CLI 的功能介绍可以参考以往公众号文章

San CLI 4.0 升级

San CLI 4.0 的主要升级包括两部分,第一个就是提升灵活性,为此对整体架构进行调整,以实现命令的按需安装,更灵活的配置,提升整体的扩展性;第二个则是针对构建性能的优化,提升用户的使用体验。接下来将详细介绍这两点。

1 架构变化
San CLI 的构建能力主要基于对 webpack 的封装,我们知道,大型项目的 webpack 的配置通常是比较复杂的,集齐一些优化方案也比较耗费时间,而 San CLI 内置了 webpack 常用的配置及优化方案,可以大大简化用户的使用,并在此基础上提供了 init(项目创建)、build(生产环境构建)、 serve(本地调试)三个核心命令,除此之外,内置的 command 、plugin 、inspect 命令可以提供自由扩展命令、插件及查看配置能力,用户可以定制属于自己的前端开发的工具集,San CLI 3.0 的架构如下图所示:

San CLI 4.0 升级后的架构,如下图所示:

为提升工具的灵活性,架构的调整主要包括以下几点:

  • 精简命令,按需安装 所有功能及插件都以独立 npm 包存在;内置命令及扩展命令都是按照统一命名规范加载,并从 之前的san-cli-service 包解耦,可以实现独立安装升级,内置命令由之前的 7 个精简为 3 个主要命令,其余命令可通过安装扩展。
  • 配置解耦,独立升级 内置的构建配置由 san-cli-config-webpack生成,统一通过插件生成和扩展,外部可以通过加载插件或配置包的形式扩展配置,并且将 webpack 启动包基于事件机制进行重构,提升复用性。
  • 统一扩展方式 San CLI 配置都是通过插件进行修改,内外逻辑统一;规定三种类型的扩展:san-cli-xxx自定义命令,san-cli-plugin-xxx 用于修改 San CLI 自身配置, san-cli-ui-xx 增加 San CL UI 可视化界面插件

1.1 命令 / 插件扩展
San CLI 有三种插件扩展的方式:

  • 第一种是命令的扩展。新增的自定义命令,只需符合包及 yargs 的命令规范,即可集成到 SanCLI,安装即可使用,无需采用之前的命令式安装。自定义命令包导出的变量格式如下所示:

  • 第二种是可修改 webapck 配置的 service 插件。同样需要符合包命名规范,并导出统一字段:插件 id 和实际执行函数,通过webpack-chain 的语法修改默认配置。在 4.0 中增加了插件的配置映射 pickConfig, 将插件的配置项与 SanCLI 配置文件中的配置项隔离,使得插件的使用更纯粹。插件包导出的变量格式如下所示:

  • 第三种则是用于 San CLI UI 可视化界面的插件,在符合包命名规范的基础上可根据提供的 api 创建不同类型的可视化部件.

1.2 配置机制
San CLI 3.0 内默认支持 CSR 工程的打包,webpack 相关的 loader 及 rules 等均在 san-cli-service 包内置,在执行 san serve/build 命令构建时,统一通过 service 生成,整个流程对用户是透明的,用户可以快速开启一个 San 的工程,但整个配置的生成是在 Service 内部流转,对开发者来说只能通过 提供的 webpack-chain 覆盖修改,如果遇到需要对构建流程有较大改动时,配置较多且繁琐,因此需要更加灵活的控制内置配置的生成,下图是配置升级前模块调用关系图:

如上图所示,配置升级前所有的 loader、 rules 等 webpack 配置都在 service 内部调用,开发者可以通过增加 San CLI 的 plugin 进行修改,或者在配置文件中通过函数对最终生成的 webpack 配置的 JSON 对象进行修改。内置的 san-cli-config-webpack 的配置是完全执行完毕,即使自定义的构建配置可能并不需要,甚至在最后需要手动覆盖。整个配置的生成流程:

  • getWebpackConfig 调用 getWebpackChainConfig 生成 chainConfig ,同时得到san-cli-config-webapck 内置的配置
  • getWebpackChainConfig 内依赖san-cli-config-webapck 内的函数 createChainConfig 创建 chainConfig ,加载san-cli-config-webapck 内置的配置
  • 执行 webpackChainFns 内的所有函数,应用 plugin的插件扩展修改配置
  • 回到 getWebpackConfig 继续执行 webpackRawConfigFns 内一些对 config直接修改的方法
  • 调用 san-cli-config-webapck 内的函数 createDevServerConfig,合并传入的devServer 配置和默认配置

在配置升级后,所有的内置的 webpack 相关配置都是以 plugin 方式存在,统一了内外部配置的修改方式;并且插件以资源类型进行拆分,加载配置时提供了每个插件的开关,用户可以通过传入插件的配置来关闭对应的插件;与此同时为提升同一类型配置的复用性,在 San CLI 的配置文件内增加了 extends 关键字,可以批量增加配置包或者配置插件,更多细节可查看 san-cli-config-webpack 配置包,升级后的模块调用关系如下如所示:

配置拆分后,移除了对 san-cli-config-webapck 创建 webpackChain 的依赖,san-cli-config-webapck 仅作为配置包加载,不参与 service 流程的执行。调用 api.getWebpackConfig 生成 webpack 配置流程:

  • getWebpackConfig 调用 getWebpackChainConfig 生成 chainConfig
  • 在getWebpackChainConfig 内通过 new Config 生成 webapckChain 的实例。
  • 执行webpackChainFns 内的所有函数,应用 plugin 的插件扩展修改
  • 回到 getWebpackConfig 继续执行 webpackRawConfigFns 内一些对 config 直接修改的方法
  • 取得 san-cli-config-webapck内的函数 devServerOptions,在 service 内部做合并

2 性能提升

San CLI 4.0 升级的第二个部分就是对构建性能的优化,将内置的 webpack 版本由 4 升级到 5。Webpack5 甩掉了一些历史包袱,并做了一些优化,进一步提升了 San CLI 的构建体验。关于 webpack5 升级的文章有很多,这里我们仅介绍升级后为 San CLI 增加的一些新特性。

2.1 新特性与效果
Webpack5 升级官方有一些关于构建性能的指导,比如 loader 设置 exclude 去掉不包含的模块,精简 loader/plugin 的数量、应用缓存等,升级的过程就是不断的修改、调试、运行的过程,不再详述,我们简要总结下在 San CLI 内部经验证保留的功能:

首先是 San CLI 4.0 内默认开启的能力(以下效果数据均基于 San CLI 创建的默认 demo 测试产生):

  • Pollyfill 按需加载:Webpack5 移除了 node 相关的依赖,结合我们实现的 pollyfill 按需加载方案,其vendor 的体积减少 5.3%(19.62kb)
  • Cache:Webpack5 的构建缓存能力,在生产环境关闭,开发环境开启且默认使用memory 缓存,在 San CLI 中指定了缓存到文件系统(filesystem),开发环境非首次启动可以减少78.14%,增量构建减少 7.66%
  • Asset module:Webpack5 的资源处理模块,可以替换 url-loader、file-loader,以减少 loader 的数量,demo 对比来看没有明显的提升(demo 工程较小),但loader 的数据量的减少对一些大型工程打包的速度会有一定的影响

以上都是在 San CLI 内默认开启的功能,接下来介绍下选择开启的功能:

  • Esbuild-loader:开启后,在开发环境替换 babel-loader,首次减少 22.25%;增量构建减少31.17%;生产环境替换 terser 对 js 进行压缩 ,构建速度有所提升(减少 34%),但是会导致包大小略有增加
  • Thread-loader:多进程打包,只应用在生产环境,开启也消耗时间(600ms)因此推荐只在大型项目时开启,默认关闭
  • RuntimeChunk:Webpack5 支持拆分运行时 chunk,推荐多入口情况下选择开启,开启后体积略有降低,配合splitChunks 进一步可以降低入口 bundle 的大小
  • Dlls 分包预编译:引入后对构建流程有所改造,通过 demo的测试,仅在开发环境增量构建速度有所降低,相较于对产出的影响,在 San CLI 内部默认不应用
  • optimization.moduleIds:Webapck5 新增的文件生成的优化,San CLI 内默认设置为deterministic 以减少文件的 hash 修改频次,有利于缓存

2.2 升级问题总结
在升级的过程中,我们遇到的问题主要有以下两类:

  1. 构建性能:尽管 webpack5 官方升级说明中指出构建性能有所优化和提升,但是在实际升级过程中,将所有的相关 loader、plugin 升级到合适版本后发现,构建速度并没有明显提升,甚至在生产环境下构建速度有所下降,为此我们尝试了一些方法,总结为以下几点:

持久化缓存

webpack5 可指定缓存到文件系统,这在本地开发环境下,可以极大提升构建速度。

{
cache: {
type: ‘filesystem’
}
}
精简 plugin

webpack5 提供了一些配置和功能,可以替代一些 loader/plugin 的使用,我们知道 loader/plugin 的数量在一定程度上会影响构建的速度,例如:使用 Asset module 替换 url-loader、file-loader;使用 lint 工具替换 CaseSensitivePathsPlugin 插件;使用 output.clean 的配置项替换 CleanWebpackPlugin 插件等。

按需关闭配置项

webpack5 内部新增了一些默认开启的计算策略,但在构建时也会影响到构建的速度,可在使用时按需关闭,例如:可通过指定 module.unsafeCache = true 来关闭 webpack5 的安全缓存策略,可减少约 800ms 左右的时间;生产环境下指定 output.pathinfo=false 禁用模块的注释信息,仅在开发环境下启用;注意简化 stats 状态信息,stats.toJSON 转换全部信息也需要耗费一定的时间,因此在使用时推荐传入配置 {all: false},仅提取需要的部分。写法上注意检查避免 export * 的写法。

  1. 工具更新和兼容

关于 esModule 的支持:webpack5 已全面拥抱 ES Module,相关的插件如:html-loader、san-loader、css-loader 等均支持 esModule 配置项,以便开启 ES Module 的语法支持。为此,在 San CLI 内部新增了 esModule 配置项,用于一键开启内置 loader 的相关配置(该配置项是在 .san 单文件构建且启用 css modules 的必要选项)。

关于 tree shaking 失效的问题:在 webpack5 升级之前,为保证构建的一致性,在 babel 使用时引入了 @babel/plugin-transform-modules-commonjs 插件,将代码转换为 commonjs 后再进行处理,我们知道,webpack 的 tree shaking 是基于 ES module 的语法实现,因此在 San CLI 的默认 babel 配置中移除了该插件,推荐工程内部采用 ES module 的语法,以便更好的利用 tree shaking 减小产出体积。

San CLI 内暂缓升级的部分:尽管 webpack5 更新已有很长时间了,但其周边的相关插件并没有完全适配,San CLI 在升级时也遇到了相关的情况,例如依赖的 webpack-chain 包,由于其未能支持一些 webpack5 新增的 api,导致在 San CLI 内部使用时仍需要单独处理此类配置,此类工具需要静待社区的更新;另外,webpack-dev-server 的 4.x 版本有较多不兼容改变,为保证 San CLI 用户的平滑升级,我们内置的 webpack-dev-server 仍考虑采用 3.x 的版本。

2.3 对业务构建性能的提升
San CLI 4.0 发布后,我们将其应用到了不同的类型的业务,性能有不同程度的提升。整体包体积均有所减小,构建速度有所提升,在不同的应用架构下趋势相同:

  • C 端的多页应用(代码行数约 11710)构建包体积减少约 2.7%,生产环境下构建速度提升约13.2%,开发环境尤其是非首次启动时速度提升较明显(约 86%)
  • B 端单页应用(代码行数约 70582)构建包体积减少约 0.9%,生产及开发环境下构建速度均有所提升

3 功能增强

除以上提到的架构升级和内置配置的修改外,在 San CLI 4.0 上增加了以下功能。

3.1 typescript 构建支持
在 San CLI 3.0 及之前版本,默认创建 js 类型的工程。使用 San CLI 4.0 创建项目时,支持选择 typescript 作为工程的语言类型。

在实现上主要基于 babel 的预设 @babel/preset-typescript 来支持 ts 文件的语法转换,而语法检测的工作默认采用 @typescript-eslint 来实现,项目创建时已默认配置,用户也可自行配置,利用 tsc 命令或配合 vscode 插件等实现。

3.2 san 单文件构建体验提升
在 San CLI 4.0 我们进一步优化了单文件的构建体验,在全局安装 san-cli 之后,只需以下两步,即可调试一个单文件组件:

  1. 创建一个 index.san 文件,内容为 san 官网最简单的单文件内容
  2. 执行 san serve index.san

同样的,执行 san build index.san 即可得到构建产出。

3.3 esm 构建支持
San CLI 4.0 还有一个新增的构建选项 —— 基于 esm 的本地构建。在本地调试场景下,我们更在意的是功能的快速查看和验证,特别是在一些大型的项目中,如果本地一个小的修改需要等待几秒钟完成构建,这个开发体验是很令人崩溃的,也就是说构建的速度很重要。而实际情况中,我们通常使用的本地浏览器的版本较新,能够很好的支持 js 的 esnext 版本,并不需要构建中通过 babel 等工具做代码的 es5 转换,因此在本地构建场景下,只需要实现基于 esm 的构建即可满足需求。

从构建工具的角度来看,随着社区构建工具的不断更新,出现了一些类似 esbuild 的构建工具,从上图数据来看,esbuild 构建速度远远大于 Webpack。esbuild 更适合处理 js 和 ts (对比 babel )来做代码转换,而在本地构架的场景下,恰好可以满足只构建 es6 以上版本,因此我们在 San CLI 内利用 esbuild-loader 来实现基于 esm 的构建功能,通过 san serve --esm 命令即可启动,通过 demo 数据的对比来看,本地调试的启动时间可降低 32.7%。

最后

社区的工具不断推陈出新,我们也在持续跟进,不断优化 San CLI 的功能,丰富 San CLI 的使用场景,以期给用户带来更好的使用体验,如果有任何疑问或想法,欢迎提出 issue 或 pr 。

点击进入获得更多技术信息~~

San CLI 4.0 升级指南相关推荐

  1. Spring Boot 3.0 正式发布,这份升级指南必须收藏

    Spring Boot 3.0 现已正式发布,它包含了 12 个月以来 151 个开发者的 5700 多次代码提交.这是自 4.5 年前发布 2.0 以来,Spring Boot 的第一次重大修订. ...

  2. PyTorch 0.4新版本 升级指南 no_grad

    PyTorch 0.4新版本 升级指南 [导读]今天大家比较关心的是PyTorch在GitHub发布0.4.0版本,专知成员Huaiwen详细讲解了PyTorch新版本的变动信息, 本次升级, 只做了 ...

  3. [转] PyTorch 0.4新版本 升级指南 no_grad

    转自PyTorch 0.4新版本 升级指南,博主为ShellCollector. PyTorch 0.4新版本 升级指南 PyTorch 终于从0.3.1升级到0.4.0了, 首先引入眼帘的,是PyT ...

  4. 小米9什么时间升级android10,小米9/MIX 3 现在即可升级安卓10.0!升级指南戳这里...

    原标题:小米9/MIX 3 现在即可升级安卓10.0!升级指南戳这里 [手机频道·原创] 最近小米接连有消息爆出,在今天早些时候的I/O开发者大会上,谷歌在Android Q中推出了许多新功能.现在, ...

  5. 52ABP前端升级2.0.x指南

    52ABP前端升级2.0.x指南 前言 本篇内容为指导从 yoyo-ng-module 1.x 升级到 yoyo-ng-module 2.x 详细说明 52ABP前端框架采用的是 基于NG-Zorro ...

  6. TiDB 4.0 升级 5.1 二三事——避坑指南

    \n> 原文来源: https://tidb.net/blog/ce260ea4 \n\n# 1. 背景 TiDB 5.1 版本 GA 到目前已经有一年时间,在稳定性.易用性.性能提升等各个方面 ...

  7. VMware vSphere 6.0 升级已知问题

    官方链接 已知问题 已知问题分为如下类别. 安装问题 升级问题 许可问题 vCenter Single Sign-On 和证书管理问题 网络连接问题 存储问题 服务器配置问题 vCenter Serv ...

  8. ESXI 4.0 升级 ESXI 4.1 手记

    一开始,以为Vmware vSphere Host Update Utility4能支持升级 4.1,结果报错··· 出错了 Google了一下,发现也有外国朋友遇到这样的问题,呵呵,我这里只是讲升级 ...

  9. Vue CLI 3.0 正式发布,Vue.js 开发标准化工具

    Vue CLI 3.0 已发布,该版本经历了重构,旨在: 减少现代前端工具的配置烦扰,尤其是在将多个工具混合在一起使用时: 尽可能在工具链中加入最佳实践,让它成为任意 Vue 应用程序的默认实践. V ...

最新文章

  1. android之http协议编程(源码ppt),Android网络编程(八)源码解析OkHttp中篇[复用连接池]...
  2. linux vi de ce,linux下vi命令Vi命令集
  3. Windows命令行参数的知识(一)
  4. vb在服务器上新建文件夹,vb.net-如果不存在,如何在VB中创建文件夹?
  5. 160 - 51 DueList.6
  6. 取一定范围内随机小数 c_算伪随机概率中C值的快捷方法
  7. string和StringBuilder的选择
  8. js判断url是否有效
  9. Android开发性能优化大总结
  10. Android Studio 技巧
  11. 理解文档对象模型(2)
  12. 公务员从事计算机网络工作,干程序员好,还是从事公务员更有前途?网友:要是我就当公务员!...
  13. java 生成 顺序 uuid_Java 生成有序 UUID
  14. 数字孪生CIM智慧城市BIM,城市cim可视化解决方案公司
  15. 2021年全球与中国数字频率计行业市场规模及发展前景分析
  16. 学习OpenCV——计算邻接区域列表(build_adjoin)
  17. html 中 超链接的写法,网页超链接样式的CSS写法
  18. Redhat相关快捷键
  19. 阿里云部署公司网盘实例
  20. 网站只有首页能打开,其他页面404

热门文章

  1. 使用Adsutil.vbs来获取IIS用户的密码
  2. 我的建模可以复制(001)— 盘古开天
  3. 狼的故事14:必死的狮子
  4. 利用公众号 + WeRoBot开发一款AI应用
  5. 数据结构——顺序表(二)
  6. 10 个 GitHub 上超火的 CSS 奇技淫巧项目,找到写 CSS 的灵感!
  7. idea好用的快捷键
  8. 【视频】React redux toolkit创建状态切片
  9. 【收藏】Kubernetes(十七) 基于NFS的动态存储申请
  10. Scala基于Akka模拟Spark Master Worker进程间通信(二):Worker定时向Master心跳