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