Production optimization withReact and Webpack
@k88hudson Firefox Engineering, Mozilla
🏎
Abstracts away the DOM
Works on servers, native apps, …Firefox?!?
It’s fast*Helpful errors
Deterministic component rendering
Lifecycle
Testable
node_modules file system
single bundle for client-side applications
Users have high standards for performance
Good optimization is not just making everything faster, smaller and more
fault tolerant…
…it’s about being aware of your options and making the right
compromises.
Everyone has Opinions™
Laws of benevolent optimization
Laws of benevolent optimization
1. Don’t optimize prematurely 2. Know your options 3. Instrument your sh*t 4. Set benchmarks that make sense for
your actual users
1. Don’t optimize prematurely
Before you optimize…• Know what you’re building, address the UX/
product risk first
• Are your engineers on the same page as your designers/product? Do you share a common goal?
• Finish a few rounds of internal testing
• Have a good idea of who your users are
You might be ready to optimize if…• You’re about to ship a product to market,
particularly on devices or in conditions that are different from your development environment
• You’ve already shipped an MVP and are seeing latency/perf/errors bog you down
• You’ve already shipped a product and have no idea if it’s performing well but you feel like you should probably figure that out
2. Know your options
Where can we optimize?
Development Build time
RuntimeAnalysis
Webpack—optimizing at Build time
Development
Optimizing at build time
Transform code (for size, compatibility)
Manage configuration
Remove unused, non-essential code
Re-structure files/output
main.js
main.bundle.js
Typical Webpack set-up
Using custom loaders
Compiling ES2015 and JSX
<Foo bar />
React.createElement(Foo, { bar: true });
How big is the bundle?
Without webpack
react.js 628K react-dom.js 4.0k
With webpack
main.js 648K
Webpack’s built-in production optimization plugins
webpack -p
Webpack’s built-in production optimization plugins
• optimize-minimize (UglifyJS)
• optimize-occurrence-order
• optimize-dedupe
With webpack -p
main.js 172K (-476k)
Another option— Using the production build directly
With resolve/externals
main.js 136K (-512)
Use a production build of React
process.env.NODE_ENV
Use a production build of React
How DefinePlugin works
Using DefinePlugin for dev-only dependencies
my-dev-logger will not be included in the bundle.
With webpack -p NODE_ENV=production
main.js 128K (-520k)
This is stuff you should definitely be doing.
3. Instrument your sh*t
webpack-bundle-size-analyzer
React—optimizing at Runtime
First-load latency
First-load latency
First-load latency
General optimizations
If we render with JS…
Server-side rendering with react
Precompile the initial state
Instrumenting performance
Instrumenting performance
Time to first React render
Time to first React renderwith content
Total render time
What if we’re havingrendering issues?
Reasons this might be a problem
• You are manipulating or reading the DOM directly
• You are handling very large arrays of complex elements
• Your business logic contains computationally expensive functions
• You are rendering very complex DOM elements (such as SVG visualizations)
Manipulating/reading the DOM
Using keys correctly
Using keys correctly
Using keys correctly
shouldComponentUpdate
shouldComponentUpdate
Use React Perf toolsrequire(“react-addons-perf“);
Perf.printInclusive
Perf.printExclusive
Perf.printWasted
Perf.printOperations()
Laws of benevolent optimization
1. Don’t optimize prematurely 2. Know your options 3. Instrument your sh*t 4. Set benchmarks that make sense for
your actual users
What should you benchmark?
• File size
• Time to first load
• Time to render
What is acceptable depends on who your users are what they’re likely to expect
The difference between over-engineering and good engineering
is making the right compromises
Thanks! Tweet at me @k88hudson
😎