JSS NextImage component implemented in SUGCON site
As ever, below is the pictorial representation of the components covered in this blog post. Note that although this diagram might not be an accurate depiction, the idea of this picture is to showcase the capability of the latest and lightweight NextImage component compared with the old JSS Image component. Here are a few points as per my understanding:
1. There is JSS version of the image component that is part of Sitecore-jss package and a pure nextjs image component that is part of the next package
2. The new nextimage component is added to Sitecore-jss package to bring all Sitecore components under one umbrella and forego the need to add an external package like next/image just for one or few components - think of package size / compactness etc.
NextImage component features:
- Lightweight images
- CDN-cacheable
- Improved FCP/better Page load speed
Now, few steps backwards: One of the latest features of Sitecore JSS, from v21.6.3, is the introduction of NextImage component. There is a slight confusion with respect to release of this feature. Although the documentation says 20.1.0, v21.6.3 seems the one that supports this component. Nevertheless, here is a rehash about the different image components:
1. next/image component: supposed to be most optimised (webp format)
2. JSS Image component: not as optimised as next/image
3. JSS NextImage Component: supposed to be better than JSS Image component
In other words, the new JSS NextImage component is the JSS answer for next/image component. An easy way to identify next/image and JSS NextImage components is they are output with img srcset in the markup irrespective of what the original file format is. Also, next/image component is in webp format irrespective of original file format. I think NextImage component will go down that path maybe in a future release. For now, to add more context, JSS image component outputs just the img tag without any srcset. Also, you can easily find the output image size difference between two components as shown in the screen shots below.
While the XMC site(s) is currently on 21.5.3, the image components are still JSS Image components. So, I thought why not bump the JSS version to 21.6.3 then replace with the new JSS' next image component for performance comparison and see for myself what Thomas Desmond already covered in this video. So, this blog post is the end-result.
Note that even with an earlier version of Sitecore JSS, NextImage component worked but didn’t offer a size compression in the final img markup.
Thomas Desmond' github example is really good to understand the difference between different JSS components. One issue I faced is, a CORS error as part of the url fetch because the image came from an external domain:
Unhandled Runtime Error
TypeError: Failed to execute 'fetch' on 'Window': 1 argument required, but only 0 present.
Since this is just an example, I used the first hack of adding mode: 'no-cors' :
1. Set mode:'no-cors' as part of the url fetch to simply forego the error
2. Or, install this chrome plugin to Allow CORS (wasn't effective)
Also, for his example, next.config.js must exclude the domain from where the image is fetched.
So, that was a dry-run with Thomas Desmond' github example. Now, my goal is to implement the NextImage component in the SUGCON site and I didn't have to do much except import the NextImage component from the Sitecore JSS NextJS package and use it.
******
******
At this point, it is important to understand what the up.ps1 script does. It is well-known that the script starts up the containers, sets up CLI, gets credentials to login to CM instance and setups up items but it also does the following important things for the client setup:
1. Create node_modules folder (under C:\projects\tst\XM-Cloud-Introduction\src\Project\Sugcon2024\Sugcon folder)
2. Modify the temp folder(depicted below) by adding certain client plugins apart from the config.js
In other words, up.ps1 also handles npm install and npm run start:connected as part of its process.
If ever, these two steps have an issue, the SUGCON sites could throw 404 page not found error.
Note that apart from the arrow-marked ones, all others are dropped by up.ps1 in the temp directory.
So, if you don't have access to XMC edge endpoint and developing locally, ensure to set the GraphQL path to the local cm instance + SC API key in the .env file. I would in fact default to the local endpoint url and api key in .env.template but then that is a discussion for some other day.
Just for reference,
Preview Endpoint: https://xmcloudcm.localhost/sitecore/api/graph/edge
Edge Endpoint: https://edge.sitecorecloud.io/api/graphql/v1
TypeError: Cannot read properties of undefined (reading 'route')
Now, there are a couple of variations to the above error:
404 page not found:
Once the Sitecore instance is up, you might see 404 page not found for the SUGCON sites in browser. I went under-hood and checked the node_modules folder and temp folder. Although node_modules was created, the temp folder was totally blank and hence the page not found error. You could probably see that I left the edge graphql endpoint and api key as-is just to mimic this error.
Next, if you are unrelenting and go ahead and run npm run start:connected since there is a node_modules folder, this is what you see:
********
PS C:\projects\tst\XM-Cloud-Introduction\src\project\Sugcon2024\sugcon> npm run start:connected
> EU@21.5.3 start:connected
> npm-run-all --serial bootstrap --parallel next:dev start:watch-components
'npm-run-all' is not recognized as an internal or external command,
operable program or batch file.
********
If you suspect a missing module, you would re-execute npm install followed by npm run start:connected and the latter should create the config.js but you will see this message in the cmd prompt.
********
Skipping site information fetch (missing GraphQL endpoint or API key).
Writing runtime config to C:\projects\tst\XM-Cloud-Introduction\src\Project\Sugcon2024\Sugcon\src\temp\config.js
> EU@21.5.3 next:dev
> cross-env NODE_OPTIONS='--inspect' next dev
> EU@21.5.3 start:watch-components
> ts-node --project tsconfig.scripts.json scripts/generate-component-builder/index.ts --watch
Debugger listening on ws://127.0.0.1:9229/d4339267-55ed-4615-b69f-a555a5436fa5
For help, see: https://nodejs.org/en/docs/inspector
Warning: An PUBLIC_URL environment variable is not defined. Falling back to http://localhost:3000.
Starting inspector on 127.0.0.1:9229 failed: address already in use
the --inspect option was detected, the Next.js router server should be inspected at port 9229.
Warning: An PUBLIC_URL environment variable is not defined. Falling back to http://localhost:3000.
`destination` does not start with `/`, `http://`, or `https://` for route {"source":"/sitecore/api/:path*","destination":"undefined/sitecore/api/:path*"}
`destination` does not start with `/`, `http://`, or `https://` for route {"source":"/-/:path*","destination":"undefined/-/:path*"}
`destination` does not start with `/`, `http://`, or `https://` for route {"source":"/sitecore/service/:path*","destination":"undefined/sitecore/service/:path*"}
Error: Invalid rewrites found
********
Also, the cm host in temp config.js looked undefined:
So, the root cause is the wrong or non-existent graphql endpoint and api key. Fix the same in .env file, delete the node_modules folder then run up.ps1 to carry out the correct process!
Note that if node_modules is generated and config.js looks fine, you could still get 404 page not found. The reason in that case is the client instance might try to connect to the local Docker Sitecore instance when it isn't ready yet. So, just refresh the browser once the Sitecore instance is up.
Now, existing XMC SUGCON site with old JSS image component can be seen in the Speakers page (Person.tsx):
New change involving NextImage Component:
About 50% reduction in image size can be seen with the NewImage Component in place. In total, Speakers page has about 40 images so, the reduction in size could be game-changing!
Lighthouse score for FCP:
Now, based on existing code, you could wrap a JSS component with Chakra-UI markup for styling as follows:
*****
*****
With that in place, you not only get the image compression offered by NextImage component but styling needed for the existing site:
Proof is in the pudding:
Before:
Images in varying uncompressed formats totalling to about 900 KB (unsure why the rogue redirects):
After:
All images in webp format totalling to just around 160 KB:
Package.json for reference:
Comments
Post a Comment