First Visit Loads are Ridiculously Slow

I deploy through kadirahq:mup. Yes they are installed.
standard-minifier-js v1.2.0.

Can someone help please?

21MB! That’s way too huge a bundle! Apart from ensuring that they’re getting minified, are you sure you have segregated files properly as client and server? i.e. are you sure there are no files in the client bundle that will not be used in the browser? For more details, refer: https://guide.meteor.com/structure.html#special-directories

Yes I have already done that. The structure is more or less derived from the guide:
|____server
|____public
|____node_modules
|____imports
| |____conf
| |____language
| |____startup
| | |____server
| | |____both
| | |____client
| | | |____lib
| | | |____routes
| |____api
| |____client
| | |____pages
| | |____layouts
| | |____components
|____client
|____packages
|____common
| |____imports
| | |____lib
| | |____startup
| | |____api

If you see the non-minified app.js is 3mb only. It is the modules.js that’s huge. I will have to decrease the dependency on external modules.
But currently, the main problem is minification.

Finally, figured out.
I had foolishly copied mup.js from the docs which had debug: true, due to which meteor was building the app with --debug flag.

2 Likes

With one REALLY neat trick (clickbait lol), I have my fairly complex Meteor app with high quality video background (or image carousel on mobile) loading in a little over 200ms.

I don’t know of any sites with similar content on the entirety of the internet loading that fast, let alone anything using Meteor.

I had my app loading time down to 1-2 seconds through a combination of on-demand external loading of non-critical javascript libraries and separating out ‘admin’ functions (and packages) to a separate admin-only Meteor instance, but to get sub-second load times I figured something out that I hadn’t seen anyone doing yet.

I am not a web developer or programmer by trade so I hope I’m not doing anything too bad or breaking something I’m not aware of. My suspicion is I may be compromising SEO. I do of course have zero traffic for now so that probably helps :relaxed:

Will elaborate more on my main thread with a very overdue update.

1 Like

Way to whet the appetite!

1 Like

Sounds great! Waiting for the details.

From your source, it seems you are sending a pure html page (that matches to your home page), which gets loaded first while the js/css is being downloaded. Nifty!
Do let us know of further details.

Well since I got two responses already… spoiler alert :slight_smile:

You inject HTML server-side depending on the inbound client route, ensuring the DIVs have classes that indicates it is special server-rendered HTML. In your real client-side template javascript .onRendered calls (yep I’m using blaze!), execute $(’.ssrblahblay’) remove commands and your client-side templates remove the server-rendered HTML as they are initialized.

It was kind of magical to see this work and I expected to see some flickering and weirdness. I was actually a little surprised that I hadn’t seen this put together yet by anyone else.

And yes you’re technically sending down the same HTML twice, but the ‘cost’ of just some gzipped HTML is minimal.

I wanted to see if I could put some logic in the actual HTML I was sending to the client and found Arunoda’s SSR package which lets you pretty much copy/paste your client-side templates into being server side templates, even allowing you to replicate template helpers on the server. You can feed these templates variables which the helpers can then consume, which let you do things like render a server-side template for a possible user vs. non-user or pipe down language settings.

Arunoda’s inject-initial package also makes the whole injection thing pretty simple - at first I was using WebApp.connectHandlers.use which I learned about when I wanted to perform automatic geo-lookups for every new session (I now run geo-lookups in Meteor.onConnection…).

I also started doing the route/path detection with the Webapp connect handler function but decided to tidy things up and use my router – which is still good old iron-router. I have some routes specifically defined to show certain templates, and then I have a wildcard route which renders the navbar, a ‘loading’ screen in the middle, and then a footer, for any routes I haven’t fully defined yet.

I’m also using fast-render, so you’re also getting rapidly rendered data-driven templates as soon as they get to the client for most of my routes (once the primary meteor client JS payload is loaded).

A good bit of work to get rid of the empty white loading screen typical of Meteor apps, but I’m happy with the result. It’s all a pretty tenable solution that is now easy to manage.

I still haven’t described the little trick I’m using to knock down the page load time to 200-300ms - more on that later, though I think it’s icing on the cake at this point and the things I mentioned above are sort of prerequisites. Being actual developers and able to inspect the web code you will figure it out anyway :slight_smile:

5 Likes

Tell the world about it!

Hi! everyone. Im experiencing the same issue on a site we recently built. I wanted to see if anyone had any thoughts. The site link is below to check out.

Im thinking it has to do with the server downtime. if heroku shuts down the server it will take a bit to boot and then display the site but not totally sure just yet.

Id be appreciative of any feedback :slight_smile:

http://a-squared.cc/

It loaded almost instantly for me. :slight_smile:

It must be server side then. When we load the page and haven’t in a while it takes around 20 seconds.

Just tested it as well, took 20+ seconds for me. You’re probably running it on a free heroku dyno as you mentioned it shutting down, if so just pay the 7$ and you won’t have any trouble.

I’d like to throw Cloudinary in as an option to serve images http://cloudinary.com/ and this Meteor package https://github.com/Lepozepo/cloudinary .

Because send and retrieve is simple, you can also manipulate images upon request much like Drupal image styles (if you’re familiar with it). Very handy tool.

CC: @ashah888

2 Likes

Perfect thank you for the feedback !

Ok, since it’s now 2017 and I haven’t posted my long overdue response to my initial post about nibbl.com, here you go…

The thing I haven’t seen done anywhere yet, that I came up with myself to get instantaneous page loads, faster than any other website using Meteor (or even meteor.com!) and quicker than any other website doing the full screen background video thing:

Defer the execution of your client-side Meteor JS payload to the browser’s onload event. BOOM.

I have a server-side web handler that manipulates Meteor’s returned JS payload to ‘replace’ it with a function that executes the payload once the browser onload event occurs.

I use iron-router to provide a server-side wildcard route (this.route(’/:query(.*)’) and Meteorhacks inject-initial to apply this to any request.

This would be quite useless and strange without SSR to deliver something to the browser before the onload event, but when you use SSR, the experience is pretty awesome.

Will try to work on posting up a more complete working example of this on Github when I can. Basically, in the route action() function, you execute this:

Ugly but it seems to work for now. I’m a glorified scripter at best so take this all with a grain of salt :slight_smile:

7 Likes

Thanks!, Would it make cense to use this if I’m only doing client side rendering?

The technique is great (thanks to @benlavalley) , and it makes the websites ‘appear’ faster.
But I feel that it is difficult to code and maintain, because you need to create all those pages/templates again for SSR. I would personally advise you to just inject a simple loader on your webpage, so that people know that the data is coming, even before the app has been fully downloaded. That should be enough for small bootstrapped apps.

s7d, absolutely correct and that was what I considered trying to put together for an example.

Just sending down a simple "loading’ page to start and use that for injection into the client, then tear it down with the method I mentioned above with one of your real templates executing $(’#someloadingtemplate’).remove() in onCreated or onRendered. You could even have a ‘click here to try again’ if you’re worried about your loading page somehow getting stuck.

I didn’t find enough of a reason to leave Blaze yet for the web but plan to dive into React when biting the bullet to develop for iOS/Android – based on the page loading experiences with it (e.g. kadira) it looks like it does this kind of thing natively.