Improve SPA PageSpeed (OpenSaaS) - Bad Score in Core Web Vitals
I have been researching ways to improve the performance and scoring of my WASP project, particularly focusing on optimizing PageSpeed, especially for the mobile version. Currently, I'm working with WASP version 0.14, but I'm considering migrating to version 0.15.
In this context, I would like to understand more about the handling of the main.wasp file with TypeScript in version 0.15. Since I’m not a developer, I don’t have an extensive background in this area, and the introduction of TypeScript isn’t immediately clear to me. Could explain what capabilities TypeScript offers in this version and how it might impact my project? Ideas?
32 Replies
Hi @NEROX. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
I understand your concern about improving the performance of your Wasp project, particularly for mobile. Regarding your question about TypeScript in Wasp 0.15, I can provide some insights based on the available information.
Wasp supports TypeScript out of the box, allowing you to use either JavaScript or TypeScript in your project Docs > Tutorial > 2. Project Structure Part 2 (https://wasp-lang.dev/docs/tutorial/project-structure). This means you have the flexibility to choose between or even mix JavaScript and TypeScript as you see fit.
The main benefits of using TypeScript in your Wasp project include:
1. Enhanced type safety: TypeScript adds static typing to JavaScript, which can help catch errors early in the development process.
2. Better IDE support: TypeScript provides improved autocompletion, IntelliSense, and error reporting in many IDEs.
3. Improved code maintainability: The added type information can make your code more self-documenting and easier to understand, especially for larger projects.
In terms of the
main.wasp
file specifically, the syntax remains largely the same whether you're using JavaScript or TypeScript. The main difference is that when referencing your React components or other imported files, you would use .tsx
extensions instead of .jsx
for TypeScript files. Here's an example:
Docs > Tutorial > 2. Project Structure > main.wasp
(https://wasp-lang.dev/docs/tutorial/project-structure#mainwasp)
It's worth noting that while TypeScript can improve code quality and developer experience, it may not directly impact your PageSpeed scores. To improve Core Web Vitals, you might want to focus on other aspects of optimization such as code splitting, lazy loading, and optimizing assets.
If you're not comfortable with TypeScript, you can continue using JavaScript in your Wasp project. Wasp allows you to mix JavaScript and TypeScript files, so you can gradually introduce TypeScript if you choose to do so in the future Discord support thread: Wasp/OpenSaas Typescript vs Javascript > Answers Part 1 (https://discord.com/channels/686873244791210014/1212823640173969408).
For improving PageSpeed scores, you might want to look into Wasp's client configuration options, which allow you to customize how your client-side application is set up and rendered Docs > Project > Client Config > API Reference Part 1 (https://wasp-lang.dev/docs/project/client-config#api-reference).
Remember, while TypeScript can be beneficial, it's not mandatory for using Wasp or improving performance. Focus on other optimization techniques if TypeScript seems overwhelming at this point.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @NEROX, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?@kapa.ai Based on:
Wasp Launch Week #7
Day 2. Stick to the Script! 📑
You can now write your Wasp config file in TypeScript (available as a preview feature)!
Could you give more details and random ideas of what could I do with this? Can I have several separated main.wasp files? or I'm wrong?
Let me check the knowledge base for you again. One moment! :books:
----------------------
Based on the information provided in the knowledge sources, I can give you some insights about the TypeScript support for Wasp config files and the possibility of splitting the main.wasp file.
Regarding TypeScript support for Wasp config files:
1. This feature is currently available as a preview feature in Wasp Launch Week #7, Day 2.
2. It allows you to write your Wasp configuration using TypeScript, which can provide benefits like better type checking and improved IDE support.
However, I don't have specific details about how this TypeScript support is implemented or what exact capabilities it offers, as it's not mentioned in the provided knowledge sources.
As for having several separated main.wasp files:
Currently, it's not possible to split the main.wasp file into multiple files. However, this is a feature that the Wasp team is planning to implement in the future. Here's what we know:
1. Many community members have requested this feature, as noted in several Discord threads Discord support thread: Can I split up the main.wasp file into seperate files > Answers (https://discord.com/channels/686873244791210014/1216264399552122922).
2. The Wasp team has acknowledged this need and is planning to implement it in a future update Discord support thread: Can I split up the main.wasp file into seperate files > Answers (https://discord.com/channels/686873244791210014/1216264399552122922).
3. When implemented, this feature will likely include support for:
- Multiple Wasp files/modules
- Ability for these files to import each other
- Scoped declarations/identifiers within modules
Github Issue (open): RFC: Wasp IDE Integration > Comments Part 7 (https://github.com/wasp-lang/wasp/issues/604)
4. The implementation of this feature is not straightforward, as it opens up questions about (sub)modules, imports, etc., which is why the team wants to take time to refine this approach Discord support thread: Can I split up the main.wasp file into seperate files > Answers (https://discord.com/channels/686873244791210014/1216264399552122922).
While you can't currently split the main.wasp file, the TypeScript support for config files might offer some improvements in terms of organization and type safety within your single main.wasp file. However, without more specific information about the implementation, it's hard to give concrete examples of what you could do with this new feature.
For the most up-to-date and detailed information about these new features, I recommend checking the official Wasp documentation or reaching out to the Wasp team directly.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @NEROX, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@kapa.ai Is any performance improvement in 0.15 vs 0.14? I'm not interested in the DB, I'm interested in the front/client
Let me check the knowledge base for you again. One moment! :books:
Sorry @NEROX, I am experiencing especially high traffic right now, please try again. :technologist:
It's purely a "nice-to-have" feature, that makes it easier for developers familiar with TypeScript to use it instead of the Wasp DSL (via
main.wasp
). But it won't improve the Core Web Vitals or performance of your app, because in the end Wasp compiles your app down to the same thing, regardless if you use the TS Config or the original Wasp DSL config.
Does that answer your question @NEROX ?Yes, your response is perfectly helpful for me to understand. Thank you, Vinny.
I'm currently working on improving performance, and right now, I’m using the official React documentation on optimization and performance, which is quite extensive. I’m making changes with Cursor and have managed to delay loading for some components, like the footer, certain menus, and other elements that don’t need to load initially, such as features or faqs components. This way, only the hero component loads first. I've even managed to make Googlebot detect only the rendering of the navbar initially.
However, I’m having issues with priority. For example, I’ve managed to make certain components, like the cookie pop-up and consent modal, load faster, but the main issue is that, despite thoroughly refactoring everything to clean up the code—organizing everything into components that are loaded properly—the entire app still loads in a waterfall pattern across all pages.
Since the type of application I’m building doesn’t need elements like authentication, admin panels, queries, stats, login, or subscriptions right now, I’ve commented out and disabled those features. Still, performance has only improved by about 1-2%, and the main issue is that everything loads in a cascade. The app fully loads before rendering the initial page that should appear on the first screen, leading to poor metrics for LCP, even though CLS and TBT are really good.
Will save this as checkpoints
Thanks for the thorough response.
Sounds like you've done a lot of work already. Maybe @miho can comment here about other approaches you can take to improve load times.
With that said, this is a priority for us and we will try and fix it as soon as we can
I will add these 2 videos as resource:
- https://youtu.be/-4fyyyQjsz8?si=7j0q3U30A_ZVKibM
- https://youtu.be/0fONene3OIA?si=2SnmSVDdXW__i3uB
Searching in YT : react spa pagespeed
I checked yesterday them and give me context of what things I worked today, maybe I missed something part important of the video or maybe I didn't undestood somethingPedroTech
YouTube
How to Improve Performance in React with Code Splitting
Hey everyone, in this video I will be going over the concept of code splitting and lazy loading your code in react.
Join our Discord: https://discord.gg/WE92Cqs6Vk
🚀 Learn ReactJS By Building 6 Projects: https://codedamn.com/learn/reactjs-projects
🐙 GraphQL Course: https://codedamn.com/learn/graphql-for-beginners
► Buy Crypto on Coinbase: coi...
Beyond Fireship
YouTube
The ultimate guide to web performance
Learn how to analyze and optimize the performance of any website. In this tutorial, we explore tips and tricks to build faster UIs that are ideal for search engine optimization.
#webdevelopment #javascript #css
🔥 Become a PRO member https://fireship.io/pro
💵 Use code BEYOND25 to save 25%
Unlighthouse https://github.com/harlan-zw/unlighthous...
But most of the routing and loading of components (as talked abouat in the first video) is being done by wasp behind the scenes, so you can't lazy load them
Oh, so that's exactly the problem :(
It's on our TODO list 🙂 https://github.com/wasp-lang/wasp/issues/2007
GitHub
Add support for lazy loading Wasp routes · Issue #2007 · wasp-lang/...
Quote from here: Lazy loading is a strategy that defers the loading of non-essential resources until they are needed, reducing the initial loading time and improving the overall performance of the ...
So having my app on 0.14 would it be a good idea migrating to 0.15?
I think it's easier to migrate the app with each version so you don't have to migrate more versions at a time 🙂 https://wasp-lang.dev/docs/migration-guides/migrate-from-0-14-to-0-15
There are some changes you'll need to do - but nothing major. Of course, each migration takes time and you'll have to be careful about it 🙂
Migration from 0.14.X to 0.15.X | Wasp
What's new in 0.15.0?
Lazy loaded the main child in
App.tsx
:https://pagespeed.web.dev/analysis/https-toograded-com/4fe36ixmba?form_factor=mobile:anim_happy:
No more margin availableOh wow. can you share the code? How did you also get SEO to 100?
Are tyou doing somethign like this @NEROX ?
If so, I'm not sure that's actually causing the lazy loading of the individual pages
I did:
return (
<HelmetProvider>
<Suspense fallback={
<div className='min-h-screen animate-pulse bg-neutral-100 dark:bg-neutral-900' />
}>
<div className='min-h-screen dark:text-white dark:bg-neutral-950'>
<Helmet>
{/* Preconnect y dns-prefetch */}
<link rel="preconnect" href="https://toograded-server.fly.dev" fetchPriority="high" />
<link rel="dns-prefetch" href="https://toograded-server.fly.dev" />
{/* Google Fonts preconnect */}
<link rel="preconnect" href="https://fonts.googleapis.com" fetchPriority="high" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
{/* Font loading */}
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap"
rel="stylesheet"
media="print"
onLoad={(e) => {
const target = e.currentTarget as HTMLLinkElement;
target.media = 'all';
}}
/>
<noscript>
{
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap"
rel="stylesheet"
/>
}
</noscript>
</Helmet>
{isAdminDashboard ? (
<Suspense fallback={
<div className='min-h-screen animate-pulse bg-neutral-100 dark:bg-neutral-900' />
}>
{children}
</Suspense>
) : (
<>
{shouldDisplayHeader && (
<Suspense fallback={
<div className="h-20 bg-white dark:bg-neutral-950 animate-pulse" />
}>
<Hero />
</Suspense>
)}
<main className='mx-auto'>
<Suspense fallback={
<div className='min-h-screen animate-pulse bg-neutral-100 dark:bg-neutral-900' />
}>
{children}
</Suspense>
</main>
<Suspense fallback={
<div className="h-96 bg-white dark:bg-neutral-950 animate-pulse" />
}>
<Footer />
</Suspense>
</>
)}
<Suspense fallback={null}>
<CookieConsentBanner />
</Suspense>
</div>
</Suspense>
</HelmetProvider>
);
}
It seems correct and I accept it, but then I don't know how it is that from this morning (50 point) to this afternoon (+70 point) the performance has been increasing.
Regarding the 100% SEO, I can't tell you right now exactly what it has been since my homepage is very different from OpenSaaS for example and the SEO should be reviewed page by page.Ok cool! Thanks for the info. 🙂
Do you like it @Vinny (@Wasp) ?
haha nice seo score
wanna submit a PR for it on the Open SaaS repo?
I was trying to improve performance yesterday. I got it to 56, but I'm going to wait until we update Wasp to user Lazy Loading internally before I continue working on Open SaaS performance.
I wanna try:be:
I saw that in production (fly in my case) it gives more performance score compared to localhost
That's good
yeah no worries. Let me know if you have any questions
and if it's too much work, at least just letting us know generally what you did would be helpful. you can write it here if you want.
Well... Any resource to understand how to work with PRs...? I owe a modification to Martin at https://github.com/wasp-lang/open-saas/pull/297 and I don't know how to update it...
GitHub desktop I have it more or less under control. I know how to work in branches, get repos and do certain things but no more
GitHub
Improved seo docs page by NeroxTGC · Pull Request #297 · wasp-lang/...
Description
Added Other Pages Meta Tags & Structured data and Schema markup.
Contributor Checklist
Make sure to do the following steps if they are applicable to your PR:
Update e2e te...
https://pagespeed.web.dev/analysis/https-closedsaas-client-fly-dev/ycqs55eo0g?form_factor=mobile (58)
Now I will try to improve performance
Heyy @Vinny (@Wasp) check this! https://gist.github.com/NeroxTGC/27a588ad5d78cf09a0b4464321eb5921
Gist
100% SEO Score with OpenSaaS Template
100% SEO Score with OpenSaaS Template. GitHub Gist: instantly share code, notes, and snippets.
I also have here the correct changes in my cloned repo
wow this is really nicely made. Thanks for this!
@miho maybe we could add this to your Learning Resources repo?
btw for the first one, you can just add the meta description to the
head
field of your main.wasp
file
you don't need to use Helmet for thatI've added it 🙂
Should I update it?
yeah I would
I have updated the gist by changing helmet's solution to uncomment and set the goals in main.wasp.
I also wanted to comment that the pages
Login
, signup
, requestpasword
, etc... They should be in noindex, it's a good SEO practice.
In the same way with the NotFoundPage.
@CamBlackwood did a very good workk with creating the 404! and to improve it would be also a VERY good practice to put that page as noindex
.