7

NEJ Build太慢怎么办?试试MOOC NEJ吧,只需两步,提升70%构建性能!

 3 years ago
source link: https://my.oschina.net/youdaotech/blog/5294274
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

NEJ Build太慢怎么办?试试MOOC NEJ吧,只需两步,提升70%构建性能!

由于历史包袱,中国大学MOOC(简称中M)的主站工程生产构建时间大约在21分钟,构建采用NEJ Build,由于NEJ当前已无人维护且在部门内应用较多,因此中M通过fork原工程在保留NEJ原有功能的前提下,将NEJ的核心打包流程进行改造升级,并提出一套通用解决方案即MOOC NEJ。MOOC NEJ已于今年年初上线验证,构建时长缩短至6分钟,提升70%构建性能,经过8个月的线上稳定运行,暂未发现由迁移引起的问题。

作者 / 徐佳露

编辑 / 李轶楠(实习)

youdao

一、历史背景

ydtech

中国大学MOOC(以下简称中M)和许多网易前端er一样在过去几年搭建工程使用的框架为RegularJS与NEJ,同时在打包上采用NEJ的工具集toolkit2即NEJ Build(https://github.com/genify/toolkit2)

在项目的开始总是愉快的,那时候开发维护NEJ的人还在(甚至还可以提一些feature),业务项目的人也还在,代码量总是清清爽爽,构建的时光总是“咻”一下就过去了。

9c042302-feb1-4e99-bc9e-2c9993dba0de.jpg

然而!时间过去了三五年,当我接手到中M主站这个项目的时候,它的构建时间已经达到了将近21分钟。

167c84b9-2c5c-4450-8da4-0016768eeee1.png

平时等就等呗,最多在后端大佬部署的时候提前构建好等着,要命的是上完线已经10点了,这时候测试大佬来报:后端没问题了,前端这里有个问题修一下。

然后,大概就是修复5分钟,打包验证半小时。。。。。同时保佑不要再出(deng)一(ban)个(ge)问(xiao)题(shi)。

0fe2bf5e-bcc6-4535-9f57-a168cd24238d.jpg

youdao

二、究竟为啥这么慢?

ydtech

速度慢的原因有两方面: 1. 中M工程架构: 由于历史原因,中M的主站将web和mobile端以及一并放在front-main项目下,同时,加载了两个看不出来有什么区别的超大lib,导致需要打包的文件非常多,东西多了自然就蚌埠住了。 02622d3c-4333-4e7d-a7b6-8784555b4e5c.png

2. NEJ合并策略

toolkit有一个合并策略的参数来决定一个文件引用计数超过多少次将合并入core.js,当这个参数设置的越大,core.js的size将越小,构建时间就越长。我们之前为了快速提高开发效率,在测试环境将该参数调至6,打包时间约11分钟,而预发和线上该参数在13,打包时间约21分钟。(毕竟我们不能因为想要打包快,就粗暴的使生产环境的资源变大😖)

youdao

三、NEJ的合并策略为何影响打包速度【核心原理】

ydtech

由于NEJ已早早无人维护,但万幸它是开源的,咱们虽然找不到作者,但是可以通过对toolkit2的源码阅读来找到答案,我大致梳理了一下NEJ打包的流程。

fd9ca08e-0db9-4d6a-bf1d-c958a4a35355.jpg

1. toolkit2全过程使用同步打包,每一步的处理结果都通过one by one的接力形式来传递。

2.toolkit2打包的本质是通过对合并策略(就是二.2提到的参数)等参数将每个文件的代码转成抽象语法树(AST),再对AST通过UgilifyJS进行压缩混淆。

看起来这个流程没什么问题,因为AST和UgilifyJS在现在也都是很主流的操作(如webpack也是使用UgilifyJS),对前端来讲是再熟悉不过了。 那么为什么会导致打包慢呢?
直到我看到了AST的生成过程: 1. 先将所有文件通过concat生成一个大AST(源码的lib/adapter/script.js的_mergeCodeAndToAST 7ecb2e5d-6dfc-4916-bd38-54aa4b32b40b.png2. 对且仅对这一个AST进行Uglify压缩混淆(源码的lib/adapter/script.js的parse) 527d247c-3f52-4bde-bced-4a4498041f9d.png 结合中M主站的历史架构,当我打印出这一个AST时, 单主站web端的Core.js就大概由400个小AST形成。。。。 然后它就开始压缩。。。。 然后它就卡住了。。。。住了。。。。了。。。。 5a8c6884-510a-4d01-bac1-8768f5cd9e62.png

youdao

四、解决方案考量

ydtech

针对当前我们对自身工程和NEJ的了解,我们大概有以下几个思路去对打包时间进行优化:

【针对中M主站工程】

1. 老生常谈的拆分工程&重构迁移:拆分需要对业务足够了解,才能对其做领域拆分。重构代价太大。同时功能回归点太多。目前一部分功能由于迭代需要已用React+Webpack做了替换。

2. webpack替换nej:需要兼容regular和nej模块,且对老项目内部也要替换webpack所需插件,成本较大。

【针对NEJ工具集】

1. Uglify2.0升级3.0:3.0有一个快速打包模式,但经过测试,3.0有部分不向下兼容的api,nej有用到。(此处有踩坑经验)

2. 多进程打包:不改造打包产物,只变更打包流程,成本可控,上线后风险较小,如遇到紧急问题可快速回滚至nej build,风险可控

最终,我们选择了给NEJ架上webpack同款多进程功能,打包需要什么,我们就造什么。

youdao

五、实现架构

ydtech

我们并不想多造一个轮子,来做一些颠覆性的改变,使性能得到提升的同时,写的人也难受(考虑太多写一些冗余代码),使用的人也难受(迁移成本高)。 因此我们选择将toolkit2 fork下来,将其所有的api保留、功能保留,不影响任何老功能的使用姿势,只修改关键路径,缩小改造和迁移成本。 我们的大致思路是这样: 306c155f-baa6-47ed-a6c8-883776f0b0c9.png

1. 不对ast做concat操作,每个文件单独uglify

2. 参考uglify-webpack-plugin插件的多进程思路,将每个文件作为task,并发打包

(我又去看了一下uglify-webpack-plugin的源码,做了一张图,毕竟知己知彼才能顺利改造。)

8aef76f0-b5cd-4ef8-9903-4e0fd79404ec.png

3. 将同步流程改成异步,完成所有task后回调结果,调用后续操作。

youdao

六、代码实现

ydtech

fork目录后,新增一个cluster文件夹用于存放多进程流程。

ef14146e-6276-4493-b469-6ccce5be1384.png

1. minifiy.js:执行ugilify压缩操作,生成压缩混淆后的ast和string代码;

2. TaskRunner.js:利用worker-farm来进行任务的分发、执行、计数、回调等;

3. worker.js:worker-farm必须要新建一个workerfile才能使用,这个workerfile用于承接;

再配合修改原文件lib/adapter/script.js 1. _mergeCodeAndToAST:取消concat以及this.ast的生成; 2. parse:增加callback参数,根据filename、file、minify参数创建task,run each task,并执行callback; 配合修改原文件lib/deploy.js 1. _afterResPrepared:将最后的embed(将变量嵌入css、js、html)操作改成异步,作为callback传入,等待完成所有的压缩后,执行最后输出前的embed操作。

youdao

七、使用方式&迁移(安利)

ydtech

说了这么久,终于要开始迁移,还记得标题吗, 只需两步!无忧迁移! 不影响任何老功能的使用! 第一步:安装mooc-nej(目前稳定版本在0.3.0,0.4.0尚属beta版本,正在内测中)
npm install @edu/toolkit3 -g 第二步:使用它,甚至不用修改命令,只需将nej build替换为mooc-nej即可

// 所有的nej build改成mooc-nej build即可

mooc-nej build deploy/mobile/release.js


// 或者构建机安装直接引用build文件

<property name="mooc-nej-build.js"  <="" span="">

value="/home/appops/study/install/node_modules/@edu/toolkit3/bin/build.js"/>

<exec dir="." executable="${mooc-nej-build.js}"failonerror="true">

<arg line ="${ob_baseline.dir}/deploy/web/release.js"/>

</exec>

backup:如果你发现有问题,还可以快速回滚到nej build。

youdao

八、生产验证

ydtech

4c242113-961d-4833-816d-541a85d181ee.png 中M在年初就已经使用上了mooc-nej, 目前稳定运行半年有余,暂未发现任何由迁移引起的bug。请大家放心食用。

youdao

九、总结

ydtech

大概从开始改造到结束改造用了去年12月的日常空余时间,其间的心路历程大致是:

😢(打包好久555)

🤔(什么东西卡这么久)

😯(哇发现了原因)

😎(改造,冲!)

😏😤😏😤😏😤...(改完了挂了...又改完了又挂了...*n)

🤨(换个思路)

💓(忐忑验证)

😁(成功上线)

但是回头看,这些踩坑都是值得的,我们终于不用再漫长的等待构建了!

-END-

da206b4e-8ea5-4935-8742-f22c16ac6010.png

往期推荐

本文分享自微信公众号 - 有道技术团队(youdaotech)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。


Recommend

  • 96

    只需两步,把你的电脑变成局域网文件共享中心 | 一日一技

  • 56

    第一次在掘金这样高大上的社区写文章,忐忑地敲下我获取小程序源码过程中的经验分享。 最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了一个滴滴他们家的青桔单车小程序的前端实现,过程一言难尽,差不多两周时间过去了,发现小程序的...

  • 10

    Hello,大家好,我是楼下小黑哥~ 今天原本是想解析一道朋友在大厂面试的时候碰到问题: 「Dubbo 异步调用的底层原理是什么?」 之前其实听说过 Dubbo 异步调用,但是没有在实际业务中使用过,所以使用方法比较陌生。 再...

  • 14
    • segmentfault.com 4 years ago
    • Cache

    github 访问太慢,怎么办 ?

    github 访问太慢,怎么办 ?发布于 3 分钟前https://segmentfault.com/a/11...mac方案打开hos...

  • 10

    TJ君最近有点惆怅,为啥呢?最近TJ君发现GitHub越来越难上了,有时候经常出现无法访问的情况: 想必很多人也会跟TJ君有同样的烦恼,毕竟GitHub是一个学习编程的好地方,这样断断续续的使用,极度影响吾等程序猿的用户体验,那,该怎么办!? 既然...

  • 9

    计算速度太慢?试试 lru_cache 装饰器发布于 今天 14:14 众所周知,python语言是相当好用的,但是它的执行性能也是相对其他语言比较慢的。还好python提供了一个非常...

  • 6

    只需两步,就可以在Windows 11操作系统上运行Android程序,非常简单-51CTO.COM 只需两步,就可以在Windows 11操作系统上运行Android程序,非常简单 作者:微课传媒 2022-02-27 23:14:33 现在,在...

  • 7

    我们在学习 51 单片机的过程中会用到延时,比如一个简单的流水灯就需要延时来控制依次点亮的时间,或者一些模块在单片机发出读数据指令后,需要延时几十微秒才可以读出数据等等,这些都离不开延时,所以我们需要一个精准的延时函数来满足我们的需求。 本篇介...

  • 11

    原先存在 google autheticator 的 2fa 两步验证的手机弄丢了怎么办? V2EX  › 

  • 14

    🔒 Telegram两步验证密码忘记了怎么办?🔐 https://www.chenweiliang.com/cwl-30523.html 如果你在使用Telegram时忘记了两步验证密码,别担心!你可以通过重置二次验证初始密码来恢复你的海外账号。🌍 🔑 我们为您提供了一个简单的解决方案

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK