I have a pretty large ember-cli application, where the production build for app.js is exceeding 1mb and we aren’t even done yet.
The initial load time is taking too long. It’s possible we shouldn’t have been so ambitious in trying to do everything in one app, but now that we’re here and committed to that I’m wondering how we can go about cutting down the initial load time.
I know fast boot is still a ways away, so what are some of the strategies we could use now to cut down the load time?
Split the app up?
RequireJS / AMD?
Have you analyzed the network traffic to see what’s taking the longest? Even on 3G, a 1MB file should only take 1 second (http://www.download-time.com/) to download. My guess is that your data requests are your real bottleneck. The
model hook in a route will wait for promises to resolve before completing the transition, so a long data request can make your app feel really slow. Here are some things you might be able to do:
- Using the
loading hook in the route is a great way to communicate to your users that something is working. Spinners are a common go-to, but a “skeleton” layout (think of how Facebook does loading) is even better.
- Parent routes will render first, and you don’t have to make async requests to get some of your application’s scaffolding rendered. Refactoring out headers, footers, etc. from routes that have to request data will get stuff on screen faster
- “Preloading” some data is a good way to get actual content on the screen quickly. Check out Store - 4.6 - Ember API Documentation
1mb should take 1 second in ‘Turbo 3G’ which that site characterizes as 7.2 mbps. I think most people that have 3g are actually more in the 1-4 mbit/s range, and that’s in good conditions. At that rate, 1-2mb download before seeing anything could be an 8-16 second wait. Too long, obviously.
Thank you for your suggestions! We’re going to go with a spinner or skeleton for now, but I was really hoping somone had figured out how to do RJS/AMD style with ember even though tom dale is against it.
Hopefully fastboot solves this woe!
Is there a good strategy for this? Do you
pushPayload based on the entry route? If so, that does mean you maintain a route table on the server-side 1:1 with your Ember routes?
The strategy is basically to design the site so that the initial content is predictable. You can
pushPayload a hand-written JSON object, and the app will never actually request them from the server (only the store), so no need for sync. You need to be careful to make sure that any relationships match what you have in persistence and all of your async relationships are labeled correctly.
So, it looks like you’re loading something from the database (and it may also be in there), you can still use Ember Data to interact with them as loaded “records”, but you really just hardcoded some JSON in.
Ah! If you’re trying to get a faster response than that on 1-4mbit/s, The only real option (save Fastboot) that I can think of is to chop your app up a little more (maybe sub-apps off the same domain?)
Webpack allows splitting your app into chunks for this purpose exactly. I would love to see this sort of thing built into Ember CLI / Broccoli.
Try https://github.com/vectart/ember-cli-pace as a pre-loader. I haven’t personally used it but it takes a very similar approach to a pre-loader I hand-wrote for a mobile Ember app. Ideally the whole app payload would be smaller, or there’d be lazy loading, but for our app/use case, having the feedback a loading bar while the JS / CSS assets are downloading made all the difference.
If you’re app has support for different languages, then don’t save the translations inside your app. Usually these get bundled into the app.js making the file bigger based on how huge your translations are. Most i18n libraries in ember addon space have support for initializer phase where you can load these by making a call to your server. It shaved off a lot on my app.js, YMMV