群内目前的业务组件库由于一些历史背景原因,源码和展示站点分为两个独立的项目工程维护,源码和站点是维护在仓库里或者用MonoRepo的方式开发维护。因此,在不改变项目结构的情况下(暂时不用担心为什么不一起维护),我们在效率协同和工程化方面进行了一系列的演进。先介绍一下我们目前面临的问题:npmlink因为源码和站点是在两个项目下维护的,所以在本地开发的时候如何关联两个项目是我们面临的第一个问题。最初我们采用的是npmlink的方式,但是由于组件库和站点都是基于reacthooks开发的,每次组件的迭代开发都需要经过以下步骤:站点下:cdnode_modules/react&&npmlink并在源码下cdnode_modules/react-dom&&npmlink:npmlinkreact&&npmlinkreact-domsourcecode:npmlinksite:npmlink源码不难找,这样的方案有以下痛点(每一个参与开发的新同学都会抱怨diss):操作繁琐,容易出错;yarn与npm混合使用导致链接问题频繁;链接断开的链接;site&sourcecode,双重编译这个版本我们完全摒弃了npmlink,采用了hacker的方式:sourcecodewatchfilechanges,实时编译构建ESM;sourcecodewatchESMChanges实时同步到站点node_modules;sitewatchnode_modules下的组件ESM变更热更新;不难发现,这样的方案存在以下痛点:监控node_modules变化,姿势很hacky;双边监视+编译严重消耗内存资源;更新时间=组件ESM编译时间+同步推送时间(可忽略)+站点编译时间,10s+适当;站点单次编译既然站点和源码都具备编译构建的能力,为什么不减少一次编译构建呢?为此,我们进行了第三次优化升级:更改源码watch文件,实时同步源码到站点缓存目录;开发环境中,站点importnode_modules下的ESM改为import缓存目录下的组件源码;sitewatch缓存目录下组件的源码变更和热更新;虽然这次升级后大部分问题都解决了,但问题依然存在。源码本地开发优化,增加现场编译压力:热更新慢:改文案hotreload2s+;冷启动更慢:60s比较合适;其实这一步的问题已经在一定程度上依赖了webpack衍生解决方案的通病,所以我们把重点放在了新的buildtoolsuperior上。为什么选择维特?下面我列出了一种常用的构建工具和一些选择注意事项。一是Webpack及Webpack衍生方案:基于CRA封装的业务脚手架;加拿大税务局;webpack轻量级配置;基于Webpack的方案与目前使用的脚手架没有太大区别,好处并不明显,不能从根本上解决Webpack带来的问题。生产力问题。接下来是目前比较流行的基于ESM的现代方案:SnowpackVite的一篇比较有说服力的文章:comparison。另外,就我个人而言,我觉得友达在中文社区和国内的影响力更大,所以友达的开源工具在国内社区会更活跃,关注度也会更高。对于后续的可持续发展也比较有利,所以我们选择了Vite进行选型。秒级冷启动:60s+=>3s-(缓存生效后约300ms)毫秒级热更新:2s+=>1s-(sync+hotreload)效果很好!!!为什么Vite快?第一次冷启动:esbuild预编译,生成缓存然后再次冷启动:冷启动使用缓存为什么先冷启动比较快,因为Vite是基于原生ESM的,也就是说Vite把构建的工作交给了Webpack前面的bundle交给了现在强大的浏览器来做,所以冷启动时间大大减少(毕竟冷启动最耗时的就是分析代码和构建bundle)。在Vite中,正如官方文档介绍的那样,Vite将我们的代码分为依赖和源代码两部分:依赖:大部分是纯JavaScript,在开发过程中不会发生变化。Vite将使用esbuild来预构建依赖项。esbuild是用Go编写的,比用JavaScript编写的打包程序快10-100倍。Pre-builddependenciesSourcecode:通常包含一些不直接是JavaScript的文件,需要改造(比如JSX、CSS或Vue/Svelte组件),经常被edit替换。同时,并不是所有的源代码都需要同时加载(比如基于路由拆分的代码模块)。以Webpack为代表的“bundlebaseddevserver”需要依赖babel等工具在冷启动前分析代码并编译生成可运行的bundle,这个build-time过程导致冷启动时间过长。对于“ESMbasedevserver”,devserver依赖于我们的ESM,而我们的代码本身就是用ESM写的,所以进入的时候需要告诉devserver加载目标模块路径,编译解析交给浏览器。运行时处理,从而大大加快了我们的冷启动。热更新基于原生ESM。在Vite中,HMR是在原生ESM上执行的。和冷启动一样的道理,当我们修改一个文件的时候,不需要重新编译,热更新会大大减少耗时。有了httpheader,Vite就充分利用了http缓存。这也是我们在本地开发时和webpack有很大区别的地方。网络上充斥着大量的模块请求。源码部分:304与ETag协商缓存依赖模块:强缓存WebpacktoVite?那么如何从Webpack顺利迁移到Vite呢?事实上,当你按照Vite文档落地的时候,它已经兼容了80%的Webpack场景。只需要考虑一些额外的情况:ESM及ESM衍生问题Vite使用esBuild预构建ESM,因此对包的要求比较严格,对于esBuild预编译失败的场景需要逐案处理。例如:esBuild预编译失败这里以react-virtualized为例,react-virtualized的WindowScroll.js引入了流类型文件,导致预编译失败。可以写esBuild插件,写解析,拉包进行本地修改。Dep-scan依赖性分析失败。以react-infinite-scroller为例。package.json中ESM读取目录指向src源码目录,发送包后被忽略,导致dep-scan插件找不到模块。ESNextbundleVite的构建过程由esBuild接管,esBuild支持的目标最低版本为es6,所以如果你想构建一个更兼容的bundle,你需要重新编译Vite的输出或者使用官方的SystemJS-基于解决方案。下图是截取的Vite官网兼容部分:使用官方插件:babel翻译注册为System.js模块;添加System.js运行时;最后把站点或者内部系统展示给我们的组件库工程项目一用就用,但是我们在实际投资外部项目的时候要考虑一些问题:成本单上说从Webpack切换到成本Vite非常低级,甚至比Webpack的大版本升级还容易。但是从Webpack到Vite不仅仅是构建工具的转换,而是整个生态的迁移,所以历史项目中已经存在的babel插件和Webpack插件需要等量替换,这就是成本。另外,上一节提到,我们还需要对一些非标准的三方包做额外的适配,这也是一个成本。收益从目前来看,Vite带来的工程效率收益是比较高的,但就我个人而言,我所尝试的只是一个简单的展示站点,不能严格等同于实际的业务工程,而且企业级项目的工程量和复杂度都比较大,我个人无法保证Vite能否达到预期并带来收益。风险最后,因为涉及到ESM,即使给出了SystemJs官方版本的兼容插件,实际投入外部项目的兼容风险还是未知数。
