JavaScript
the fast & the furious
Let's begin with the big question...
Are we alone in the Universe?
What happens after death?
Why should we optimize?
It's part of our duty as programmers... 👨💻
Mindset
Measure, Optimize, Monitor
📏 Measure
Lighthouse
+10s
load time
2.6M
javascript
The JS is already minified
Already done
📈 Optimize
#1 Code splitting
<Route exact path="/" component={LazyLanding} />
import React from 'react';
import Loadable from 'react-loadable';
import RouterLoading from '../RouterLoading.component';
const LazyLandingPage = Loadable({
loader: () => import('./Landing.page'),
modules: ['./Landing.page'],
webpack: () => [require.resolveWeak('./Landing.page')],
loading: RouterLoading
});
export default (props) => <LazyLandingPage {...props} />;
React
Angular
const routes: Routes = [
{
path: 'customers',
loadChildren: './customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: './orders/orders.module#OrdersModule'
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
= 70Kb
How about loading it just when I need it?
AKA: on button click
#2 Aggressive code splitting
onClick() {
import('../Swal.service').then(SwalService => {
SwalService.default(
/* ... */
);
});
}
React & Angular
But that's not it! Thanks to my 💩 phone...
<MonacoEditor />
2.6MB
javascript
class LazyEditor {
constructor() {
this.state = {
Editor: () => <div />
}
}
componentDidMount() {
import('./MonacoEditor.jsx').then(MonacoEditor => {
this.setState({
Editor: MonacoEditor.default
});
});
}
render() {
return <this.state.Editor />
}
}
#3 - Treeshaking
Include just the code you actually reference and use!
webpack ❤
// package.json
{
"sideEffects": [
"*.css",
"*.scss"
]
}
#4 Cheapest tool for the job
Check our progress
2.5s
load time
260Kb
javascript
+10s
load time
2.6M
javascript
#5 SW Precaching
...because now the UX kinda sucks!
self.addEventListener('fetch', function onFetch(event) {
if (event.request.url.indexOf(location.origin) === 0) {
event.respondWith(cacheOrNetwork(event));
}
});
Download from a Service Worker all the other
chunks & pre cache them.
#6 Server Side Rendering
-
100% SSR - which I didn't have time to implement 😅
-
or almost SSR - to help eliminate useless requests 😎
<body>
<script>
window.__PRELOADED_STATE__ = {
"user": {
"username": "iampava",
"email": "pava@iampava.com",
"avatarUrl": "/assets/images/avatars/i_avatar.png",
"hasFullSubscription": true,
"notifications": {
"unread": "20",
"list": null
}
},
"allTeams": [],
"currentTeam": null,
"joinTeam": null,
"exercises": {
"current": null
}
}
</script>
<script type="text/javascript" src="/dist/devdrive.7e79696e5c8a4011ba42.js"></script>
</body>
or
#7 Skeleton Screens
🔍 Monitor
Bundlesize 📦
{
"bundlesize": [{
"path": "./dist/**/!(*.worker).js",
"compression": "none",
"maxSize": "300 kB"
}],
"scripts": {
"perf-test": "bundlesize"
}
}
and and...
Lighthouse CLI 😍
$ lighthouse http://localhost:1234
--output json --output-path ./audit.json
but now what...?
Q&A
Thank you!
BONUS
Prezentare Pava
By alexb_90
Prezentare Pava
Building a performant, non-trivial web app is a challenge every developer must take, be it just for educational purposes. It's no small feat to accomplish this, as it requires curiosity and perseverance, as well as the technical skills to back them up!
- 564