Debugging your app
For app developers, launching and debugging is a critical step in the app development process. To make lives of developers easier, iTwin Studio has designated VS Code as its supported editor and our templates include pre built VS Code debug/launch configurations. With these scripts, you can launch your app in the context of iTwin Studio and debug the code with support for hot reloading. Below are the steps for debugging your app in VS Code.
- Open your app folder in VS Code
- Select
Debug in Studiolaunch config - Start debugging via Run -> Start Debugging or press F5
You can put breakpoints directly in VS Code for backend code, however, you need to use developer tools to debug the frontend. Hot reloading is supported for both backend and frontend during the session.
If you encounter issues with launching, debugging, hot reloading, setting breakpoints, or loading sourcemaps, chances are something within your launch.json is misconfigured. We offer launch.json scripts tailored to our templates (e.g., our basic template’s launch.json).
However, as your application evolves, these configurations might become inadequate, especially in scenarios such as integrating an iTwin Studio app within a larger monorepo.
In the next sections, we’ll break down the provided launch.json configurations from our templates. This breakdown aims to empower you to extend or modify these configurations to suit your evolving project needs. While launch.json handles debugging configurations, tasks.json manages the tasks and build processes within your project. These tasks define how your app gets built, compiled, or processed. Lastly, we’ll show you how to launch iTwin Studio without Visual Studio Code.
Prerequisites
Section titled “Prerequisites”tasks.json anatomy
Section titled “tasks.json anatomy”The tasks.json file contains build tasks for your application. It defines how your application is compiled and provides necessary configurations for debugging. Ensure these tasks are correctly set up before proceeding.
{ tasks: [ { // Use npm to execute this task type: "npm", // This 'dev' script within the template triggers `studio-cli apps build watch ...` // The command optimizes the app for development, including sourcemaps and un-minified code // Both backend and frontend build concurrently. script: "dev", // Ensure this label matches the `preLaunchTask` value in the launch.json label: "npm: dev", // Run the script in the background // https://code.visualstudio.com/docs/editor/tasks#_background-watching-tasks isBackground: true, problemMatcher: [ { pattern: [ { "regexp": "^[✘▲] \\[([A-Z]+)\\] (.+)", "severity": 1, "message": 2 }, { "regexp": "^(?:\\t| {4})(?!\\s)([^:]+)(?::([0-9]+))?(?::([0-9]+))?:$", "file": 1, "line": 2, "column": 3 } ], "background": { "beginsPattern": ".*", // Since `studio-cli apps build --watch ...` is being run in the background, VS code needs to know when the initial build is complete to begin launching iTwin Studio. // `studio-cli apps build --watch ...` will print "Compiled frontend and backend. Ready for iTwin Studio" after the first build. "endsPattern": "Compiled .*|Rebuilt .*" } } ] }, ],}launch.json anatomy
Section titled “launch.json anatomy”The launch.json file is crucial for configuring the debugger. Let’s break down the launch.json script for Windows, as an example (Mac and Linux configurations will be hidden for brevity):
{ // Compounds group configurations together for simultaneous launching via a single button in the debugger explorer // https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations compounds: [ { name: "Debug in Studio", configurations: [ "Launch iTwin Studio", "Attach to iTwin Studio Frontend", "Attach to iTwin Studio Backend", ], stopAll: true, // Execute the 'npm: dev' task in tasks.json before launching any configurations // Omitting this would start Studio with the current app build. // If the 'studio-cli apps build' or 'studio-cli apps build --watch' hasn't been executed before, the app may fail to load due to an non-built state. preLaunchTask: "npm: dev", }, ], configurations: [ { name: "Launch iTwin Studio", request: "launch", outputCapture: "std", // Troubleshooting: Some users noticed Studio would not close even after stopping the debugging session. Set 'killBehavior' to forceful if that's the case. killBehavior: "polite", // If this configuration is terminated, terminate other attached configurations cascadeTerminateToConfigurations: ["Attach to iTwin Studio Frontend", "Attach to iTwin Studio Backend"], type: "node", windows: { // Specifies the location of iTwin Studio executable on Windows runtimeExecutable: "iTwinStudio", }, args: [ // Path to your app.config.json file - this must be the first argument, or it won't work "${workspaceFolder}/app.config.json", // Allows attachment to port 9222 for debugging the frontend (see 'Attach to iTwin Studio Frontend' below) "--remote-debugging-port=9222", // Sets console logging verbosity level to "verbose" "-v" ], env: { // Passes space-separated CLI arguments directly to the backend process, enabling attachment to port 9232 for backend debugging (see 'Attach to iTwin Studio Backend' below) // miscellaneous node development arguments such as --trace-warnings go here as well, space separated // Note: the "-brk" tells the iTwinStudio backend to STOP and wait for the "Attach to ITwin Studio Backend" debugger to attach. Use "--inspect=9232" if your app is having issues starting up. STUDIO_UTILITY_EXTRA_CLI_ARGS: "--inspect-brk=9232", }, }, // This is optional (unless If "-brk" is set in `STUDIO_UTILITY_EXTRA_CLI_ARGS` then you need this or to attach your own debugger) { name: "Attach to iTwin Studio Backend", type: "node", request: "attach", // Port specified in --inspect-brk argument passed to iTwin Studio through STUDIO_UTILITY_EXTRA_CLI_ARGS port: 9232, cascadeTerminateToConfigurations: ["Launch Studio", "Attach to Frontend"], continueOnAttach: true, restart: true, windows: { // Defines the location of compiled JavaScript files for proper sourcemap discovery // Note: you can also set resolveSourceMapLocations if you notice issues with source map resolution. outFiles: [ "${workspaceFolder}/dist/**/*.js", // Your app's Javascript files "${env:LocalAppData}/Programs/Bentley/iTwinStudio/v1*/resources/app.asar/backend-bundle/**/*.js", // iTwin Studio's Javascript files "https://*autoupdatecdn.bentley.com/itwindesktopplatform/standard*/**" // iTwin Studio's source maps ], }, }, { // Attaches to iTwin Studio Frontend via port 9222 for frontend debugging in VS Code type: "chrome", request: "attach", name: "Attach to iTwin Studio Frontend", // Port specified in --remote-debugging-port argument passed to iTwin Studio port: 9222, cascadeTerminateToConfigurations: ["Launch Studio", "Attach to Backend"], // Defines the location of compiled JavaScript files for proper sourcemap discovery windows: { // Note: you can also set resolveSourceMapLocations if you notice issues with source map resolution. outFiles: [ "${workspaceFolder}/dist/**/*.js", // Your app's Javascript files "${env:LocalAppData}/Programs/Bentley/iTwinStudio/v1*/resources/app.asar/dist/**/*.js", // iTwin Studio's Javascript files "https://*autoupdatecdn.bentley.com/itwindesktopplatform/standard*/**" // iTwin Studio's source maps ], }, }, ],}Hot Reloading
Section titled “Hot Reloading”When using the studio-cli apps build --watch command, backend and frontend file modifications trigger respective signals for restarting iTwin Studio and reloading the frontend. It’s advisable to maintain a stateless backend or implement resource cleanup within the deactivateFrontend function to fully leverage hot reloading.
Consider this scenario: your frontend requests the backend to open a briefcase, and the backend complies. During development, a frontend file modification triggers a reload, but the backend remains unaware of this change. Consequently, if the frontend requests the same file again, the backend might fail due to an already open briefcase.
To address this, ensure backend awareness of frontend reloads by incorporating cleanup instructions within the deactivateFrontend function, which is invoked before every reload:
export async function deactivateFrontend() { // Notify the backend to handle cleanup of any remaining resources. IpcApp.send("frontend:deactivated:closeBriefcase", { resourceId: "briefcaseId" });}By signaling the backend in this manner, you’ll facilitate proper resource management and prevent conflicts arising from file re-openings after frontend reloads.
Working without Visual Studio Code
Section titled “Working without Visual Studio Code”When initiating debugging for iTwin Studio outside of Visual Studio Code, utilize the command-line. iTwinStudio should automatically be added to your PATH on Windows.
To launch iTwin Studio for debugging purposes, use the following command:
iTwinStudio "path/to/app.config.json" --remote-debugging-port=9222Here’s a breakdown of the components and their functionalities:
iTwinStudio: The command to launch iTwin Studio.
path/to/app.config.json: Refers to theapp.config.jsonfile, necessary for configuring iTwin Studio.
For effective debugging:
- Frontend Debugging:
--remote-debugging-port=9222opens a port for remote debugging on the frontend. - Backend Debugging: utilize the
STUDIO_UTILITY_EXTRA_CLI_ARGSenvironment variable settings, such asSTUDIO_UTILITY_EXTRA_CLI_ARGS="--inspect-brk=9232". This configuration attaches the backend process to port 9232 for debugging purposes. The iTwin Studio backend will wait for a debugger to attach if-brkis specified.
Then attach to the port using your favorite Node.js Inspector Client. We recommend using chrome://inspect and finding the ports you’ve specified.
Debugging Multiple Apps Simultaneously
Section titled “Debugging Multiple Apps Simultaneously”Debugging multiple startup apps simultaneously can be achieved through additional configurations in the iTwinStudio edition. Please note, only one instance of iTwinStudio in developer mode can run at a time without these modifications, throwing an Error: listen EADDRINUSE: address already in use \\.\pipe\iTwinStudio\server.ipc exception for the second instance.
Each of the following parameters serves a distinct purpose in configuring and managing the debugging environment, especially when working with multiple apps or profiles within iTwinStudio:
--profileis a parameter passed toiTwinStudioto specify a particular profile name be used to uniquely identify the instance ofiTwinStudio. By default, theappIdparameter from theapp.config.jsonfile is used as the profile name.--useProfileDebugChannelsis a flag passed toiTwinStudioto instruct the use of a separate debug channel for this profile.--unsafeProfileNameis a flag used by thestudio-cli apps buildcommand to explicitly define the profile name associated with the app being debugged. The name of the profile passed here should match the name of the profile passed via--profile.
- Open the
launch.jsonfile of the first app you want to debug. - Locate the “Launch iTwin Studio” configuration.
- Modify it by adding an extra CLI arguments
useProfileDebugChannels:"configurations": [{"name": "Launch iTwin Studio","request": "launch",// ...,"args": ["${workspaceFolder}/app.config.json","--remote-debugging-port=9222","--useProfileDebugChannels",], - Find and replace all instances of the Chrome debugging port
9222with a different port number, e.g.,9001. - Find and replace all instances of the Node debugging port
9232with a different port number, e.g.,9002. - Open the
package.jsonfile. - Modify the dev script within the scripts section by adding the
unsafeProfileNameCLI argument, matching the profile name we set asappIdin ourapp.config.jsonfile.
"dev": "studio-cli apps build --watch --backendEntry backend/index.ts --frontendEntry frontend/index.tsx --copy frontend/assets","dev": "studio-cli apps build --watch --backendEntry backend/index.ts --frontendEntry frontend/index.tsx --copy frontend/assets --unsafeProfileName=\"{appId from app.config.json}\"",Custom Node.js arguments
Section titled “Custom Node.js arguments”Custom Node.js arguments may be passed to iTwin Studio’s iTwin.js backend using the environment variable STUDIO_UTILITY_EXTRA_CLI_ARGS. You may edit that variable according to your shell or set it in the env section of your launch.json when using VS Code. You must space separate multiple options. For example:
NODE_OPTIONS="--inspect-brk=9229 --trace-warnings"Debugging with iTwin Studio code
Section titled “Debugging with iTwin Studio code”If you wish to test changes to iTwin Studio along with your app, you can clone the repository and follow these instructions.
Troubleshooting
Section titled “Troubleshooting”iTwin Studio freezes or doesn’t start when debugging
Section titled “iTwin Studio freezes or doesn’t start when debugging”If iTwin Studio and your app start under normal circumstances, but freezes when debugging, we recommend the following changes:
- replace all references of
inspect-brkwithinspect. The former is known to be problematic on Windows. - set
pauseForSourceMaptofalse. Setting it totrueintroduces performance overhead and it can be safely disabled
VS Code - iTwin Studio doesn’t close correctly when debugging is stopped
Section titled “VS Code - iTwin Studio doesn’t close correctly when debugging is stopped”Make sure that all tasks have cascadeTerminateToConfigurations:
{ "name": "Launch Studio", "cascadeTerminateToConfigurations": ["Attach to Frontend", "Attach to Backend"], //...},{ "name": "Attach to Backend", "cascadeTerminateToConfigurations": ["Launch Studio", "Attach to Frontend"], //...},{ "name": "Attach to Frontend", "cascadeTerminateToConfigurations": ["Launch Studio", "Attach to Backend"], //...},VS Code - Cannot see iTwin.js/iTwin Studio source maps in backend
Section titled “VS Code - Cannot see iTwin.js/iTwin Studio source maps in backend”Add resolveSourceMapLocations to your launch.json:
"resolveSourceMapLocations": [ "${workspaceFolder}/dist/**/*.js", "https://*autoupdatecdn.bentley.com/itwindesktopplatform/standard*/**" ], "outFiles": [ "${workspaceFolder}/dist/**/*.js", "${env:LocalAppData}/Programs/Bentley/iTwinStudio/v1*/resources/app.asar/backend-bundle/**/*.js" ]Cannot see iTwin.js/iTwin Studio source maps in frontend
Section titled “Cannot see iTwin.js/iTwin Studio source maps in frontend”Add resolveSourceMapLocations to your launch.json:
"resolveSourceMapLocations": [ "${workspaceFolder}/dist/**/*.js", "https://*autoupdatecdn.bentley.com/itwindesktopplatform/standard*/**" ], "outFiles": [ "${workspaceFolder}/dist/**/*.js", "${env:LocalAppData}/Programs/Bentley/iTwinStudio/v1*/resources/app.asar/dist/**/*.js" ]