Debug a Node.js application
Debugging against a remote environment, such as a VIP Platform environment, can be limiting and challenging. For this reason, it is recommended to debug Node.js application issues on a local development environment. Make an effort to reproduce issues locally, and to keep the local development environment in close synchronization with remote environments.
Avoid writing environment-specific code that runs on one environment type but is skipped on others (e.g., on Production but not on Develop). Environment-specific code can lead to issues that are very difficult to debug. If environment-specific code cannot be avoided, log liberally to clearly indicate when the conditional code is running, and when it is not.
Web browser developer tools
Most web browsers include developer tools that make it possible for developers to inspect network requests made by visitors to an application.
Using developer tools regularly in a local development environment is helpful for gaining a familiarity with the normal network activity generated by an application. This familiarity can be a helpful reference for recognizing issues before they are pushed to production. Be cautious when modifying some settings in the developer tools dashboard that might change the behavior of network requests (e.g., “Disable cache”).
cURL
cURL is a command-line tool that can be used to simulate requests to an application and provide a response for inspection. cURL commands are easily shared, enable issues to be replicated by multiple team members, and are a quick way to communicate the how and why of a problem.
By including the -I
option in a cURL command, only the response headers will be returned in the output. Header responses can provide insights into page cache behavior, payload size, and more.
In this command example, curl -I
is run against a VIP Platform Node.js application running at https://nodejstestsite.go-vip.net
:
$ curl -I "https://nodejstestsite.go-vip.net/latest/post" HTTP/2 200 server: nginx date: Tue, 14 Jun 2022 15:40:40 GMT content-type: text/html; charset=utf-8 content-length: 5160 x-powered-by: Next.js cache-control: public, max-age=300 age: 4 x-cache: hit vary: X-Mobile-Class, Accept-Encoding accept-ranges: bytes strict-transport-security: max-age=31536000
In the example command output above:
- The returned HTTP status code
200
indicates a healthy response. - The
x-cache
header is evidence that the request passed through the VIP Platform’s page cache, and the header’shit
value indicates that the response was served from cache.
cURL can also be used to expose and investigate problems.
In this command example, curl -I
is run against http://localhost:3000
:
$ curl -I "http://localhost:3000" curl: (7) Failed to connect to localhost port 3000 after 9 ms: Connection refused
The command output returns a “Failed” message instead of an HTTP status code, indicating that no application is listening on port 3000.
Limitations
cURL is a powerful tool but it does not behave the same way as a web browser. In particular, requests made with cURL do not automatically send the request headers that are typically sent by some web browsers. If an application’s behavior varies based on the presence of browser-specific request headers, use the “Copy as cURL” feature provided by many web browser’s development tools. This will ensure that the cURL requests will include the expected request headers.
Node.js inspector
Node.js includes a debugging inspector that allows developers to set breakpoints, step through code, inspect variables, and more—for both client and server-side applications. Most web browsers include a client that connects to the inspection port opened by Node.js and provides a graphical interface for debugging. This approach can be more effective than “manually” debugging an application, and is worth the time required to set it up.
Instructions for enabling the inspector—as well as a command-line debugging utility option—can be found in Node.js documentation.
Caution
For security reasons, only run the Node.js inspector on local, non-public applications.
Logging
Logging can be used to inspect requests and responses as they flow through an application’s code. Logging is useful for gathering context around issues and debugging them, especially in remote environments.
On the VIP Platform, console.*
can be used by Node.js applications to log information and make it available in application logs. For maximum readability, always convert non-string values to strings (e.g., using JSON.stringify
).
Knowing what and where to log is critical to logging effectively. Next.js and Apollo are two examples of useful locations within certain frameworks and libraries where logging can be most effective.
Next.js
Next.js recently introduced the construct of middleware, which provides a way to inspect every request and potentially modify the response. The main function of Next.js middleware is to respond to health checks, but it can also be extended to log information about incoming requests. An example implementation of middleware is provided in the vip-go-nextjs-skeleton GitHub repository.
Apollo
Apollo is a GraphQL client that is used for communication between a Node.js front end and a WordPress back end. ApolloLink
is an Apollo module that makes it possible to customize the flow of data between the Apollo client and the GraphQL server. ApolloLink
is a useful location to add logging, and can be helpful for understanding data that is requested by an application. A custom ApolloLink
for logging information about requests is included in vip-go-nextjs-skeleton and can be used to correlate front-end and back-end requests.
Last updated: February 29, 2024