I work on a fairly large e-commerce site that was built using gatsby. Up till now we have been dynamically loading all our product data at runtime so we only had 1 product page for the whole site and a total of about 3k pages.
However, for SEO reason we are trying to statically build all our product pages and that adds about 60k pages to the website.
After we did this our app.[hash].js file has increased to 10mb and general page performance as tanked. Hovering links causes page to hang for a half a second.
We are creating the product pages by passing the product data as page context when calling create pages:
const productsRaw = await fetch(productsUrl)
const products = await productsRaw.json()
/* Build a page for each product */
if (products) {
products.forEach(product => {
const productPage = {
path: `/product${product.route}`,
component: path.resolve(`./src/templates/product.jsx`),
context: product,
}
createPage(productPage)
})
}
We believe the bad page performance is related to the app.js file jumping to about 10mb. Is there any optimization we can make to reduce the size of this file or is this just unavoidable when increasing the page count?
Update
After analyzing the webpack I found that the issue is that each product page is added to the match-path.json file. This caused the file to exceed 10mb. Is it necessary that all these paths get added to the file and if not is there a way to correct that when I create the page?
Update 2
I ended up writing a script to remove all non-regex paths from match-path.json before webpack runs and the site seems to work great and perform very well. Any way I can prevent them from getting added in the first place?
2
Answers
I figured this out. So we actually do create another dynamic product page that contains a matchPath. This page is used just in case we dont properly build out all the products and a user tries to access a product thats not statically generated. In this case, it would hit a match path that would dynamically load product data. This page also uses the same template as the other product page. When I remove this page from getting created all the other products get removed from match-path.json but when it is included all the other products get added to the match-path.json. Here is the code:
I'm assuming it does this for a reason, any thoughts on why this is necessary? We were talking about removing this dynamic page so its probably not a big deal for us to just deleted it and move on.
While 60k is a fair number of pages to generate at build-time, it’s not extreme. The issue you’re having is that you are passing product data in via context. That is intended to be a small amount of data that allows you to query for the data in your page template.
gatsby-node.js
, callcreatePage
for each page that should be exportedcontext
passed tocreatePage
(e.g. an ID or slug)context
is available as an argument to a named GraphQL query)If you follow the above, each page query data will be written out as an individual page-data.json file that will be rather small (it’s literally just the query data). That should be the only data that is prefetched when you hover over a link.
Note: if, after doing this, your
app.<hash>.js
file is still large, chances are you have some data you’re not expecting in there. Check it out using webpack-bundle-analyzer to see where the weight is coming from.