仅在必要时在Node中重建
如果您的项目需要一些时间来准备 – 可能是编译或重写步骤 – 您可能需要等待的时间超过每次加载所需的时间。这让我们在Google的Santa Tracker h上h,我们使用Closure Compiler来构建大多数游戏。关闭是一个伟大的优化者,但它不知道速度。
所以这篇文章的主题是:慢速构建并不好玩,我们将学习如何只在需要时运行它们 ?
钟表原型
每次加载编译资源或手动重新运行脚本时,我们都可以使用NodeJS,而不是构建游戏,场景或代码库。 fs.watch
功能告诉我们我们是否真的需要。
从表面上看,这是一种简单的方法,可以告诉您文件在磁盘上的更改时间。像这样使用它:
常量 FS = 要求('FS'); FS。看('yourfile.txt', (事件类型, 文件名) => { //'yourfile.txt'发生了什么:¯ _(ツ)_ /¯ });
这是一种超级高效的方法,因为它要求您的操作系统在发生变化时通知您(不是相反,您的程序必须经常检查)。
构建用法
假设您正在编译一些Less CSS文件。你通过编译文件来做到这一点, entrypoint.less
,有依赖关系:
常量 减 = 要求('减'); 减。给予(`@import'intrypoint.less';`)。然后((产量) => { 安慰。信息(产量。CSS); //包含导入的所有文件,例如: // entrypoint.less => main.less => body.less //将导致('entrypoint.less','main.less','body.less') 常量 档 = 产量。进口; });
Less将为我们提供它在构建中使用的简单文件列表。其他一些工具可能会为您提供源映射,该映射还包含原始文件的名称。
如果这些文件中的任何一个发生更改,则最终输出无效,我们应该重建它。在实践中,这只是意味着呼唤 fs.watch
在每个文件上:?
常量 档 = 产量。进口; 档。的forEach((文件) => { FS。看(文件, () => rebuildIsNeededCallback()); });
这在技术上有效,但它还不适合整个构建系统。继续阅读 ??
注意事项
而 fs.watch
它是一个强大的功能,它有一些警告。这些可以归结为几点:
- 您无法始终确保告知哪个文件已更改
- 在Linux,macOS等上,
fs.watch
跟随被监视文件的inode- …如果文件被移动,您将收到有关其新位置变化的通知
- …如果文件被替换,您将收到一次通知,但不会自动监视新文件
- 你需要打电话
。关()
结果当你不再需要它时 – 如果你忘了,你的程序将保持开放的听众
在实践中,这些警告意味着您应该使用每次调用 fs.watch
作为一次性暗示某些事情发生了变化。 ?这样想:你不能确定究竟改变了什么,但值得检查
思考的另一个论点 fs.watch
作为一次性:如果你的依赖关系通过添加或删除文件而改变,那么重置所有观察者而不是试图保持最新状态可能更容易。 ?
看助手
让我们把上面的知识放在一起,帮助你在代码发生变化时使代码无效。这就是我们在Santa Tracker中所做的事情;我们保留构建输出,直到它不再有效(因为底层源已经改变)。
?您可能会说“为什么无效,而不仅仅是完全重建?”除非您需要尽可能快地输出,否则每次保存都会运行一个昂贵的编译步骤。
所以 看
下面的方法将接受路径列表,观察它们,并在其中任何一个更改(或超时通过)时调用回调:
功能 看(路径, DONE, 超时=0) { 让 观察家; 让 timeoutId; 常量 完 = () => { //为了完成,我们关闭观察者(因为它不清楚 //他们处于什么状态),取消超时回调, //让用户知道改变了什么。 观察家。的forEach((w ^) => w ^。关()); clearTimeout(timeoutId); DONE(); }; 如果 (超时 > 0) { //如果给出超时,则在超时后'成功'。这是 //对*总是*重建或在一段时间后失效有用。 timeoutId = 的setTimeout(完, 超时); } 观察家 = 路径。地图((p) => FS。看(p, 完)); }
请务必查看代码?,因为我已经留下了一些解释它的功能的评测。让我们把它与上面的Less示例结合起来。
少即是多
那么当依赖关系发生变化时,我们怎样才能使输出无效?
我们可以使用两个方法和一个缓存变量来做到这一点:
-
getCSS
哪个确保了诺言
包含结果可用;和 -
buildCSS
在需要时实际重建(因为这是异步
,它返回一个诺言
)。
让 compileCache; 异步 功能 buildCSS() { 安慰。调试('重建CSS ...'); 常量 产量 = 等待 减。给予(`@import'intrypoint.less';`); 看(产量。进口, () => { compileCache = 空值; //下次强制重建 }, 60 * 1000); 返回 产量。CSS; } //无论什么时候需要CSS,都可以调用getCSS,它始终是最新的 功能 getCSS() { 如果 (compileCache) { compileCache = buildCSS(); } 返回 compileCache; }
当然,这是一个非常简单的示例,只缓存一个结果:如果您想扩展它,您将使用输出字典,如果它们的依赖关系发生变化,每个输出都可以失效。
最后
最后联系起来 getCSS
对于这个世界,我现在为你最喜欢的NodeJS网络服务器添加一个处理程序,这样当我加载时说 /compiled.css
,它返回结果 getCSS
,确保编译版本始终是最新的。在波尔卡,它可能看起来像:
波尔卡() 。得到('/compiled.css', (REQ, 水库) => { 水库。结束(getCSS()); });
如果您对更多可能需要安装开发服务器的方法感到好奇,请在下面告诉我们 ?
谢谢
如果您直接使用现代盘点系统(或构建工具),那么该工具可能会使用 fs.watch
已经在引擎盖下。然而,我仍然希望你已经学会了如何使用它 fs.watch
改进你的构建系统
暂且不说:我个人已经停止使用类似的构建工具了 吞
和 咕噜
直接支持自定义构建工具或按需执行编译的Web服务器(由 fs.watch
,就像我们在Santa Tracker中所做的那样)。
1?