中英文模式阅读
中文模式阅读
英文模式阅读

How to Inspect Node.js with Grunt-SWATCH (!watch) and Fiveo

I know, I know... the socket in the cover picture isn't really the type of socket we're talking about in this post, but I've been preoccupied lately with the idea of building a new workstation and the
我知道,我知道......封面图片中的插座并不是我们在这篇文章中讨论的插座类型,但最近我一直专注于构建新工作站的想法ThreadRipper is a monster! I mean it might actually be the solution to never feeling like my computer is never fast enough no matter what I upgrade to using (right now it's an Intel I7 8th Gen CPU).
是一个怪物!我的意思是它实际上可能是解决方案,从不觉得我的计算机永远不够快,无论我升级到使用什么(现在它是Intel I7第8代CPU)。

Every desktop/workstation I've ever used over the years (well there was one) has always left a lot to be desired. Waiting on your computer to COMPUTE sucks! Screen glitches, seemingly never ending progress spinners, lag time, and the like really break up productivity and workflow.
我多年来一直使用的每台桌面/工作站(有一台)总是有很多不足之处。在你的电脑上等待COMPUTE糟透了!屏幕故障,似乎永无止境的进度旋转器,滞后时间等真正打破了生产力和工作流程。

Anyway on to the topic and away from the...
无论如何关于主题,远离...Tangent

NodeBB (Node.js Forum) Hacking {#nodebb-node-js-forum-hacking}

As I've written about recently, my hacking time of late has been spent on the forum software NodeBB. The build process that the developers of NodeBB put into place relies on the Grunt task runner, which itself is also build with Node.js. It's great when you can work within an ecosystem built primarily upon the frameworks you enjoy the most (for example Node.js ❤️).
正如我最近所写的那样,我最近的黑客攻击时间已经花在了论坛软件NodeBB上。 NodeBB开发人员的构建过程依赖于Grunt任务运行器,它本身也是用Node.js构建的。当你可以在一个主要基于你最喜欢的框架构建的生态系统中工作时(例如Node.js❤️),这很棒。

However when it comes to debugging, and when your build tooling and other layers of software are all built with Node.js, sometimes things get a little tricky. Like when you want to pass the
但是,当涉及到调试,以及当您的构建工具和其他软件层都使用Node.js构建时,有时事情会变得有点棘手。就像你想要通过时一样--inspect flag to node executable to start a debugging session, having the intent of debugging your plugin code, and not the layers above it (Grunt, NodeBB).
标记到节点可执行文件以启动调试会话,目的是调试插件代码,而不是它上面的层(Grunt,NodeBB)。

I am not aware of any command line options specific to the Grunt cli that can be used to pass your intent to start a Node debugging session down to the task level. I tried several things to no avail, however there were still a few options to get it done:
我不知道任何特定于Grunt cli的命令行选项,可用于将启动Node调试会话的意图传递到任务级别。我尝试了几件事无济于事,但仍然有一些选择可以完成它:

  1. Start Grunt by calling Node directly, ala node --inspect /path/to/grunt
  2. Start the Node Inspector programmatically using the still experimental Inspector API
  3. Start the Node Inspector after the fact using Linux signals, SIGUSR1 to be exact.

Tradeoffs {#tradeoffs}

Of course, each of these solutions provided obstacles of their own, and as with most things included both positive and negative aspects!
当然,这些解决方案中的每一个都提供了自己的障碍,并且大多数事情包括积极和消极方面!

In this post I'll talk about each of these solutions, detailing the issues I faced using each one. We will see how leveraging the Inspector API made the
在这篇文章中,我将讨论这些解决方案中的每一个,详细说明我使用每个解决方案时遇到的问题。我们将看到利用Inspector API如何利用NPM module fiveo possible, and how that tool makes using Linux signals with Node.js even more powerful. And finally I will show how in the scenario presented herein, option #3 proved to be the best solution. And how choosing option #3 served as a catalyst to write the grunt-swatch plugin, what that plugin currently does, and what it could do with a little more work.
可能,以及该工具如何使用Node.js的Linux信号更加强大。最后,我将展示如何在此处提供的方案中,选项#3被证明是最佳解决方案。选择#3选项如何成为编写grunt-swatch插件的催化剂,该插件目前的功能,以及它可以做多少工作。

So this command works perfectly well to start the debugger:
所以这个命令可以很好地启动调试器:

node --inspect /home/batman/.nvm/versions/node/v10.16.0/bin/grunt

and grunt will continue doing its thing which is to perform a bunch of build steps before actually starting the NodeBB server. Yet, note the important fact that starting that initial Node process by calling node with
并且grunt将继续做其在实际启动NodeBB服务器之前执行一系列构建步骤的事情。然而,请注意通过调用节点来启动初始Node进程的重要事实--inspect is going to present its own challenges when Grunt launches entirely new processes.
当Grunt推出全新流程时,它将面临挑战。

Wonderfully when node child processes are started and the parent process has been called with the inspect flag set, the children will inherit that setting. But it's for that same reason that if you call node with
很奇怪,当启动节点子进程并且在设置了inspect标志的情况下调用父进程时,子进程将继承该设置。但是出于同样的原因,如果你用节点调用节点--inspect as we did, you are faced with these nice messages 😒 staring at you in the console:
就像我们一样,你面对这些好消息😒在控制台里盯着你:

failed: address already in use

Those
那些failed: address already in use messages occur because the inspector, which is a socket server, has already been started on the parent process which in our case is Grunt. Thus when the children start with the inherited
消息的发生是因为作为套接字服务器的检查器已经在父进程上启动,在我们的例子中是Grunt。因此,当孩子们从遗传开始--inspect flag who's default arguments are set to
flag的默认参数设置为localhost:9229, Node tries to start up the inspector socket server (we'll call it the "
,Node尝试启动检查器套接字服务器(我们称之为" inspect process " from now on) using the default port 9229.
"从现在开始"使用默认端口9229。

A workaround for this would be to change our initial command to:
解决方法是将我们的初始命令更改为:

node --inspect=0 /home/batman/.nvm/versions/node/v10.16.0/bin/grunt

The
"=0" causes the inspect process to choose a random port, as you can see 39380 and 46704 have been chosen.
导致检查过程选择随机端口,如您所见,已选择39380和46704。Random Insepctor Ports

Which is great because now we have two inspector processes running! The part that is not so great is that we don't care about either of them... yet.
这很好,因为现在我们有两个检查程序进程在运行!不那么伟大的部分是我们不关心它们中的任何一个......

NodeBB's Build Setup {#nodebb-s-build-setup}

I can't completely explain the
我无法完全解释 WHY of the
Grunt flow that makes up NodeBB's Gruntfile:
组成NodeBB的Gruntfile:NodeBB Gruntfile.js snipit

But I can say that
但我可以这么说 WHAT it is doing is basically forking an initialization sequence which takes care of building the css, language files, templates, building/bundling Javascript, etc... and then a second process is being forked to actually start the NodeBB server with assets ready and good to go.
它正在做的基本上是分配一个初始化序列,它负责构建css,语言文件,模板,构建/捆绑Javascript等等......然后第二个进程被分叉以实际启动NodeBB服务器,资产准备就绪并且良好去。

Going further, each time a change is detected thanks to the watch process (
更进一步,每次检测到更改都归功于监视过程(grunt-contrib-watch), the current NodeBB process is killed and new one started. And with that new process comes... exactly, a new random debug port is going to be generated upon each cycle.
),当前的NodeBB进程被终止并且新的进程被启动。随着新流程的到来......确切地说,每个周期都会生成一个新的随机调试端口。

Which again complicates our debugging efforts and raises a few questions.
这再次使我们的调试工作变得复杂并提出了一些问题。

  • How do we keep track of all of these random inspector ports?
  • Further as we are working on a remote server, how do we handle port forwarding?
  • Do we really care about the intermediate inspector sessions?

While we ponder 🤔 on those, let's fork ourselves to...
当我们思考那些时,让我们自己去......

Doing so requires a more "invasive" approach when it comes to our initial desire to debug OUR own code. This option requires the inclusion of the inspector module, which in and of itself isn't a big deal. We require code all the time and the inspector module is a core Node.js module, and not some 3rd party piece of code.
当我们最初想要调试我们自己的代码时,这样做需要更具"侵入性"的方法。此选项需要包含检查器模块,这本身并不是什么大问题。我们一直需要代码,检查器模块是核心Node.js模块,而不是一些第三方代码。

But, for that module to really be of any use, additional code must be written and added to our codebase.
但是,为了使该模块真正有用,必须编写额外的代码并将其添加到我们的代码库中。

const inspector = require('inspector')

To be quite...
要相当......

stepped away to hack on some other code...

Last Night! {#last-night-}

So last night while I was writing this, I was starting to write that
所以昨晚我写这篇文章时,我开始写这篇文章了 to be quite honest, I hadn't given the inspector module much of a look before. And while doing so in the effort to write this post in the most informed manner possible, I was sent down a bit of a rabbit hole.
说实话,我之前没有给过检查员模块。虽然这样做是为了尽可能以最明智的方式写这篇文章,但我还是被送了一个兔子洞。

One of which I emerged from having written a tiny library that adds some sugar on top of the core inspector module, which as it turns out is pretty cool. Now, after having written said tiny library, I would recommend that instead of requiring the inspector module, one would be better off using
其中之一我从编写了一个小型库,在核心检查器模块的顶部添加了一些糖,结果证明它非常酷。现在,在编写了这个小型库后,我建议不要使用检查器模块,最好不要使用fiveo which in turn does that for you, while adding some nifty features such as using a port other than 9229 sort of like
这反过来为你做了,同时添加一些漂亮的功能,如使用9229之类的端口this GitHub issue is about.
是关于。Fiveo Demo Gif

Still, you may not like my tiny library 🙁, and you may be uninterested in writing your own. The fact that using the inspector api requires adding additional code to your own still exists. And that might be a factor which makes this second option a bad choice for your project. Which leads us to the 3rd and final option...
不过,你可能不喜欢我的小图书馆,你可能对编写自己的图书馆不感兴趣。使用检查器api需要向您自己添加额外代码的事实仍然存在。这可能是使第二个选项成为您项目的不良选择的一个因素。这导致我们进入第三个也是最后一个选项......

So ultimately the best solution I found was to use UNIX/Linux
所以最终我找到的最佳解决方案是使用UNIX / Linuxsignals. That's a link to the manpage which gives you an overview of what signals are exactly. The long and short of it is that signals can change the behavior of processes that receive them.
。这是一个指向联机帮助页的链接,可以让您全面了解哪些信号是准确的。它的长短是信号可以改变接收它们的进程的行为。 Note that signals are not supported on Windows. And from Node's official docs:
来自Node的官方文档:

Node.js will also start listening for debugging messages if it receives a SIGUSR1 signal. (SIGUSR1 is not available on Windows.)
如果收到SIGUSR1信号,Node.js也将开始侦听调试消息。 (SIGUSR1在Windows上不可用。)

The Plan {#the-plan}

The overall idea is that we can deliver the SIGUSR1 signal to the Node process specific to our code at the time we need it, and not before then, thus eliminating all the noise that we don't care about. Noise like what NodeBB is doing during the init phase (remember it forks a bunch of stuff), or what the Grunt code is getting into, etc.
总体思路是我们可以在需要时将SIGUSR1信号传递给特定于我们代码的节点过程,而不是在此之前,从而消除了我们不关心的所有噪声。像NodeBB在初始阶段所做的那样的噪音(记住它分叉了一些东西),或者Grunt代码进入的内容等等。

The point that we're ready to start the debugger is the point after Grunt does its init tasks, starts the NodeBB server, and the forum can be reached via the port it's configured to run on
我们准备启动调试器的重点是Grunt执行其init任务,启动NodeBB服务器之后的点,并且可以通过配置为运行的端口访问论坛tcp/45670. At that time we need to determine the process id that NodeBB is listening on, because we need a process id in order to deliver our signal to the appropriate place. Upon receiving the
。那时我们需要确定NodeBB正在监听的进程ID,因为我们需要一个进程ID来将信号传递到适当的位置。收到后SIGUSR1, Node will start the inspector process and we can begin debugging!
,Node将启动检查程序进程,我们可以开始调试!

What we just described in the preceeding paragraph is exactly what our Grunt plugin
我们刚才在前一段中描述的正是我们的Grunt插件 grunt-swatch does. It's similar to
确实。它类似于 grunt-contrib-watch in that it continuously watches for changes in your environment, the difference is in that
因为它不断观察你环境的变化,不同之处在于 grunt-swatch doesn't watch the filesystem but rather the network, thus the name, derived from
不看文件系统而是网络,因此名称来源于 socket watch .

grunt-contrib-watch
咕噜-的contrib手表

Run predefined tasks whenever watched file patterns are added, changed or deleted
每当添加,更改或删除监视文件模式时,运行预定义任务

One should be able to write other "actions" for the plugin, however I've only written the nim (aptly named but also a callback to
一个应该能够为插件编写其他"动作",但是我只编写了nim(恰当命名但也是一个回调函数)NiM) action
)行动nim.js:
Code for nim action showing SIGUSR1

You can see that it's rather simple in what it does, but exactly what we need. It uses the Linux
您可以看到它的功能相当简单,但正是我们所需要的。它使用Linuxkill command (also
命令(也是an entertaining Sci-Fi by the way!) to send the
顺便说一句!)发送SIGUSR1 signal to our
发信号给我们 swatched process. As you can see the
处理。正如你所看到的那样close() function currently doesn't do anything and that's because prior to writing
函数目前没有做任何事情,那是因为在写作之前fiveo, there was no way to close the Node inspector via the signal method. However with fiveo included, we have access to
,无法通过信号方法关闭节点检查器。但是如果包含fiveo,我们可以访问SIGUSR2 which can close the inspector process... leaving things a bit more tidy 🧹.
这可以关闭检查员的过程......让事情更加整洁🧹。Code for nim action showing SIGUSR2

And here is the output where you can see from the
以下是您可以从中看到的输出swatch:nim log output, that the nim action is actually closing the Node inspector socket that was previously opened. In the screenshot below you can see the complete open/close cycle of this websocket:
日志输出,nim操作实际上是关闭先前打开的节点检查器套接字。在下面的屏幕截图中,您可以看到此websocket的完整打开/关闭循环:ws://localhost:9230/b26fc131-af5e-4943-b911-a25b4261e43c
Log for nim action showing SIGUSR2

Grunt with my grunt-swatch task loaded and configured appropriately will ensure that during my development process, the inspector will intelligently be stopped and started when I need it to.
Grunt与我的grunt-swatch任务相关地加载和配置将确保在我的开发过程中,检查员将在我需要时智能地停止并启动。

grunt.loadNpmTasks('grunt-swatch')

Further
进一步NiM will ensure that DevTools is always right where I need it, opened to the correct inspector websocket and ready to go.
将确保DevTools始终在我需要的地方,打开正确的检查员websocket并准备好。NiM Popup Screenshot

And there we have it. By using grunt-swatch, fiveo, along with
我们终于得到它了。通过使用grunt-swatch,fiveo,以及NiM the
Chromium Extension, our NodeBB plugin development workflow is greatly improved! I certainly don't miss the manual process of running this command over, and over, 🔁 and over again:
,我们的NodeBB插件开发工作流程大大改进!我当然不会错过这个命令的手动过程,反过来,🔁和重复:

pid=`netstat -lnp|grep 45670|awk 'BEGIN {FS=" "}{print $7}'|cut -f1 -d"/"'`
kill -SIGUSR1 $pid

Some next steps could be to devise a method of communicating to the debugee process in order to change the debugger port dynamically. To be able to set the debug port from the Grunt config and in essence force the Node application to open a debugger on a preconfigured (in development, post runtime) port would be ideal!
接下来的一些步骤可能是设计一种与debugee进程通信的方法,以便动态地更改调试器端口。为了能够从Grunt配置设置调试端口,实质上强制Node应用程序在预配置(开发中,后运行时)端口上打开调试器将是理想的!

I hope you found this post helpful. Here are the relevant links to stuff:
我希望你发现这篇文章很有帮助。以下是相关链接:

中英文模式阅读
中文模式阅读
英文模式阅读

查看英文原文

查看更多文章

公众号:银河系1号
公众号:银河系1号

联系邮箱:public@space-explore.com
联系邮箱:public@space-explore.com

(未经同意,请勿转载)
(未经同意,请勿转载)