import { CodeSurfer } from 'mdx-deck-code-surfer' export { future as theme } from 'mdx-deck/themes' import { Split } from 'mdx-deck/layouts' import { Appear, Image, Head } from 'mdx-deck' import nightOwl from "prism-react-renderer/themes/nightOwl"
<title>Better Performance with Lazy-Loading and Code-Splitting</title>👋 I'm Jose and I work as an Engineer in Spotify
🚀 I like building & using web sites with good performance
@jmperezperez on Twitter
- Create a component to perform lazy-loading
- Apply the component to other use cases
- Loading polyfills on-demand
- Existing implementations
export default Split
const Page = () => {
<div>
<Header />
<Gallery />
<Map />
<Footer />
</div>;
};
Most times you would include all the scripts and CSS needed to render all sections as soon as the user visits the page. Until recently it was difficult to define a module’s dependencies, and load what was needed.
- How likely is it for the user to see the header?
- What about the map?
- Track dependencies (YUI Loader, RequireJS → ES6 + dynamic imports)
- Lazy-loading (Scroll + Resize listeners → IntersectionObserver)
export default Split
export default Split
Invisible content in some scenarios
- printing the page
- RSS readers
- SEO
<CodeSurfer title="High Order Components" theme={nightOwl} code={require("!raw-loader!./snippets/comp-pattern-hoc.mdx")} />
<CodeSurfer title="Function as Child Component aka Render Callback" theme={nightOwl} code={require("!raw-loader!./snippets/comp-pattern-child.mdx")} />
<CodeSurfer title="Our Component ⬇️" theme={nightOwl} code={require("!raw-loader!./snippets/comp-basic.mdx")} steps={[ { ranges: [[6, 6], [24, 28], [32,32]]}, { ranges: [[4, 4], [9, 12], [29, 31]]}, { ranges: [[14, 18]]}, ]} />
<CodeSurfer title="Using it" theme={nightOwl} code={require("!raw-loader!./snippets/comp-basic-use.mdx")} />
<CodeSurfer title="Stateless Child Component ⬇️" theme={nightOwl} code={require("!raw-loader!./snippets/gallery-stateless.mdx")} steps={[ { ranges: [[1, 1], [5, 9]], notes: "Using isVisible ➡️️" } ]} />
<CodeSurfer title="Stateful Child Component ⬇️" theme={nightOwl} code={require("!raw-loader!./snippets/map.mdx")} steps={[ { ranges: [[30, 38]]}, { ranges: [[8, 28]]} ]} />
<CodeSurfer title="Moving state to the Observer component" theme={nightOwl} code={require("!raw-loader!./snippets/has-been-visible.mdx")} />
<CodeSurfer theme={nightOwl} code={require("!raw-loader!./snippets/conference-data.mdx")} steps={[ { ranges: [[9, 21]] } ]} />
<CodeSurfer title="Disabling lazy-loading if IO is not supported" theme={nightOwl} code={require("!raw-loader!./snippets/disable-lazy-loading.mdx")} steps={[ { ranges: [[6, 6], [12, 12]] } ]}/>
<CodeSurfer title="Requesting a polyfill on demand" theme={nightOwl} code={require("!raw-loader!./snippets/polyfill-on-demand.mdx")} steps={[ { ranges: [[4, 8]] } ]}/> />
Safari requests the polyfill for intersection-observer on demand.
No need to ship it to browsers that support it natively.
- react-router and Next.js have made code-splitting easy to implement
- lazy-loading can be applied to other resources (SVGs, CSS)
- With CSS-in-JS we take code splitting further, loading CSS on demand