Even though we strive for a minimal JavaScript load on dev.to, we had gotten lazy with our optimization. Our vendor.js file, which includes all the...
For further actions, you may consider blocking this person and/or reporting abuse
Hat tip to @nickytonline for first introducing this concept into the DEV codebase a while ago.
Thanks for a great post going over this stuff @goenning .
We're all making @addyosmani proud. 😄
Great stuff! If you keep looking, you'll find many more places you can apply this!
Chrome Code Coverage is also a great tool to find downloaded javascript/css that has not been used.
Wasn't searching for the 🎩 tip, but I'll take it! It's still crazy how little effort it took to get that perf gain. 💪💯
So proud! :') Great work, Ben and team! These kinds of vendor bundle savings are awesome to see. Also, so good all of these are open-source for others to learn from.
Might be worth considering bundlesize for CI/PR JS budgets at some point :)
Noice! For those interested, here's another PR in the codebase that uses a dynamic import... because perf!
github.com/thepracticaldev/dev.to/...
It's a good use of a dynamic import in this case because we only want to load the on-boarding flow if the user has never seen it.
You can make a second step, and load it when its needed (or not load when its not needed - i assume not every page needs it).
Simplified example for prism.js:
Notes:
And then call it from your js, when something happens.
If dev.to wasnt so heavy into react i could do some good with my webpack knowledge, but i dont want to get dirty with all the abstractions in there ;)
Unfortunately, Firefox has not yet implemented dynamic import. How do you do progressive enhancement for module browsers that don't implement
import()
?TLDR; : with transpilation
dev.to uses webpacker which supports dynamic import (it also supports prefetch and preload). This in turn is supported through Babel (a transpiler), with @babel/plugin-syntax-dynamic-import
AMD?
What do you mean?
well, in order to transpile
import()
you need a way to a) convert modules to scripts and b) dynamically load those scripts.Sounds like Async Module Definition.
I did a half-hearted poke through the production code, and it looked more like cjs to me. Just curious what kind of 'modules' are actually serving down to clients.
Great job Ben =)
Out of curiosity, where are the other 194KB? I would assume they are in another vendor chunk. Right?
Webpack 4 has the concept of initial and async chunks. Dynamic imports are automatically separated from your original bundle.js and are downloaded on demand by the Webpack runtime.
An interesting thing is that you can prefetch your async bundle. Prefetching is an ambiguous term but it means that the browser will download this resource with super low priority. This is cool because you can induce the browser to not block your render but download it as soon as possible in such a way that it will possibly be already there by the time it is needed. I didn't check the internals of how this works in Webpack 4 but there is a high change that the Webpack runtime will auto prefetch async bundles.
The other 194 are in chunks that load when
import
is called within the code.Some are quite deep in app logic and we really never want them for most visits. They are only called as necessary. We would maybe want to prefetch them once folks get close to where they would be hidden, but that's about it.
Is it possible to use async/await ?
Yes, looks like it
I presume you could do something like this?
How is this better than just using a promise, as shown in the post?
you could even
Which is similar to the static syntax
Good job Ben! Hats off to you and @goenning for showing this technique.
Good job
Thanks!
This is very nice ! I didn't know Dynamic import at all, and I'll definitely try it out !
I did a talk about this subject. Great stuff.
github.com/iruzevic/presentations/...
Great one! Thanks for sharing Ben :)
Import on Demand.
I think this post by @quii is relevant to this discussion. I hope we can do a lot more to improve on this front.
The Web I Want
Chris James
This is cool, I haven't seen this technique before
Is there a chance it could make some features a bit slow when they're first used?
So if i click some button, it's now that it downloads, parses and executes the JS; which might be slow.
I guess it's all trade offs and from my point of view it seems like a good one.
Prefetching would be the next step but it requires more than 5 minutes:
The other 194 are in chunks that load when
import
is called within the code.Some are quite deep in app logic and we really never want them for most visits. They are only called as necessary. We would maybe want to prefetch them once folks get close to where they would be hidden, but that's about it.
Yeah, you still download it only one time