Comments (3)
Optimization: Reduce bloated dependencies to keep JS payloads smaller.
Step 1: Measure
We start out by testing npm run dev
. We know Vue doesn't apply all production optimizations at this point. We're looking at a 2.3MB payload overall:
Of this, 1.7MB of the payload is JavaScript:
Let's try running the production build to see how this changes.
Thanks to Vue's usage of the Webpack performance budget feature, we're able to highlight [big] files:
Lots of large PNGs/images but also a very large 2.16MB JavaScript vendor file. The rest of our application JavaScript is pretty small.
We can use Lighthouse to analyze how we're doing on performance:
We have large network payloads:
A lot of the initial JS bootup costs are low because we aren't doing a whole lot when the app first starts. Most of the UI that gets executed is on the next route:
And we can see that Parse/Compile of JS takes a few hundred milliseconds:
But enormous payloads are still the biggest problem.
Let's try analyzing this bundle in some more depth. Following https://code.luasoftware.com/tutorials/vuejs/vuejs-webpack-analyze-bundle-size/, we know we can run npm run build --report
to run Webpack Bundle Analyzer.
It gives us an output that looks like this:
with the drawer
That unicode (SO.js) module seems troublesome! The parsed cost is 1.64MB of code, which we know will take a few seconds to parse and gzipped that code is still ~93KB.
Where do we use this module?
- Having a hard time finding it. I looked in the source. No
unicode
orso.js
- Looked in package.json and lockfile. Seems it might be tied to a babel transform for regex/unicode
- Digging through npm, I see that this
unicode
module is relied upon by https://www.npmjs.com/package/slug (which we use for slugifying URLs). Let's try to replace it with something much slimmer.
We go to our editor, and because we're using the import-cost
plugin in VSCode, we can see that yes, slug does indeed take up a bunch of extra bytes and has a heavy weight:
BundlePhobia is a nice tool for finding out the consumption weight of different npm modules. We use it to test the slug module as follows:
and can then try out alternatives. I find one called Limax which is 42KB gzipped: https://bundlephobia.com/[email protected] and another called https://bundlephobia.com/[email protected] which is 4.2KB gzipped. Let's try that one.
Step 2: Optimize
Looks pretty okay in editor and bundlephobia. Let's use the slugify module.
When we make this change to our app, we can see that Vue's webpack build report changes:
We have now saved 1.72MB on the size of the bundle and it's down to 444KB.
This audit now passes the enormous payloads check in Lighthouse:
and here's some bumps in performance metrics:
Success
from oodle-demo.
Optimization: Remove unused/unnecessary dependencies to reduce JS payload size
Originally, we made changes to our app because we were experimenting with using Material Design - cards, toolbars, nav. Later, once we decided to go more custom, we kept these imports in and they were bloating our bundle.
We can also see that the Vue MDC adapter is taking up a chunk of our bundle:
Looking back after the last optimization, we were at 444KB for the size of the bundle.
Lighthouse audits for main thread consumption and JS bootup time:
Dropping the MDC Web JavaScript only, we're able to trim the bundles down much more heavily.
We can still use the CSS styles (which we import) as needed.
We shaved off 327KB off our bundle.
Everything seems to work as expected:
Lighthouse wise, this takes us from this:
to this:
Our network payloads and JS bootup time are down
from oodle-demo.
Optimization - code-splitting
Note: this may not be entirely practical for now, so documenting the change but not including in PR just yet.
Originally, we're looking at a 12-13KB app.js size:
This is before we even considered doing anything with code-splitting etc.
Let's look at the old code before we add code-splitting:
import DoodleHome from '@/components/DoodleHome'
import DoodleBrowse from '@/components/DoodleBrowse'
import DoodleFullscreen from '@/components/DoodleFullscreen'
import DoodleOffline from '@/components/DoodleOffline'
and after:
const DoodleHome = () => import('@/components/DoodleHome')
const DoodleBrowse = () => import('@/components/DoodleBrowse')
const DoodleFullscreen = () => import('@/components/DoodleFullscreen')
const DoodleOffline = () => import('@/components/DoodleOffline')
and if we want to name these chunks:
const DoodleHome = () => import(/* webpackChunkName: "doodle-home" */ '@/components/DoodleHome')
const DoodleBrowse = () => import(/* webpackChunkName: "doodle-browse" */'@/components/DoodleBrowse')
const DoodleFullscreen = () => import(/* webpackChunkName: "doodle-fullscreen" */'@/components/DoodleFullscreen')
const DoodleOffline = () => import(/* webpackChunkName: "doodle-offline" */'@/components/DoodleOffline')
Post-build, we're looking at some pretty small sized bundles now for each route:
With named chunks, it looks like this:
However...
I now notice a short lag before the doodles browser view loads. As the previous app chunks were small enough (12KB) we might want to suggest we tried code-splitting but it wasn't needed in the end, or, try to inflate the size of a route artificially so that the benefit is more pronounced.
from oodle-demo.
Related Issues (19)
- Mocks
- CSS Optimization
- Web Font optimization HOT 2
- Enable text compression HOT 1
- Reduce render-blocking stylesheets HOT 1
- Uses inefficient cache policy on static assets
- Progressive Web App
- Error: Cannot read property url of undefined
- Preload key requests HOT 1
- Compression/Brotli
- Improve speed HOT 3
- Introduce performance issues HOT 1
- Final updates
- Improve accessibility
- Support for working without JavaScript
- Doodle mini perf-audits
- Implement offline experience
- Design assets HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from oodle-demo.