Hi
I finally uploaded my software to the server, but when I check the performance of the site with Google tools and https://gtmetrix.com/, we see that it is very low.
-My server has 2 G RAM and 2 CPU cores.
I used prerender and handled it with my nginx middleware.
@captainn maybe you have success case for such optimisation?
I just cloned package/collection2 folder to my_project/packages/ folder (or you can you symlink) and make changes from PR.
In your client’s startup script, you should import it dynamically like:
imports/startup/client/index.js:
Meteor.startup(async () => {
await import("meteor/aldeed:collection2");//dynamic import for meteor package
await import("yourRoutesFile.js"); // your entry point for router
await import("..."); //other stuff if it needs
});
You have to be aware, that some packages immediately add a lot of code to your bundle via api.addFiles. This can increase your bundle dramatically. Besides that here are some (incomplete) tips for reducing your bundle size:
use dynamic import where you can, especially on a router level: only the code relevant for the current route should be imported.
import layout-related components first, then load the data after the component has at least drawn once and display some loading indicators while the data loads
avoid packages that add many files to the bundle via api.addFiles
use api.mainModule on your own packages and combine it with dynamic import to load package content not before it is actually used
defer loading of css styles and fonts after start and provide a minimal css for the landingpage / loginpage etc.
load all images, videos and iframe content lazy (I use lozad NPM package for this but there are many others for this)
don’t forget to dynamically import all your JSON content! It is easy to hard-wire JSON files into your bundle. Especially large files for i18n increase bundle size a lot.
avoid auto-publishing where you can and start subscribing after your initial bundle has arrived at the client (use Meteor.startup to defer execution after bundle loading)
set the html head <meta charset="utf-8"> at the very first tag in your head or the browser will re-evaluate all your html once it finds this tag anywhere else
use google lighthouse (in chrome embedded) to find yet hidden issues
These are rather general hints and should apply independently from using server/client or SSR.
Some of the parameters/ scores make relevance(or need to be prioritised ) depending on your app and its purpose. If you are using your meteor app site as a means of customer conversion or stickiness then yes quick loading is important otherwise they may loose interest.
In other words take a call based on your end goal. This does not mean performance is not important, it is upto you to decide which parameter your end user looks for and focus on it.
I found the link responsive and it seems fine. But then performance depends on so many other things and they change over a period of time.
Meteor Framework itself brings its constraint so focus on solving that is possible to be solved. And not all things have to be done on day one.
Also, note gtmetrix server is based out of Canada, not sure where your server is …it will add to latency.
Using bundle-visualizer I just managed to find a serious problem with react-icon, which made the packaged file shrink by 40% and reduced its speed by 1 second for the first opening and 600 milliseconds for the second opening
However, I also have a problem to solve, using the above code, SSR function is invalid, SSR is not supported, according to the @nathanschwarz prompt, do not use react on the server side, but I do not understand, has not been successful
First of all, you should run bundle visualizermeteor --extra-packages bundle-visualizer --production and go to http://localhost:3000 to understand what exactly should be extracted from main js bundle.
Probably your ../../Routes/Routes file contains many imports, which can be dynamically loaded.
The second improvement which we’r now implementing - cut off React+React-dom from the main bundle and load it after DOM ready.
Lets see example, based on your code.
I move your code from project_name/client/index.jsx(maybe another file, IDK) to project_name/client/react.jsx;
project_name/client/react.jsx:
import React from 'react';
import {render} from 'react-dom';
import {BrowserRouter as Router} from "react-router-dom";
import {HelmetProvider} from 'react-helmet-async';
import Routes from "../../Routes/Routes";
const helmetContext = {};
render(
<HelmetProvider context={helmetContext}>
<Router>
<Routes/>
</Router>
</HelmetProvider>
,
document.getElementById('App')
);
Rename index.jsx → index.js and add a new code:
import { Meteor } from 'meteor/meteor';
// Custom splash screen/loading indicator
// You can use css animation, more complex HTML etc.
const splashScreen = document.createElement('div');
splashScreen = `Loading...`;
const showSplashScreen = () => {
document.body.appendChild(splashScreen);
}
const hideSplashScreen = () => {
document.body.removeChild(splashScreen);
}
Meteor.startup(async () => {
showSplashScreen(); //also we can call it in DOMContentLoaded event
await import('./react.jsx'); //import our react's stuff dynamically
hideSplashScreen(); //hide loading indicator
});
react-dom should be removed from the main bundle after these changes. If not - it means that some meteor package uses it and should be lazy loaded, as I described above.
To understand my approach, I suggest to create an empty project and try to improve the bundle size.
For our project, we expect that bundle size should be 400-500kb after such optimisation, and our routes file with react-dom - another 200-300kb.
I followed exactly this example, but it did not change.
I checked the packages, packages like react-bootstrap and ostrio: files are relatively large.
Now exactly how can I implement them with lazy?
As I understand it, I do not have to do anything special, but that package must take the necessary measures.
Thank you for explaining on a package with an example