{"id":11377,"date":"2022-07-22T18:07:31","date_gmt":"2022-07-22T18:07:31","guid":{"rendered":"https:\/\/docs.wpvip.com\/?post_type=how-tos&#038;p=11377"},"modified":"2026-01-01T17:26:13","modified_gmt":"2026-01-01T17:26:13","slug":"debug","status":"publish","type":"page","link":"https:\/\/docs.wpvip.com\/node-js\/debug\/","title":{"rendered":"Debug a Node.js application"},"content":{"rendered":"\n<p>Debugging against a remote environment, such as a <a href=\"https:\/\/docs.wpvip.com\/vip-platform\/environments\/\">VIP Platform environment<\/a>, 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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<div class=\"a8c-docs-note-block general\">\n<p><strong>Note<\/strong><\/p>\n\n\n\n<p>VIP Support does not provide assistance with questions or issues related to the application code of a Node.js application. Node.js applications are not eligible for the debugging feature regardless of <a href=\"https:\/\/wpvip.com\/pricing\/\">the contracted pricing plan<\/a> that an organization has with VIP. <\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-web-browser-developer-tools\">Web browser developer tools<\/h2>\n\n\n\n<p>Most web browsers include <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/Common_questions\/What_are_browser_developer_tools\">developer tools<\/a> that make it possible for developers to inspect network requests made by visitors to an application. <\/p>\n\n\n\n<p>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., &#8220;Disable cache&#8221;).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-curl\">cURL<\/h2>\n\n\n\n<p><a href=\"https:\/\/curl.se\/docs\/manpage.html\">cURL<\/a> 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 <em>how<\/em> and <em>why<\/em> of a problem.<\/p>\n\n\n\n<p>By including the <code>-I<\/code> 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. <\/p>\n\n\n\n<p>In this command example,&nbsp;<code>curl -I<\/code>&nbsp;is run against a VIP Platform Node.js application running at&nbsp;<code>https:\/\/nodejstestsite.go-vip.net<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ curl -I \"https:\/\/nodejstestsite.go-vip.net\/latest\/post\"\nHTTP\/2 200\nserver: nginx\ndate: Tue, 14 Jun 2022 15:40:40 GMT\ncontent-type: text\/html; charset=utf-8\ncontent-length: 5160\nx-powered-by: Next.js\ncache-control: public, max-age=300\nage: 4\nx-cache: hit\nvary: X-Mobile-Class, Accept-Encoding\naccept-ranges: bytes\nstrict-transport-security: max-age=31536000<\/pre>\n\n\n\n<p>In the example command output above:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The returned HTTP status code&nbsp;<code>200<\/code>&nbsp;indicates a healthy response. <\/li>\n\n\n\n<li>The <code>x-cache<\/code> header is evidence that the request passed through the VIP Platform&#8217;s <a href=\"https:\/\/docs.wpvip.com\/caching\/page-cache\/\">page cache<\/a>, and the header&#8217;s <code><a href=\"https:\/\/docs.wpvip.com\/caching\/page-cache\/#h-review-details-about-cache-behavior\">hit<\/a><\/code> value indicates that the response was served from cache.<\/li>\n<\/ul>\n\n\n\n<p>cURL can also be used to expose and investigate problems. <\/p>\n\n\n\n<p>In this command example, <code>curl -I<\/code> is run against <code>http:\/\/localhost:3000<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ curl -I \"http:\/\/localhost:3000\"\ncurl: (7) Failed to connect to localhost port 3000 after 9 ms: Connection refused<\/pre>\n\n\n\n<p>The command output returns a &#8220;Failed&#8221; message instead of an HTTP status code, indicating that no application is listening on port 3000. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-limitations\">Limitations<\/h3>\n\n\n\n<p>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&#8217;s behavior varies based on the presence of browser-specific request headers, use the <a href=\"https:\/\/developer.chrome.com\/blog\/replay-a-network-request-in-curl\/\">&#8220;Copy as cURL&#8221; feature<\/a> provided by many web browser&#8217;s development tools. This will ensure that the cURL requests will include the expected request headers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-node-js-inspector\">Node.js inspector<\/h2>\n\n\n\n<p>Node.js includes a <a href=\"https:\/\/nodejs.org\/en\/docs\/guides\/debugging-getting-started\/\">debugging inspector<\/a> that allows developers to set breakpoints, step through code, inspect variables, and more\u2014for 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 &#8220;manually&#8221; debugging an application, and is worth the time required to set it up.<\/p>\n\n\n\n<p><a href=\"https:\/\/nodejs.org\/en\/docs\/guides\/debugging-getting-started\/#enable-inspector\">Instructions for enabling the inspector<\/a>\u2014as well as a <a href=\"https:\/\/nodejs.org\/api\/debugger.html\">command-line debugging utility<\/a> option\u2014can be found in Node.js documentation.<\/p>\n\n\n\n<div class=\"a8c-docs-note-block caution\">\n<p><strong>Caution<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/nodejs.org\/en\/docs\/guides\/debugging-getting-started\/#security-implications\">For security reasons<\/a>, only run the Node.js inspector on local, non-public applications.<\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-logging\">Logging<\/h2>\n\n\n\n<p>Logging can be used to inspect requests and responses as they flow through an application&#8217;s code. Logging is useful for gathering context around issues and debugging them, especially in remote environments.<\/p>\n\n\n\n<p>On the VIP Platform, <a href=\"https:\/\/nodejs.org\/api\/console.html#class-console\"><code>console.*<\/code><\/a> can be used by Node.js applications to log information and make it available in <a href=\"https:\/\/docs.wpvip.com\/vip-dashboard\/health-logs\/\">application logs<\/a>. For maximum readability, always convert non-string values to strings (e.g., using <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/JSON\/stringify\">JSON.stringify<\/a><\/code>).<\/p>\n\n\n\n<p>Knowing <em>what<\/em> and <em>where<\/em> 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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-next-js\">Next.js<\/h3>\n\n\n\n<p>Next.js recently introduced the construct of <a href=\"https:\/\/nextjs.org\/docs\/advanced-features\/middleware\">middleware<\/a>, which provides a way to inspect every request and potentially modify the response. The main function of Next.js middleware is to respond to <a href=\"https:\/\/docs.wpvip.com\/node-js\/health-checks\/\">health checks<\/a>, but it can also be extended to log information about incoming requests. An <a href=\"https:\/\/github.com\/Automattic\/vip-go-nextjs-skeleton\/blob\/trunk\/middleware.ts\">example implementation of middleware<\/a> is provided in the <a href=\"https:\/\/github.com\/Automattic\/vip-go-nextjs-skeleton\">vip-go-nextjs-skeleton<\/a> GitHub repository. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-apollo\">Apollo<\/h3>\n\n\n\n<p><a href=\"https:\/\/www.apollographql.com\/\">Apollo<\/a> is a GraphQL client that is used for communication between a Node.js front end and a WordPress back end. <a href=\"https:\/\/www.apollographql.com\/docs\/react\/api\/link\/introduction\/\"><code>ApolloLink<\/code><\/a> is an Apollo module that makes it possible to customize the flow of data between the Apollo client and the GraphQL server. <code>ApolloLink<\/code>  is a useful location to add logging, and can be helpful for understanding data that is requested by an application. A <a href=\"https:\/\/github.com\/Automattic\/vip-go-nextjs-skeleton\/blob\/trunk\/graphql\/apollo-link.ts\">custom <code>ApolloLink<\/code><\/a> for logging information about requests is included in <a href=\"https:\/\/github.com\/Automattic\/vip-go-nextjs-skeleton\">vip-go-nextjs-skeleton<\/a> and can be used to correlate front-end and back-end requests. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recommended tools, methods, and best practices for debugging Node.js application issues <\/p>\n","protected":false},"author":20,"featured_media":0,"parent":2047,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"jetpack_post_was_ever_published":false,"footnotes":""},"categories":[32],"tags":[72],"code_tag":[],"environment":[69],"class_list":["post-11377","page","type-page","status-publish","hentry","category-node-on-vip","tag-how-to"],"parsely":{"version":"1.1.0","canonical_url":"https:\/\/docs.wpvip.com\/node-js\/debug\/","smart_links":{"inbound":0,"outbound":0},"traffic_boost_suggestions_count":0,"meta":{"@context":"https:\/\/schema.org","@type":"NewsArticle","headline":"Debug a Node.js application","url":"https:\/\/docs.wpvip.com\/node-js\/debug\/","mainEntityOfPage":{"@type":"WebPage","@id":"https:\/\/docs.wpvip.com\/node-js\/debug\/"},"thumbnailUrl":"","image":{"@type":"ImageObject","url":""},"articleSection":"Node.js on VIP","author":[{"@type":"Person","name":"WordPress VIP Documentation"}],"creator":["WordPress VIP Documentation"],"publisher":{"@type":"Organization","name":"WordPress VIP Documentation","logo":"https:\/\/docs.wpvip.com\/wp-content\/uploads\/sites\/2\/2023\/07\/cropped-cropped-site-logo.png"},"keywords":["how-to"],"dateCreated":"2022-07-22T18:07:31Z","datePublished":"2022-07-22T18:07:31Z","dateModified":"2026-01-01T17:26:13Z"},"rendered":"<script type=\"application\/ld+json\" class=\"wp-parsely-metadata\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@type\":\"NewsArticle\",\"headline\":\"Debug a Node.js application\",\"url\":\"https:\\\/\\\/docs.wpvip.com\\\/node-js\\\/debug\\\/\",\"mainEntityOfPage\":{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/docs.wpvip.com\\\/node-js\\\/debug\\\/\"},\"thumbnailUrl\":\"\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"\"},\"articleSection\":\"Node.js on VIP\",\"author\":[{\"@type\":\"Person\",\"name\":\"WordPress VIP Documentation\"}],\"creator\":[\"WordPress VIP Documentation\"],\"publisher\":{\"@type\":\"Organization\",\"name\":\"WordPress VIP Documentation\",\"logo\":\"https:\\\/\\\/docs.wpvip.com\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2023\\\/07\\\/cropped-cropped-site-logo.png\"},\"keywords\":[\"how-to\"],\"dateCreated\":\"2022-07-22T18:07:31Z\",\"datePublished\":\"2022-07-22T18:07:31Z\",\"dateModified\":\"2026-01-01T17:26:13Z\"}<\/script>","tracker_url":"https:\/\/cdn.parsely.com\/keys\/docs.wpvip.com\/p.js"},"_links":{"self":[{"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/pages\/11377","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/comments?post=11377"}],"version-history":[{"count":55,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/pages\/11377\/revisions"}],"predecessor-version":[{"id":27070,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/pages\/11377\/revisions\/27070"}],"up":[{"embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/pages\/2047"}],"wp:attachment":[{"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/media?parent=11377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/categories?post=11377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/tags?post=11377"},{"taxonomy":"code_tag","embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/code_tag?post=11377"},{"taxonomy":"environment","embeddable":true,"href":"https:\/\/docs.wpvip.com\/wp-json\/wp\/v2\/environment?post=11377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}