您现在的位置:主页 > 银河高手论坛 >

基于Tree-shaking的多平台Web代码打包实践东方心经

发布时间: 2020-01-24

  在业务中,我们常常会遇到一个场景:同一套web业务代码要在多平台下执行其对应的不同职能。这样很容易出现两个问题:代码里“尸横遍野”的环境判断和分支,提高了代码维护难度;执行环境下载了其他环境的功能代码,造成了资源的浪费。只要我们合理使用Webpack的Tree-shaking功能,就可以很好地解决问题。

  出现一套Web代码在多个平台下执行需要实现不同功能的问题,功能包括但不限于:数据加载、展示样式、用户交互等。

  例如,腾讯课堂H5课程详情页需要承载起H5、App、PadApp、小程序等多平台的页面功能,以该页面在H5和App两个环境下的对比为例:

  以其中的一个组件为例(如下代码),只要是在移动端需要适配多平台,那类似这样isApp的运行时环境判断代码一定不会少见(无论你是通过App/小程序内嵌H5页面、React-Native-Web三端同构、kbone同构小程序/H5等)。

  这样的代码一方面容易在多次迭代中慢慢沦为垃圾代码(当然这个可以通过更合理的目录和代码重构解决);另一方面在不同的平台也加载了多余的代码逻辑,例如App相关的逻辑代码在H5上完全不会执行,但是还是被加载了。

  一套web代码想要在多个平台实现不同功能,无论你使用条件分支、还是继承派生等方法,一个页面一份代码打天下的实践已经无法满足我们的需求了。细究这么多种多平台同构的方案,其基本原理都是一份统一API的代码,通过编译打包引用不同的平台底层组件,最后打包成多份可执行程序的过程。

  重新回头看上文的isApp判断逻辑,如果我们把运行时环境判断提前到编译时环境判断,根据逻辑判断的结果,通过Tree-shaking优化去除多余的代码,那么就能得到指定运行平台的可执行代码了!

  通过webpack.DefinePlugin注入编译时环境变量,后续我们的执行代码里就可以引用这个环境变量进行当前平台的判断了。

  分离容器组件和功能组件,通常容器组件以组合的形式实现,功能组件以继承的方式实现;

  功能组件,以继承的方式实现,通常你需要一个基础父组件和多个平台下的子组件;

  更新环境判断逻辑,需要把 运行时环境判断 修改为 编译时环境判断 ,同时这也是一个梳理的过程,你可以了当前你的代码需要支撑多少平台;

  本文章已Webpack4的角度进行阐述,其他版本或者构建工具可以进行参考。

  需要注意的是 Tree-shaking依赖ES6模块语法,如果你的项目使用的babel:

  声明指定文件的副作用,可以通过include或者exclude指定文件范围。

  什么样的模块会被Tree-shaking去除呢?通过官方教程,我们了解到:

  以上图的CourseDetail组件为例,当编译时环境变量RUNTIME_ENV_EXPECT注入为APP时,相关条件判断代码将被置为true,借而产生不可到达的分支,而这种条件分支和相关依赖都会被 Tree-shaking 自动去除,也就达到了去除非本环境依赖代码的效果。王中王鉄算盘开奖成果118接着再做后续的护肤事

  通过上面的三个步骤,我们可以走通指定一个运行平台的代码构建打包过程。接下来要做的事情就是将该过程重复多轮,每一轮注入特定的编译时环境变量用来指定运行平台。

  其中buildDistConfigForEnv根据输入的参数生成指定运行平台的构建配置,需要做以下几件事情:

  直出代码打包同理,需要根据编译时环境变量打包出多个平台使用的模板代码和组件。

  最后打包进直出templates的模板有多个,例如腾讯课堂App内嵌课详页时是使用course.app.html。所以需要一个直出服务的路由逻辑,在访问同一个URL时,自动根据请求带的用户环境信息选择对应合适的模板文件(指向不同的静态资源)进行渲染。

  每个平台都需要进行静态资源 + 直出资源的打包,总共累计平台数*2的编译过程,这个过程是串行执行的,一旦打包平台增加不免需要等待更长的构建事件。

  我们可以利用 parallel-webpack 同时启动多个打包构建过程,例如:

  但是以前无往不利的构建配置似乎出现了异常,最后输出的文件夹只有一个平台的打包代码,这是为什么呢?原因很简单,在构建打包的各个阶段我们使用了不同的插件,其中CleanWebpackPlugin和EndWebpackPlugin造成了破坏性结果,前者会在构建开始前清除构建输出目录,后者会在构建结束阶段允许用户执行脚本。

  于是我们的多进程并行打包过程就受影响了,后一个启动的进程把前一个进程的结果给破坏了,最后构建结束阶段做的工作也被重复了多次。

  我们可以通过 parallel-webpack 提供的 Node.js API,手动控制打包过程,特别是打包前置操作和打包后置操作,例如:

  代码压缩率可以达到 4.1% - 24.7% ,随着支撑平台数增多,跨平台功能逻辑复杂度的上升,这里的优化效果会越来越明显;

  其中 App 平台的页面逻辑(page.js)上升,公共逻辑(common.js)下降,其主要原因是因为在该平台仅部分页面开启了多平台打包过程,抽取的公共模块(即大于两个页面共同引用的模块)比较少;

  Web 上的基础依赖(vendor.js)没有下降,其主要原因为基础依赖的模块并为标识为 sideEffects = false 缩小Tree-shaking影响的范围,降低本次重构造成的风险,当然如果把这部分模块也开启,可以得到更加明显的优化效果;

  App 上的基础依赖(vendor.js)下降 21.8%,其主要原因是App中对比H5端少了部分功能组件,而这些功能组件依赖的一些基础模块也被 Tree-shaking 消除了;

  这是前文留下的一个疑问,先抛出结论:没有一个简单快捷的方式来确认模块到底会不会被Tree-shaking。2020-01-24xg778.com假如放宽视线来看保持引育并重浓浓的

  这个也是官方教程中给的例子,如果这个模块的成员被标志成unused harmonyexport,就说明该成员没有外部引用使用到该成员,那么是可以将其安全去除的。东方心经马报。当然这里还有一种情况就是该成员没有被外部引用,但是被内部调用了,那这种情况也会把export语句和声明语句分离,只将export语句去除。

  有部分模块是只有暴露的成员,但是没有被引用的成员,这种模块会被直接消除。

  部分模块是自执行的,即本身自带副作用的模块,而我们通常会使用importxxx来进行模块引用,而不进行显示的调用。

  没错,这个第四个分类你没看错,部分被标注为 harmony export 的模块成员依旧会被消除掉。当然 Tree-shaking 最后是由著名压缩工具UglifyJS做的。如果你真的对这里的细节感兴趣,可以看一下 UglifyJS 跟以下压缩选项配置相关的代码:

  我们专注前端领域多年,负责过QQ资料、QQ注册、QQ群等亿级业务。目前聚焦于在线教育领域,精心打磨腾讯课堂、企鹅辅导及ABCMouse三大产品。返回搜狐,查看更多



友情链接:
www.097788.com,诸葛亮论坛,3460.com,www-3460.com,银河高手论坛,开奖记录,满地红开奖记录,手机看历史开奖记录。

本港台现场报码软件| ki72香港马会开奖结果| 六合现场开奖结果168| 香港六资料| 4887铁算盘资料开特马| 355555.com| 香港挂牌彩图| 九龙挂牌图库| 大红鹰报码聊天室| www.379988.com| 大赢家心水论坛官方网站| 手机看开奖结果找233|