Debug PWA Kit Apps
Bugs and performance bottlenecks are an unavoidable part of web app development. With PWA Kit, you can get to the bottom of these issues with a variety of tools and techniques for examining your app up close.
Replace any placeholders in this guide with actual values. Placeholders are formatted like this: $PLACEHOLDER
.
Before you follow the more targeted advice in this guide, try these general troubleshooting steps first:
- Double-check that you’re running a supported version of Node (refer to the Get Started guide) before starting your local development server.
- Confirm that your development server is still running and the port hasn’t been taken over by another process.
- After a code change, confirm that the message
HTTP development server listening
appears in the terminal before reloading your browser. - Look for errors in both the browser console and in the terminal.
- Look for network error responses using your browser’s developer tools. (In Chrome’s DevTools, go to the Network tab.)
- To help identify syntax errors and typos, run a code formatter and a linter. Configuration files are provided for both Prettier (code formatter) and ESLint (linter) in the Retail React App.
- Check your computer’s antivirus and firewall settings for anything that is preventing your code from running or blocking network requests.
- To identify and analyze performance issues, use the Profiler in Chrome’s DevTools. For more information, see this guide from Google: Analyze Runtime Performance. You can also install the React Developer Tools extension for Chrome to get another Profiler tab where you can see similar info but at the component level.
There are two special query parameters that you can add to any URL served by your commerce app to help debug issues with server-side code.
The __server_only
query parameter stops the hydration process so that the page appears in your browser exactly as it does after server-side rendering. Seeing the server-side rendered version of the page helps troubleshoot issues not only with server-side rendering, but also with SEO since search engines crawl this version of the page.
The __pretty_print
query parameter adds formatting to the __PRELOADED_STATE__
object to make it more readable. This object provides a snapshot into your app’s state before hydration begins, so it can be helpful for debugging to see if it contains the values that you expect. To view the contents of the object, load your app, view the source of the page, and search for __PRELOADED_STATE__
.
The __PRELOADED_STATE__
object is included in a <script>
tag within the HTML source of the page that was initially requested when your app begins running on the server side. The __PRELOADED_STATE__
object contains serialized values returned from the getProps
function (including the versions of getProps that are attached to the _app
component and the page component).
This feature is generally available from PWA Kit version 3.7.
The __server_timing
query parameter provides detailed performance metrics for various stages of the rendering process with the HTTP Server-Timing header. This feature allows you to gain insights into the performance characteristics of your applications, helping in optimization and troubleshooting. When the __server_timing
query parameter is present, the Server-Timing HTTP response header will be available, providing performance metrics. Performance metrics logs are also available in Log Center.
To track the current performance on your site:
- Run
npm start
. - Go to
http://localhost:3000?__server_timing
. Or go to any local URL for a page on your site and add the__server_timing
query parameter to the URL. - Check the network responses using your browser’s developer tools. (In Chrome’s DevTools, go to the Network tab.)
- Check the
Server-Timing
HTTP response header.
These metrics are included in the Server-Timing header. Each metric helps you understand specific aspects of the server-side rendering (SSR) process:
-
ssr:route-matching
: Measures the time taken to match an incoming request to a specific route. It is crucial for evaluating if the route configuration file (route.js) is optimally structured. Typically, this metric should be less than a few milliseconds. -
ssr:load-component
: Represents the time required to load components on demand at the page level. Generally, this metric should also be less than a few milliseconds. -
ssr:fetch-strategies
: Indicates how long in total your fetch strategy takes to complete. -
ssr:fetch-strategies:get-props:<page-name>
: Time taken by the getProps function for execution, where<page-name>
is either theApp
component or the page. This is only applicable when theuseLegacyGetProps
higher-order component (HOC) is used. -
ssr:fetch-strategies:react-query:pre-render
: Duration for pre-render stage to collect all queries before rendering. This is only applicable when theuseReactQuery
HOC is used. -
ssr:fetch-strategies:react-query:use-query:<query.meta.displayName>
: Time taken by individual useQuery calls. The display name can be set using themeta.displayName
property of the query. By default, all queries in thecommerce-sdk-react
library havedisplayName
configured. If no display name is added, it will be an integer index. This is only applicable when theuseReactQuery
HOC is used. -
ssr:render-to-string
: Time taken to render the application to a string, after all network requests have completed. This metric is crucial for assessing the complexity of the application. Typical values are less than 100ms for small apps and may be longer for large-scale applications. -
ssr:total
: The total time taken for the server to render the HTML output, encapsulating all stages of the SSR process.
If you want to capture performance metrics continuously, set the local SERVER_TIMING
environment variable to true
. This allows you to look up historical events and debug issues involving performance at a later time thru logs.
It's not recommended to set this environment variable on production environments because of its increased log usage.
For more performance-related recommendations, see Pre-Build and Go-Live Best Practices Checklist.
By default, the app server displays console messages in the terminal but doesn’t otherwise allow you to observe code execution. This limitation can make it hard to debug the code that renders pages on the server side (or on your local machine).
For enhanced debugging, you can start your local development server with an alternate command that runs an inspector process in Node that a debugger can attach to. (For more details, see the Node documentation.)
You can attach the debugger included in many popular browsers and text editors to Node’s inspector process. Here are instructions for Google Chrome and Visual Studio Code.
- Open a terminal.
- Go to your project directory.
- Start your local dev server using
npm run start:inspect
. - To confirm that the debugger is listening, look for a “Debugger listening” message in the terminal output.
- Open Chrome and enter the URL chrome://inspect.
- Click Open dedicated DevTools for Node.
- DevTools opens in a new window.
- To confirm that the debugger is attached, look for a “Debugger attached” message in the terminal output.
- Set breakpoints, add
debugger
statements, and so on. - Load a page from your local development server in Chrome.
- Use the dedicated window for debugging.
Now you can trace the execution of your server-side code!
To learn more about debugging with breakpoints in DevTools, see this guide from Google: Debug JavaScript.
- Open your project files in Visual Studio Code.
- From the menu bar, click Terminal > New Terminal.
- Start your local dev server using
npm run start:inspect
. - Open the Command Palette. Shortcut for Windows:
Ctrl
+Shift
+P
. Shortcut for MacCommand
+Shift
+P
. - Type the following command: “Debug: Attach to Node Process.”
- A list of the Node processes appears. Choose the first one in the list.
- To confirm that the debugger is attached, look for a “Debugger Attached” message in the terminal output.
- Set breakpoints, add debugger statements, and so on.
- Load a page from your local development server in your web browser.
- Use the integrated debugger in Visual Studio Code for debugging.
Now you can trace the execution of your server-side code in Visual Studio Code!
To avoid having to attach the Node process repeatedly, open the Command Palette and enter “Debug: Toggle Auto Attach.” Toggle the setting to Always and restart your local dev server in the Visual Studio Code terminal.
There are three ways to debug code deployed to Managed Runtime (MRT):
- Use source maps to pinpoint where errors occurred.
- Tail logs to debug real-time issues or errors in a low-volume environment.
- For a production environment, use Log Center, which offers powerful search and retention features.
Use source maps to identify any server-side errors. Source maps provide a simple error stack trace that pinpoints where an error occurred. For example, the stack trace identifies the file and line number where the error occurred to make troubleshooting easier.
Enabling source maps has a performance impact, so we recommend using this feature in only non-production environments.
To use source maps, you must build your site using PWA Kit version 3.4.x or later. If you have an earlier version, upgrade your project to use PWA Kit 3.4.x.
You have two choices for enabling source maps: use Runtime Admin or use the Managed Runtime API.
Use Runtime Admin
- Log into Runtime Admin.
- Click your project.
- Click an environment.
- Click Environment Settings.
- In the Advanced section, click Edit.
- Enable Source Maps.
- At the top of the Advanced section, click Update.
- Wait for the bundle to finish redeploying.
Use the Managed Runtime API
Call the projects_target_partial_update API endpoint and set enable_source_maps
to true
. This configures the NODE_OPTIONS
Managed Runtime environment variable in your environment with --enable-source-maps
and redeploys the bundle.
- When you build your project, generate the
ssr.js.map
file by using this local environment variable:PWA_KIT_SSR_SOURCE_MAP=true
.
- Deploy your bundle to Managed Runtime.
After you enable and upload source maps, you can view them using Tail Logs on Managed Runtime.
Using source maps can cause performance issues. For example, there’s latency anytime error.stack
is accessed. So when you include console.error(e)
in your code, this can slow down your site.
- New Non-Production Environments:
enable_source_maps
is set totrue
. - New Production Environments:
enable_source_maps
is set tofalse
. This behavior helps to avoid potential performance impacts that may arise when the source maps feature is enabled. - All Pre-existing Environments:
enable_source_maps
is set tofalse
.
When your app is deployed to Managed Runtime, remote debugging is not supported. However, you can tail logs for any Managed Runtime environment in real time to help diagnose any server-side errors.
You have two options to tail logs through the command line.
If you are working within a PWA Kit project generated from version 2.4.1 or higher, you can:
- View help for the logs command:
npm run tail-logs -- --help
- Tail logs for a specific project and environment:
npm run tail-logs -- --environment $ENV_ID
The extra --
in the commands above is required.
If you are working outside of a PWA Kit project, or have a project generated from below version 2.4.1, you can use npx
to:
- View help for the logs command:
npx @salesforce/pwa-kit-dev tail-logs --help
- Tail logs for a specific environment ID and project ID:
npx @salesforce/pwa-kit-dev tail-logs --environment $ENV_ID --project $PROJ_ID
Instead of --environment
and --project
arguments, you can also use the shorter -e
and -p
arguments.
When tailing logs, keep in mind the following constraints:
- Each log tailing session will terminate after 60 minutes.
- Each environment can support up to 100 active log-tailing sessions at a time, across all users.
- To tail logs, you need to be given developer or admin user permissions to the Managed Runtime project.
Use Log Center to troubleshoot errors if you built a site using PWA Kit or you have a B2C Commerce instance. Log Center:
- Provides a single location to access logs from Managed Runtime (MRT) and your B2C Commerce instance. Connect what's happening in your MRT environment with what's going on in your B2C Commerce instance.
- Lists Shopper Login and API Access (SLAS) errors. See View SLAS Error Logs in Log Center.
- Allows you to search and filter many historical logs. You can get more information about what happened in production, to help investigate and resolve issues quicker.
- MRT logs in Log Center are available for only production environments. See the Prerequisites.
- There can be a delay of up to 15 minutes between the time that an event happens and the log appears in Log Center.
This guide focuses on debugging for sites built using PWA Kit. For information about using Log Center with your B2C Commerce instance, see Centralized Log Center.
To access MRT logs for an environment in Log Center, you must first:
-
Have the Log Center User role in Account Manager. To verify, check your role in Account Manager. If you don't have the role, ask your Account Manager admin to give you access. See Managing Account Manager for Salesforce B2C Commerce Users.
-
Set up the environment as follows:
- Mark the environment as a production environment. See details and limitations related to production environments.
- Select a Commerce Cloud (B2C Commerce) instance to connect to the environment.
- Add one or more site IDs to associate with the environment.
After you complete the Prerequisites, to view MRT logs in Log Center:
-
Select a Region.
-
Select a Realm. If you don’t know your realm ID, ask your Account Executive (AE) or Customer Success Manager (CSM).
-
Click Show filtered results.
-
Click Search > Current Search.
-
Under Service Type, select mrt.
-
Under Host, select the production environment whose MRT logs you want to see. The format of the host is
$PROJECT.$ENVIRONMENT
. If you have more than one MRT production environment, you can see multiple MRT host names. -
View the MRT logs.
If you’re using PWA Kit version 3.6.0 or later, you can quickly find logs generated by your PWA Kit site by searching on namespaces added as prefixes to logs in Log Center. The namespace pinpoints the specific part of your codebase where an error occurred.
By default, PWA Kit provides namespacing in the format
<package-name>.<Component>.<action> <LOGLEVEL>
, the namespace is<package-name>.<Component>.<action>.
Here are definitions of the parts of the namespace and the log level.-
<package-name>
: The name of the package where the error occurred. -
<component>
: The component within the package that encountered the issue. -
<action>
: The action being performed when the error was triggered. -
<LOGLEVEL>
: The severity level of the error.: TRACE, DEBUG, INFO, WARN, ERROR, or FATAL.Here are common examples of namespaces provided by PWA Kit:
pwa-kit-runtime.httprequest
retail-react-app.App.render
retail-react-app.useActiveData.sendViewProduct
-
-
Optional: You can create your own custom namespace based on your requirements. For example, if you’re using a third-party integration such as a content management system (CMS), you can add the integration as a namespace. That way you can easily find errors associated with that integration in Log Center.
To create a custom namespace:
-
Go to the file in your project for which you want to log messages. For example, your homepage file:
app/pages/home/index.jsx
. -
Add this to the file:
import logger from '@salesforce/retail-react-app/app/utils/logger-instance
-
In the component for which you want to create a namespace, add an if statement. In this example, we use a component called
CmsProductDescription
and add a namespace calledHome.CmsProductDescription
.
-
- Managed Runtime: Each MRT log message available when you tail logs or use Log Center is limited to 32 KB. Any characters over 32 KB are truncated in the message. To avoid seeing truncated messages, you can tail logs in a non-production environment and shorten any long messages.
- Log Center: For information about log levels and log volumes, see Configuration for Administrators.