有没有一种方法可以预编译node.js脚本?

14

有没有一种方法可以预编译Node.js脚本并分发二进制文件而不是源代码文件?


是的,这似乎是可能的。V8引擎包含一个预解析器,可以做到这一点;V8构建过程使用它在构建时将JavaScript数组方法(这些方法是用JavaScript实现的)预编译为本机代码。我不知道细节 - 但这里有代码(http://code.google.com/p/v8/source/browse/trunk/#trunk%2Fpreparser)。 - JoeG
https://prepack.io/ 正在朝着这个方向发展,通过预先评估脚本来实现。虽然还没有准备好投入生产,但值得关注。"可以在编译时完成的计算将被消除,而不是在运行时完成"。 - protoEvangelion
1个回答

20

Node已经实现了这个功能

所谓的"这个功能"是指创建可执行机器二进制代码。它使用JIT模式来实现。关于这个,我会在讲解其他人可能搜索的内容之后再详细介绍...

本地操作系统二进制可执行文件... 如果你指的是本地操作系统可执行文件而不是源代码,那么是的。NW.JSElectron都做得非常好。

在你的node.js脚本中使用二进制文件... 如果你指的是将脚本的一部分编译成二进制文件,使其难以或不可能被利用,或者你想要一些具有本地机器速度的东西,那么是的。 它们被称为C/C++插件。你可以分发一个二进制文件(针对你特定的操作系统),并像使用任何其他var n = require("blah");一样调用它。

Node使用"Just In Time"二进制文件

Node默认会自行预编译您的脚本,并创建缓存的V8机器码(类似于“可执行文件”——它使用实际的机器码,该机器码是本地CPU上运行的),然后在处理每个事件时执行。

这里有一个谷歌参考文献,解释了V8引擎实际上是编译成真正的机器码,而不是虚拟机。

Google V8 JavaScript Engine Design

这种编译发生在应用程序首次加载时。

只要调用“require('module')”指令,它就将这些代码片段作为“模块”缓存起来。

它不会等待整个应用程序被处理,而是在遇到每个“require”时预先编译每个模块。

所有require内部的内容都会被编译并引入内存,包括其变量和活动状态。再次强调,与许多流行的博客文章相反,这是作为单独的机器码进程执行的。没有虚拟机,也没有解释器。JavaScript源代码实际上是编译成内存中的可执行文件。

这就是为什么每个模块只需引用相同的require,而不会创建大量开销。它只是引用内存中预编译和现有的对象,而不是“重新要求”整个模块。
您可以随时强制重新编译任何模块。很少有人知道您实际上可以轻松控制重新编译这些对象,从而使您能够“热重载”应用程序的某些部分,而无需重新加载整个应用程序。
这样做的一个很好的用例是创建自修改代码,例如从文件夹加载策略的策略模式,例如,只要添加了新文件夹,您自己的代码就可以将文件夹重新编译为内联策略模式,创建一个“strategyRouter.js”文件,然后使Node缓存失效以强制Node仅重新编译该模块,然后在将来的客户端请求中使用它。
最终结果:Node可以在您将新文件或文件夹放入应用程序时立即热重载路由或策略。无需重新启动应用程序,无需分离无状态和有状态操作:只需编写响应作为常规Node模块,并在更改时重新编译它们。
注意:在有人告诉我自修改代码与 eval 一样糟糕甚至更糟、很难调试且无法维护之前,请注意 Node 本身就是这样做的,许多流行的 Node 框架也是如此。我并不是在解释原创研究,而是在解释 Google 的 V8 引擎(因此也是 Node)的设计能力,正如这个问题要求我们做的那样。请不要开枪打 FM,否则人们将停止 R 它并保持沉默。
Unix 的设计并不是为了阻止用户做愚蠢的事情,因为这也会阻止他们做聪明的事情。 - Doug Gwyn
Angular 2、Meteor、新的基于 Node 的开源 Light table IDE 和其他一些框架正在朝着这个方向发展,以进一步将开发人员从代码中分离出来,使他们更加接近应用程序。
如何重新编译(热重载)所需的 Node 模块?
实际上非常容易... 这里有一个热重载 npm,如果想要其他选择,只需在 Google 上搜索“node require hot-reload”。

https://www.npmjs.com/package/hot-reload

如果我想要构建自己的框架并以一种惊人的新方式进行热重载呢?

像许多Node中的事情一样,这也是非常容易的。Node就像服务器上的jQuery! ;D

stackoverflow - 使Node的require缓存无效


2
本地操作系统二进制可执行文件 - 这正是我在寻找的! - nebulr
JIT 提供了良好的运行时性能,但以启动时间为代价。这几乎使得 Node 在命令行工具上无法使用。 - Justin Meiners
自 Node 7.5 开始,Node 会自动缓存第一次 JIT 的结果。你甚至可以将 JIT 缓存与你的包一起分发,以便从一开始就以二进制形式存在。 - Nick Steele
那么,如何构建、分发和运行“缓存的V8机器代码”? - Zibri
你是否想要分发JIT缓存,以便在第一次运行可执行文件时不会出现延迟?如果是,请查看我的答案:https://dev59.com/KJPea4cB1Zd3GeqP_y96...我在上面的答案中涵盖了您可能寻找的其他所有内容。如果您正在寻找特定/不同的内容,请告诉我。 - Nick Steele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接