{"id":22853,"date":"2018-01-23T16:28:56","date_gmt":"2018-01-23T16:28:56","guid":{"rendered":"https:\/\/blog.jetbrains.com\/webstorm\/?p=9421"},"modified":"2024-01-25T14:14:26","modified_gmt":"2024-01-25T13:14:26","slug":"how-to-debug-with-webstorm","status":"publish","type":"webstorm","link":"https:\/\/blog.jetbrains.com\/zh-hans\/webstorm\/2018\/01\/how-to-debug-with-webstorm","title":{"rendered":"How to Debug With WebStorm"},"content":{"rendered":"<p><em>Note: This post was updated in January 2024.<\/em><\/p>\n<p>The debugger is one of the most essential features of WebStorm. With it, you can debug all kinds of applications written in JavaScript and TypeScript: Node.js, React Native, Electron apps, and client-side apps written using different frameworks. In addition to that, you can also debug unit tests and build scripts.<\/p>\n<p>One of the main benefits of using a debugger inside the IDE is you can add breakpoints and step through your source code (even if you then compile it. Thank you, source maps!). If you want to edit the code or quickly navigate to the usages or definitions of methods while debugging, you don\u2019t need to switch back to the editor.<\/p>\n<p>And no matter what kind of code you debug, your experience with the debugger will be the same.<\/p>\n<p>To see how the debugger works in WebStorm, we\u2019ll try to debug a simple <a href=\"http:\/\/expressjs.com\/\" target=\"_blank\" rel=\"noopener\">Express<\/a> Node.js application <a href=\"https:\/\/www.jetbrains.com\/help\/webstorm\/developing-node-js-applications.html?keymap=macos#ws_node_quick_start\" target=\"_blank\" rel=\"noopener\">generated by the <em>New Project<\/em> wizard<\/a>. We\u2019ll start by creating a new run\/debug configuration. Then, we\u2019ll add some breakpoints, see what\u2019s happening in the Debugger\u2019s <em>Variables<\/em> view, step through the code, evaluate expressions, and use the interactive console.<\/p>\n<h2 id=\"prepare_for_debugging_create_a_run_debug_configuration\"><strong>Prepare for debugging: create a run\/debug configuration<\/strong><\/h2>\n<p><em>Run\/Debug Configurations<\/em> is an entry point to, as the name suggests, running and debugging apps in WebStorm.<\/p>\n<p>To debug different types of apps and files, you need to use different types of <em>Run\/Debug Configurations<\/em>.<\/p>\n<p>Depending on the type, the information you need to provide in the configuration varies.<br \/>\nFor example, in the <em>Node.js<\/em> configuration, you need to specify a file to run. In the test configuration, you can select the name of a suite, test, or test file. Some configurations attach to the already started app. In this case, you need to specify the URL and port to attach to.<\/p>\n<p>To create a run\/debug configuration:<\/p>\n<ol>\n<li>Click the drop-down list on the toolbar and select <em>Edit configurations\u2026<\/em>. The <em>Run\/Debug Configurations<\/em> dialog opens.<\/li>\n<li>In the left-hand pane, click the <em>+<\/em> icon on the toolbar and select the configuration type: we\u2019ll choose <em>Node.js<\/em>.<\/li>\n<li>In the right-hand pane, add the missing information about the debug environment: we need to specify <code>bin\/www<\/code>, which is the main file that runs our app.<\/li>\n<li>Name and save the configuration.<\/li>\n<\/ol>\n<p><img decoding=\"async\" alt=\"Create a run\/debug configuration.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_create_run_configuration.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_create_run_configuration.png\"\/><br \/>\nAll the created configurations are saved in the <em>workspace.xml<\/em> file in the <em>.idea<\/em> folder in the root of your project, so you can reuse them the next time you open this project.<\/p>\n<p>If you want to share your configuration with your team, check the <em>Share<\/em> checkbox in the configuration and then commit the <em>.idea\/runConfigurations<\/em> folder to the version control.<\/p>\n<h2 id=\"starting_the_debugger\"><strong>Starting the debugger<\/strong><\/h2>\n<p>Once our configuration is ready, select it from the drop-down list on the toolbar and click the green debug icon next to it.<\/p>\n<p><img decoding=\"async\" alt=\"Start a debugging session.\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_start_debug_session.png\"\/><\/p>\n<p>Our <em>Node.js<\/em> configuration will run the file we specified in debug mode. Many configurations will do the same, but some others will instead <a href=\"https:\/\/www.jetbrains.com\/help\/webstorm\/running-and-debugging-node-js.html?keymap=macos#node_debugging_running_application\" target=\"_blank\" rel=\"noopener\">attach the debugger to an already running app<\/a>.<\/p>\n<p>In our case, we could have started the debugger without creating a configuration beforehand. Instead, we could have right-clicked the <code>bin\/www<\/code> JavaScript file in the <em>Project<\/em> tool window or the editor and selected <em>Debug<\/em>, or we could have pressed <em>^D<\/em> on macOS or <em>Ctrl+Shift+D<\/em>\/<em>Ctrl+Shift+F9<\/em> on Windows and Linux.<\/p>\n<p><img decoding=\"async\" alt=\"Start a debugging session from the Project tool window.\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_start_debugging_session_context_menu.png\"\/><\/p>\n<p>This creates a temporary configuration that, if you want to reuse it, you can save later in the <em>Run\/Debug Configurations<\/em> dialog (temporary configurations are greyed out).<\/p>\n<p><img decoding=\"async\" alt=\"Saving a temporary run\/debug configuration.\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_save_temporary_configuration.png\"\/><\/p>\n<h2 id=\"debug_tool_window\"><strong>Debug tool window<\/strong><\/h2>\n<p>We can now see a new <em>Debug<\/em> tool window at the bottom of the IDE \u2013 a control panel for everything related to debugging.<\/p>\n<p>The toolbar above it shows icons for stopping and re-running our configuration and for stepping through the application.<\/p>\n<p>The <em>Frames<\/em> and <em>Variables view<\/em> will be activated when the app stops at a breakpoint (we\u2019ll talk about it in a moment).<\/p>\n<p>The <em>Debugger Console<\/em> tab can be used for evaluating expressions.<\/p>\n<p><img decoding=\"async\" alt=\"Debug tool window.\nblog_post_debugging_debug_tool_window_overview.png\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_debug_tool_window_overview.png\"\/><\/p>\n<p>The <em>Process Console tab<\/em> shows the messages logged by the app and error messages.<\/p>\n<p>The <em>Scripts tab<\/em> lists all the files loaded into the currently running process. We can double-click on the file to see its content in the editor.<\/p>\n<h2 id=\"adding_breakpoints_to_pause_the_code\"><strong>Adding breakpoints to pause the code<\/strong><\/h2>\n<p>We want to see what\u2019s going on in our app at a specific point. With the breakpoints, we can pause the app when a specific line of code is executed and then look at the application state: what variables are now available and what their values are.<\/p>\n<p>Let\u2019s put a breakpoint on a line in which our demo app handles the <code>GET<\/code> request: click the line number in the editor, and you will see a red circle, a breakpoint.<\/p>\n<p><img decoding=\"async\" alt=\"Setting and removing breapoints.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_set_and_remove_breakpont.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_set_and_remove_breakpont.png\"\/><\/p>\n<p>(Here\u2019s the <a href=\"https:\/\/gist.github.com\/prigara\/c6832f94c842a3ca9bcb5d8658ac8329\" target=\"_blank\" rel=\"noopener\">content of the file<\/a> on this screenshot)<\/p>\n<p>If you click the breakpoint again, it will be removed. You can additionally configure how the breakpoint works if you right-click it. For example, you can set specific conditions for hitting the breakpoint.<\/p>\n<p><img decoding=\"async\" alt=\"Conditional breakpoint.\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_conditional_breakpoint.png\"\/><\/p>\n<p>We can add and remove breakpoints any time during the debug session or before it. There\u2019s no need to restart the debugger after we\u2019ve set or cleared a breakpoint!<\/p>\n<h2 id=\"exploring_the_app_state_and_call_stack\"><strong>Exploring the app state and call stack<\/strong><\/h2>\n<p>So now, when the debugger is up and running and we have a breakpoint in our code, let\u2019s stop on it. For that we should do the actions that will trigger the code with the breakpoint: in our case, we need to open the browser at <code>http:\/\/localhost:3000\/en<\/code>.<\/p>\n<p>Now, the <em>Debug<\/em> tool window is full of content. Let\u2019s have a look at what is going on!<\/p>\n<p>On the right, we see the state of our application \u2013 all the local and global variables available at this point and their values. We can also see the values right in the editor: at the end of the lines of code or if we hover over a variable.<\/p>\n<p><img decoding=\"async\" alt=\"Debug tool window during a debugging session.\nblog_post_debugging_debug_tool_window_active.png\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_debug_tool_window_active.png\"\/><\/p>\n<p>The <em>Threads<\/em> view shows the call stack \u2013 a list of all the methods that have been executed to get the execution to the code with the breakpoint in reverse chronological order. If we go through the frames, we will see the application\u2019s state at every point of the execution path.<\/p>\n<p>Don\u2019t forget that the code under the breakpoint has not yet been executed. So, if you introduce a variable in this line, you\u2019ll see it in the <em>Variables view<\/em>, but it will still be undefined.<\/p>\n<p>We can expand the objects and arrays to see their content in the <em>Variables view<\/em>.<\/p>\n<p>We are specifically interested in the <code>params<\/code> object that contains the parameters of the request. We can type its name to find it in the list (note that it will search only through the expanded nodes). Let\u2019s add it to <em>Watches<\/em> \u2013 that way, we will always see its value on the top of the <em>Variables view<\/em> anytime we stop at a breakpoint.<\/p>\n<p><img decoding=\"async\" alt=\"Adding Watches.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_add_watch.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_add_watch.png\"\/><\/p>\n<p>Now press the <em>Resume Program<\/em> button on the toolbar to continue executing the program.<\/p>\n<p><img decoding=\"async\" alt=\"Resuming program.\" width=\"800\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_resume_program.png\"\/><\/p>\n<h2 id=\"stepping_through_the_code\"><strong>Stepping through the code<\/strong><\/h2>\n<p>If we want to get a better understanding of how our code is executed, we, of course, can put lots of breakpoints in our code and then move from a breakpoint to a breakpoint by resuming the execution, but there\u2019s a better way \u2013 we can step through the code!<\/p>\n<p>The stepping actions are available on the top of the debug tool window and activated when the breakpoint is hit.<\/p>\n<p><em>Step over<\/em> action (<em>F8<\/em>) will move the execution in the current file, line by line, without stepping into any function calls.<\/p>\n<p><img decoding=\"async\" alt=\"Step over.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_step_over.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_step_over.png\"\/><\/p>\n<p>In our example, if we hit it once, it will check the condition in line 10 and then stop on the statement in the else block because the condition was false.<\/p>\n<p>With <em>Step Into<\/em> (<em>F7<\/em>), we will step to the next executed line in this or another file. So, if it\u2019s a function call, it will jump to its definition and stop at the first line.<\/p>\n<p><img decoding=\"async\" alt=\"Step Into.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_step_into.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_step_into.png\"\/><\/p>\n<p>By default, WebStorm will not step into the source code of JavaScript, Node.js, or dependencies in the <em>node_modules<\/em> folder of your project. But if you want to step into them, you can use the <em>Force Step Into<\/em> action (you can clear the <em>Do not step into libraries<\/em> checkbox in <em>Settings | Build, Execution, Deployment | Debugger | Stepping<\/em>).<\/p>\n<p><em>Step Out<\/em> (<em>\u21e7F8<\/em> \/ <em>Shift+F8<\/em>) will finish executing the current function and stop at the next statement after the call.<\/p>\n<p>If we want to skip some lines but then stop on another line that is not yet executed, we can either put a new breakpoint on this line and press <em>Resume<\/em> or put a cursor in it and use the <em>Run to Cursor<\/em> action. Which is a much easier and more efficient way than setting and clearing breakpoints whenever you move the cursor.<\/p>\n<h2 id=\"evaluate_expression\"><strong>Evaluate Expression<\/strong><\/h2>\n<p>The <em>Variables view<\/em> shows the values of objects when the app is stopped on a breakpoint. But what if we want to check the value of an expression? For instance, we want to see if a condition in the if statement is true or false before we step over to the next line.<\/p>\n<p>There are three ways you can do this:<\/p>\n<p>The first way is to type the expression in the <em>Debugger Console<\/em>. For that, we can either type it or copy and paste it.<\/p>\n<p><img decoding=\"async\" alt=\"Evaluating a expression in the Debugger Console.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_debugger_console.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_debugger_console.png\"\/><\/p>\n<p>A second way is to select the expression and then use the <em>Quick Evaluate Expression<\/em> action (<em>\u2318\u2325F8<\/em> \/ <em>Ctrl+Alt+F8<\/em>): the result will appear next to it in a tooltip.<\/p>\n<p><img decoding=\"async\" alt=\"Quick Evaluate Expression.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_quick_evaluate.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_quick_evaluate.png\"\/><\/p>\n<p>And a third way is to invoke the <em>Evaluate Expression<\/em> popup. Similar to the console, you can type (with the help of code completion) and evaluate any statement it is in.<\/p>\n<p><img decoding=\"async\" alt=\"Evaluate Expression Popup.\nblog_post_debugging_evaluate_expression_popup.png\nAnimated image:\nblog_post_debugging_evaluate_expression_popup.gif\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_popup.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_popup.png\"\/><\/p>\n<p>The pros of using the <em>Evaluate Expression<\/em> popup compared to the console are that you can open it using a shortcut (<em>\u2325F8<\/em> \/ <em>Alt+F8<\/em>) and then see all the information about the returned object in a handy tree view.<\/p>\n<p><img decoding=\"async\" alt=\"Evaluate Expression in a popup: view object.\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_popup_view_object.gif\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/01\/blog_post_debugging_evaluate_expression_popup_view_object.png\"\/><\/p>\n<p>So now we know enough to debug an application: we can stop the app on a breakpoint, see the application state, step through the code, and evaluate expressions. It all works the same way in WebStorm, no matter what kind of app you are debugging.<\/p>\n<p>That&#8217;s it for today. You can also find lots of helpful information in the <a href=\"https:\/\/www.jetbrains.com\/help\/webstorm\/running-debugging-and-testing.html\" target=\"_blank\" rel=\"noopener\">WebStorm documentation<\/a>.<\/p>\n<p><em>The WebStorm team<\/em><\/p>\n","protected":false},"author":221,"featured_media":433684,"comment_status":"open","ping_status":"closed","template":"","categories":[601],"tags":[632,264,263],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/webstorm\/22853"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/webstorm"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/webstorm"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/221"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=22853"}],"version-history":[{"count":7,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/webstorm\/22853\/revisions"}],"predecessor-version":[{"id":437779,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/webstorm\/22853\/revisions\/437779"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/433684"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=22853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=22853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=22853"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=22853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}