General Development and Debugging Tips For Layer0 Apps

Hello. I need a comprehensive guide to general processes involved in developing and debugging my app. I’ve experienced some issues with functionalities like prefetching, caching, routing and cors access errors. Please how can I get a list of general debugging steps for these issues

1 Like

General Development and Debugging Tips

  • Always use Incognito Mode - When debugging LAYER0 Starter apps (or anything with Service Workers), work in Chrome’s Incognito mode. Browsers can be very tricky when it comes to service workers, and you can find yourself spinning in circles if your app isn’t clean in the browser after every change you make. So, when you make a change, always open a new Incognito window before debugging your changes.
  • Make sure to use Webpack’s development mode - In your project’s webpack.config.js file, make sure you have mode: 'development’ so that the LAYER0 prefetcher and Workbox log statements are shown in the console
  • Make sure the service worker has “update on reload” turned on in the application tab. Otherwise, it may not update correctly
  • Track your service worker caching - Make sure to familiarize yourself with the Application tab in the Chrome Dev Tools. Under Cache → Cache Storage, there will be a “prefetch” cache that contains all the endpoints prefetched by the service worker. When, for instance, you open a menu that contains links to cacheable pages, the list of cached files should grow as those endpoints are prefetched by the service worker.
  • The docs are your best friend - These pages, in particular, should be second nature to successfully develop with LAYER0 Starter:

Managing CORS errors

If you run into CORS issues in the browser console, here are a few ways to address this:

  • Ensure that the request allows CORS - If this is a resource that is already being proxied through LAYER0, but the headers are preventing it from being used cross-origin, the allowCors function lets you easily update these headers. See the docs for this function.
  • Use cURL to help determine what is causing the issue - Sometimes the origin server sends back “Invalid CORS request” when a request is sent. A good way to debug this is to copy the request (in Chrome’s Network tab, right-click on the request → Copy → Copy as cURL) and paste it into the terminal, then remove headers until you can determine what combination of headers allows the request to work.
  • Force CORS error requests to proxy through LAYER0 - If you have requests that are made to a different origin server, you can force those requests to go through the LAYER0 so that they can be treated as relative requests that allow CORS:
    • Use the Initiator column/tab on the Chrome Dev Tools Network to determine the exact origin of the request.


fetch('https://my.api.server/rest/products/list', { ... })

  • Add a backend to your layer0.config.js for the origin server of the script:
backends: {

origin: { ... },

api: {

domainOrIp: 'my.api.server',

hostHeader: 'my.api.server'


  • Add a route to your router that proxies the script where that request is made, and add a transformResponse property in which you modify the response so that the host of the request is changed to be a local path:
new Router()


.match('/scripts/api-caller.js', ({ proxy }) => {

proxy('origin', {

transformResponse: response => {

response.body = response.body.toString()

.replace('https://my.api.server', '/script-proxy')



  • Add a route to proxy that script file to the new backend created in step #2:
new Router()

.match('/script-proxy/:path', ({ proxy }) => {

proxy('api', { path: ':path' })


Now your resource should be wired through the LAYER0 site, proxying the correct backend, and no longer inhibited by CORS.

Keep in mind that you might have to chain a few of these transformations together, if the script that makes the invalid-CORS call is also from a different origin server, so that all of the files can be transformed to be proxied from your LAYER0 project.

Note that this is not a production-viable solution, and should only be used for demo purposes. The production-ready way to handle this is to have make it so that the changes to transformResponse aren’t necessary, and the upstream site is modified so that the CORS-affected requests are configured to go through the LAYER0 on their own.

Edge caching issues

You can run locally with the --cache option to emulate edge caching. This will allow you to know if your cache configurations are working as you expect.

Eliminate your 412s when working on demos - By default, prefetch requests are only served from edge cache, and will return a 412 status if the resource is not available in the cache. To prevent this when working on starter demos, set the includeCacheMisses when running install() for your service worker:

  • Understand why your edge caching is failing - Always check the x-layer0-caching-status response header, which tells you if the response was cached on the edge or not. Use the docs to learn and memorize all the possible values for this header.

JSON Query issues

One common issue with starter is debugging the deep fetching of JSON. Here are some things to keep in mind:

  • Deep fetching is only for prefetches - The DeepFetchPlugin is only triggered when the original request is made from a prefetch. So, this might mean having to manually call prefetch('/my/json/resource.json', 'fetch') in order to deep fetch URLs from that JSON
  • Test your JSON queries manually - The JSON query syntax is specific to the json-query library. Thankfully, there is a great site that can be used to test your queries: JSON-query Tester. Use this site to copy/paste the JSON file’s contents and check that your query is returning the right array of URLs that you are expecting.

Prerendering issues

The typescript definition isn’t correct and throws an error as well as warnings in Visual Studio Code for the prerender function and subsequent function input variables for some reason. To circumvent the issue I used // @ts-ignore before the prerender(functionName) which needs to be a function in a single line since the ignore only works for one line. alternatively one could add // @ts-nocheck at the top of the routes file but that may have other consequences.

Common issues for slow sites

  • Prefetching/caching too much - Forcing all of a sites assets to be cached in the service worker does not necessarily make a site faster. In fact, there’s a good chance that this can slow things down. In general, you should only cache static assets on the edge, and not in the service worker
  • Lazy loaded images - When a site has a framework in place that lazily loads images on PLP/PDPs, it generally prohibits the LAYER0 from reaching its full potential. One way to avoid this is to use transformResponse to change the lazily-loaded img tag’s src attribute to be the correct image when the HTML is loaded. This allows you to deep fetch images and have them cached so that they can be shown immediately when the navigating to the page.

Note that this is not a production-viable solution, and should only be used for demo purposes. The production-ready way to handle this is to make it so that the changes to transformResponse aren’t necessary, and the upstream site is modified so that the HTML is configured to use the right src attributes on its own.

Shopify issues

Shopify has a throttler so you want to

  • be conservative in prerendering
  • ensure that only cached pages are prefetched. i.e. don’t use includeCacheMisses: true, in your browser.ts