打造基于Webpack的构建流程与性能改进
Posted 前端之巅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打造基于Webpack的构建流程与性能改进相关的知识,希望对你有一定的参考价值。
本文最初发布于 Medium 网站,经原作者授权由 InfoQ 中文站翻译并分享。
大家可能经常会有这样的经历:随着一个项目一天天成长,你也跟着添加了一个个的构建任务,并没有做过什么细致的优化。
然后在某一天你看了下自己的 package.json 脚本,它已经变成了类似这个样子:
使用 neo.mjs 框架就会是这样的结果。package.json 文件太大的话,调用“npmpublish”时就容易出问题,导致仓库超时;对于刚开始使用这个框架的开发新人来说,文件内容变成这个样子也很容易把人绕晕。
所以是时候来一次大规模的重构了。重构后新的 package.json 会变成这个样子:
当然,之前的任务还是一个不能少,而且接下来任务的数量很可能会进一步增长。
这篇文章讲的是如何调整 neo.mjs 框架:https://github.com/neomjs/neo
这个代码库是基于 MIT 许可分发的,因此就算你不直接使用它,也可以把它涉及的概念应用到自己的项目中。它应该能帮的上你的忙。
> node ./buildScripts/buildAll.js — help
> npm run build-all-questions1
程序源代码在下面的链接查看:
https://github.com/neomjs/neo/blob/dev/buildScripts/buildAll.js
> npm run build-all
并且所有子程序运行时都不会弹出问题。build-all 只是用来组合其他程序的切入点,因此它自己不会进行任何构建。
接下来我们来看一下 buildThreads 程序:
https://github.com/neomjs/neo/blob/dev/buildScripts/webpack/buildThreads.js
它与 buildAll 遵循相同的设计模式(其他程序也是如此)。
默认情况下,neo.mjs 使用 4 个线程:
main(默认顶级进程)
app(webworker)
data(webworker)
vdom(webworker)
与其他框架相比,这里的概念是非常独特的,因为这个框架的大部分内容以及使用它构建的应用都运行在 app 线程中。
每个 app 针对 main、data 和 vdom 都使用相同的构建,因此你很少需要构建这些线程。
main 线程非常模块化 =>你可以为框架配置自由选择插件。每个插件都会延迟加载(动态导入)。
将每个线程的基于 Webpack 的入口点隔离开来是很有意义的,因为在不同领域之间共享块是不可能的。
有关 main 线程插件的更多内容,请参考我以前的文章:
https://codeburst.io/using-js-libraries-inside-a-multithreading-environment-835cd8cbc30b
重点在于,每个 app 只会在其 index.html 文件中包含主块,并且 main 会根据需要导入要使用的 app。
由于 app 线程是 app worker 和你的应用代码的组合,因此不包含在 buildThreads 程序中。
https://github.com/neomjs/neo/blob/dev/buildScripts/webpack/buildMyApps.js
buildMyApps 为 apps 使用动态程序选项 =>它将显示存储库中的所有可用 apps(你可以使用 create-app 脚本创建新的 app)。
Covid Dashboard 应用就是一个很好的例子,它有大约 2500 行代码(不包括注释)。
在我的机器上,为开发环境构建它(未压缩,使用源映射)需要 0.98s。
生产环境的构建(压缩,没有源映射)结果差不多:1.05s。
像 neo.mjs RealWorld 这样的小型应用要快一些:
接下来我们看一下 buildThemes:
https://github.com/neomjs/neo/blob/dev/buildScripts/webpack/buildThemes.js
有黑暗和明亮两个主题可以选择。
我选择使用 SCSS 来实现它们,因为包装器允许我们生成(可选)是否包含 CSS 变量的输出(选项名称为 CSS4)。
构建过程使用的是 PostCSS,因此你无需使用前缀为不同的浏览器编写不同的规则。
这不是固定的途径,你也可以添加通过 JS 生成 CSS 的 PR(不过是否能与 PostCSS 一起使用就说不准了)。
使用 CSS var 的好处是,你可以轻松地为一个应用加入多个主题,并将这些主题应用在不同的部分。所有主题共享一个相同的 CSS 源,并为每种模式提供一个 CSS var 文件(假设你确实要使用 CSS var)。这样以来,就算你用了多个主题,对整体 CSS 文件大小的影响也会很小。
https://github.com/neomjs/neo/blob/dev/buildScripts/webpack/buildDocsExamples.js
从屏幕快照中可以看出,docs 应用也是 neo.mjs 应用。由于我们希望能够根据需要(延迟)加载示例应用,因此为 docs 应用和示例应用构建的 app 线程组合在了一起。
尽管 main 线程已经支持基于 Webpack 的块拆分,但是对于 app 而言这还是做不到的。具体原因相当复杂,但这个问题已经在处理计划上了。
neo.mjs 使用 jsdoc-x,可用来直接创建框架与你自己应用的文档输出。
在我的机器上总构建时间高达 140s+,这实在太不合理了。
我深入研究了 jsdoc-x 源代码,并创建了一个小的覆盖。现在对于 neo.mjs 上下文,构建时间减少到了只有 5s:
https://github.com/onury/jsdoc-x/issues/14
包括 npm install 在内,几乎所有内容的总构建时间减少到了 35.5s。
由于你很少需要 buildAll,因此这样的结果已经很不错了。
当我想将这个新版本部署到 Github 页面时(在线示例):
https://neomjs.github.io/pages/
Webpack 为拆分块创建了完全不同的输出。8 个 main 线程插件中有 6 个是正常的,而另外两个在路径内添加了一个 vendors 前缀,结果搞坏了输出。这肯定是因为将框架包含在了一个 node_modules 文件夹中。我用了一个小技巧修复了这个问题,更多细节在此:
https://github.com/webpack/webpack/issues/10949
谈了这么多关于新的构建程序的内容后,我觉得接下来有必要讲一下关于 neo.mjs 的最重要部分:
node 和 Webpack 应该是用来以 dist 模式构建和打包应用的工具。
开发应用时,如果能直接在浏览器内部运行基于 ES8 的真实代码(完全不需要构建)就太方便了。
你不需要源映射,不需要热模块替换,只需使用实际代码即可。
这确实节省了我很多时间。
公平地说,对于 neo.mjs 上下文而言,这只能用在 Chrome80+ 中,因为 Firefox 和 Safari 尚无法在 worker 内部支持 JS 模块。
但是,如果你创建自己的应用时只锁定在 main 线程上,那就可以利用新版 Chrome 浏览器的支持实现这个功能了。
如上所述,针对 app 领域的基于 Webpack 的块拆分仍处于发展阶段。对触摸事件的支持(类似于 Hammerjs)是一个很大的主题,我真正期待的是对共享 worker 的 JS 模块支持。
目前来说,我们可以创建基于 neo.mjs 的,可以运行在多个浏览器窗口中的 UI=>多显示支持。
https://medium.com/swlh/bundling-your-webpack-based-build-processes-performance-improvements-dd7d0ffdd788
以上是关于打造基于Webpack的构建流程与性能改进的主要内容,如果未能解决你的问题,请参考以下文章
从零开始配置webpack(基于webpack 4 和 babel 7版本)