vNext Async Dependencies Part II

by Troy Rhinehart

Why?

  • Lodash (8.4%)
  • OLS Core (2.6%)
  • HTTP/2 +Cache (15 deps)
  • Shared Deps
    • editor
    • api
    • render
    • sdk-app

Lodash

  • Ship Core instead of Full
    • ~24kB vs ~4kB gzipped
    • 83% decrease
  • Add more as needed

import _, { merge, forEach } from 'lodash';
import _ from 'lodash/core';
import merge from 'lodash.merge';
import forEach from 'lodash.foreach';

before

 

after

How?

  • AMD
  • SystemJS
  • Registry?

AMD

Asynchronous module definition

define("components/Hello", [
  "react"
], React => {
  return props => {
    return React.createElement("h1", props, "Hello World")
  };
});

define("app/index", [
  "react", "react-dom", "components/Hello"
], (React, ReactDOM, Hello) => {
  ReactDOM.render(
    React.createElement(Hello),
    document.getElementById("app")
  );
});

require(["app/index"]);

CURL

AMD Loader

// Single dependency
curl("react", React => {
  ...
});

// Multiple dependencies
curl(["react", "react-dom"], (React, ReactDOM) => {
  ...
});

// Promise
curl(["react", "react-dom"]).then((React, ReactDOM) => {
  ...
}).catch(err => {
  ...
});

Config



curl.config({
  baseUrl: `https://${process.env.CDN_URL}`,
  paths: {
    react: 'react@15.6.2/dist/react.min.js',
    lodash: {
      location: 'lodash@4.17.5',
      main: 'core.min.js',
      config: {
        loader: 'curl/loader/cjsm11'
      }
    },
    '@wsb/guac-widget-core': {
      location: '@wsb/guac-widget-core@3.12.0/dist/core.min.js',
      config: {
        loader: 'curl/loader/legacy',
        exports: 'Core'
      }
    }
  }
});

Loader Component

import React from 'react';
import { Loader } from '@wsb/thing';
import Component2 from './Component2';

function Component (props) {
  return (
    <Loader Immutable assign="lodash/assign">
      <Component2/>
    </Loader>
  );
}
import React from 'react';

function Component2 ({ Immutable, assign, ...props })) {
  return ...;
}

Loader Component w/ Custom Render Function

import React from 'react';
import { Loader } from '@wsb/thing';
import Component2 from './Component2';

function Component (props) {
  return (
    <Loader Immutable assign="lodash/assign">
      { (loaded) => (
        <Component2
          Immutable={ loaded.Immutable }
          assign={ loaded.assign }
        />
      ) }
    </Loader>
  );
}

Extends

react-loadable

Loader Component w/ Loading Logic

import React from 'react';
import { Loader } from '@wsb/thing';
import Loading from './Loading';
import Component2 from './Component2';

function Component (props) {
  return (
    <Loader Immutable assign="lodash/assign" loading={ Loading }>
      <Component2/>
    </Loader>
  );
}
import React from 'react';

function Loading ({ error, pastDelay }) {
  if (error) {
    return <div>Error!</div>;
  }
  if (pastDelay) {
    return <div>Loading...</div>;
  }
  return null;
}

vNext Async Dependencies - Part II

By gingur

vNext Async Dependencies - Part II

  • 88