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

Pava - JavaScript: the fast & the furious

By sergiu_enasoaie

Pava - JavaScript: the fast & the furious

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!

  • 205