Supercharge Front-End Performance with Build Optimizations and Smart Rendering
This article presents a comprehensive front‑end performance checklist covering JavaScript engine targeting, script defer and streaming, progressive boot, server‑side versus client‑side rendering strategies, hydration techniques, third‑party script management, self‑hosting assets, and proper HTTP caching headers to dramatically reduce load and interactive times.
Original source: https://www.smashingmagazine.com/2020/01/front-end-performance-checklist-2020-pdf-pages
Build Optimization
34 Optimize for target JavaScript engines
Identify which JavaScript engines dominate your user base and apply engine‑specific optimizations. For V8 used in Blink browsers, Node.js, and Electron, use script streaming to handle the whole script.
Script streaming allows async or defer scripts to be parsed on a separate background thread, potentially reducing page load time by up to 10 %.
Warning : Opera Mini does not support script defer, so defer will be ignored and block rendering.
You can also separate libraries from the code that uses them, or combine them into a single script to enable V8 code caching, or use v8-compile-cache.
Firefox’s new Baseline Interpreter and JIT optimization strategies further improve JavaScript execution speed.
Progressive boot means using server‑side rendering to quickly obtain the first meaningful paint while including the minimal JavaScript needed for interaction.
35 Client‑side or server‑side rendering? Use both!
The choice depends on performance goals. Progressive boot combines server‑side rendering for the first meaningful paint with a small amount of JavaScript to keep time‑to‑interactive (TTI) close to that paint.
If JavaScript loads too late after the first paint, the browser locks the main thread while parsing, compiling, and executing the script, harming interactivity.
Break functions into asynchronous tasks and use requestIdleCallback where possible. WebPack’s dynamic import() enables lazy‑loading of UI components, reducing load, parse, and compile costs.
TTI measures the time from navigation start to when the page becomes interactive, defined as a 5‑second window after initial paint where no JavaScript task exceeds 50 ms.
Frameworks often lack simple priority mechanisms, making progressive boot harder to implement, but recent discussions outline practical approaches.
Fully Server‑Side Rendered (SSR)
All requests are processed on the server, returning complete HTML. This yields fast first paint but may increase time‑to‑first‑byte due to server processing.
Static SSR
Build step pre‑renders each page to static HTML with minimal JavaScript. Netflix uses this to cut resource loads and halve TTI.
SSR + CSR with (Re)Hydration
The server returns HTML plus a script that loads the full client app. React uses ReactDOMServer.renderToString , Vue uses vue-server-renderer.renderToString , and Angular uses @nguniversal . Frameworks like Next.js and Nuxt.js provide full SSR experiences. Rehydration is expensive and can increase first‑contentful‑paint to TTI gaps.
Progressive (Re)Hydration with streaming SSR
Render multiple requests in parallel and stream HTML chunks, reducing first‑byte time. React’s renderToNodeStream and Vue’s renderToStream enable this. Future React Suspense may allow asynchronous rendering. Components are activated gradually based on priority, visibility, or user interaction. Vue’s lazy‑hydration plugins, Angular’s Ivy Universal, and Preact with Next.js support partial hydration.
Tri‑synthetic Rendering
Use a service worker to take over rendering after the initial streamed server render, allowing shared templates and routes across server, client, and service worker.
Tri‑synthetic rendering uses the same code in three places: server, DOM, and service worker.
Client Pre‑rendering
Build‑time static HTML generation using tools like Gatsby ( renderToStaticMarkup ) for React or Vuepress for Vue, often combined with prerender-loader and Webpack. This reduces TTFB and FCP but requires known URLs.
Fully Client‑Side Rendering (CSR)
All logic, rendering, and startup occur in the browser, typically increasing the gap between FCP and TTI. SSR is generally faster than CSR.
Choose CSR only for pages that truly need it; for complex apps, a hybrid approach is recommended.
36 Always self‑host third‑party resources
Self‑hosting static assets is a good rule of thumb. Relying on public CDNs rarely yields performance gains because browsers partition caches per origin, preventing shared caching across sites.
Self‑hosted resources are more likely to stay cached, are more reliable, and improve security.
37 Limit the impact of third‑party scripts
Third‑party scripts can dominate JavaScript execution time (up to 57 %). Regularly audit dependencies and use sandboxed iframes or CSP to isolate them.
Load third‑party code asynchronously, defer it, or use dns-prefetch and preconnect. Consider loading from your own server, lazy‑loading on user interaction, or using service workers to block or stub failing requests.
Use the sandbox attribute on iframes with appropriate allow values to restrict capabilities.
Intersection Observer can defer loading of off‑screen ads, and Feature Policy can limit harmful web features.
Stress‑test third‑party scripts with DevTools performance profiling or WebPageTest’s blackhole server, and map requests to monitor changes.
38 Set HTTP cache headers correctly
Ensure Expires, Cache‑Control, max‑age, and related headers are set appropriately. Short‑lived resources should have brief caching, while static assets can use long‑term caching with versioned URLs.
Use Cache‑Control: immutable for fingerprinted static assets (supported in Firefox, Edge, Safari) and consider stale‑while‑revalidate to hide latency.
Avoid unnecessary headers like X‑Powered‑By, Pragma, X‑UA‑Compatible, and ensure security‑related headers such as Content‑Security‑Policy, X‑XSS‑Protection, and X‑Content‑Type‑Options are present.
Be aware of the performance cost of CORS requests in single‑page applications.
References
[1] https://www.smashingmagazine.com/2020/01/front-end-performance-checklist-2020-pdf-pages
[2] https://blog.chromium.org/2015/03/new-javascript-techniques-for-rapid.html
[3] https://medium.com/reloading/javascript-start-up-performance-69200f43b201#3498
[4] https://medium.com/reloading/javascript-start-up-performance-69200f43b201#3498
[5] https://caniuse.com/#search=defer
[6] https://www.npmjs.com/package/v8-compile-cache
[7] https://hacks.mozilla.org/2019/08/the-baseline-interpreter-a-faster-js-interpreter-in-firefox-70/
[8] https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JIT_Optimization_Strategies
[9] https://aerotwist.com/blog/when-everything-is-important-nothing-is/
[10] https://aerotwist.com/blog/when-everything-is-important-nothing-is/
[11] https://davidea.st/articles/measuring-server-side-rendering-performance-is-tricky
[12] https://philipwalton.com/articles/why-web-developers-need-to-care-about-interactivity/
[13] https://aerotwist.com/blog/when-everything-is-important-nothing-is/#which-to-use-progressive-booting
[14] https://www.youtube.com/watch?v=k-A2VfuUROg
[15] https://medium.com/dev-channel/a-netflix-web-performance-case-study-c0bcde26a9d9
[16] https://alligator.io/react/server-side-rendering/
[17] https://alligator.io/react/server-side-rendering/
[18] https://ssr.vuejs.org/
[19] https://angular.io/guide/universal
[20] https://nextjs.org/
[21] https://nuxtjs.org/
[22] https://addyosmani.com/blog/rehydration/
[23] https://reactjs.org/docs/react-dom-server.html#rendertonodestream
[24] https://ssr.vuejs.org/guide/streaming.html
[25] https://medium.com/maxime-heckel/asynchronous-rendering-with-react-c323cda68f41
[26] https://markus.oberlehner.net/blog/how-to-drastically-reduce-estimated-input-latency-and-time-to-interactive-of-ssr-vue-applications/
[27] https://github.com/maoberlehner/vue-lazy-hydration
[28] https://github.com/vikerman/ivy-universal
[29] https://medium.com/@luke_schmuke/how-we-achieved-the-best-web-performance-with-partial-hydration-20fab9c808d5
[30] https://github.com/facebook/react/pull/14717
[31] https://medium.com/maxime-heckel/asynchronous-rendering-with-react-c323cda68f41
[32] https://codesandbox.io/s/progressive-hydration-react-1-k65r2
[33] https://codesandbox.io/s/progressive-hydration-react-2-2hprz
[34] https://codesandbox.io/s/progressive-hydration-react-3-geyzs
[35] https://github.com/GoogleChromeLabs/progressive-rendering-frameworks-samples
[36] https://nicedoc.io/theKashey/react-prerendered-component
[37] https://developers.google.com/web/updates/2019/02/rendering-on-the-web#trisomorphic
[38] https://developers.google.com/web/fundamentals/primers/service-workers/
[39] https://www.gatsbyjs.org/
[40] https://vuepress.vuejs.org/
[41] https://github.com/GoogleChromeLabs/prerender-loader
[42] https://itnext.io/server-side-rendering-with-react-redux-and-react-router-fa5b67d4965e
[43] https://www.youtube.com/watch?v=k-A2VfuUROg
[44] https://twitter.com/_developit/status/1093223382223605762
[45] https://csswizardry.com/2019/05/self-host-your-static-assets/
[46] https://calendar.perfplanet.com/2019/bundling-javascript-for-performance-best-practices/
[47] https://calendar.perfplanet.com/2019/bundling-javascript-for-performance-best-practices/
[48] https://almanac.httparchive.org/en/2019/cdn#cdns-for-common-libraries-and-content
[49] https://calendar.perfplanet.com/2019/self-hosting-third-party-resources-the-good-the-bad-and-the-ugly/
[50] https://github.com/patrickhulce/third-party-web
[51] http://conffab.com/video/taking-back-control-over-third-party-content/
[52] https://medium.com/caspertechteam/we-shaved-1-7-seconds-off-casper-com-by-self-hosting-optimizely-2704bcbff8ec
[53] https://gideonpyzer.dev/blog/2019/07/13/lazy-loading-zendesk-saved-huddle-2.3mb-of-javascript/
[54] https://caniuse.com/#search=sandbox
[55] https://www.smashingmagazine.com/2018/12/feature-policy/
[56] https://csswizardry.com/2017/07/performance-and-resilience-stress-testing-third-parties/
[57] https://www.twnsnd.com/posts/performant_third_party_scripts.html
[58] https://www.soasta.com/blog/10-pro-tips-for-managing-the-performance-of-your-third-party-scripts/
[59] https://csswizardry.com/2018/05/identifying-auditing-discussing-third-parties/
[60] https://docs.google.com/spreadsheets/d/1uTcRSoJAkXfIm2yfG5hvCSzvSZD9fAwXNQMVK3HdPMI/edit#gid=0
[61] https://www.youtube.com/watch?v=bmIUYBNKja4
[62] https://www.tunetheweb.com/blog/adding-controls-to-google-tag-manager/
[63] https://schepp.dev/posts/ad-integration-in-2020/
[64] https://jakearchibald.com/2016/caching-best-practices/
[65] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
[66] https://almanac.httparchive.org/en/2019/caching
[67] https://discuss.httparchive.org/t/cache-control-immutable-a-year-later/1195
[68] https://www.fastly.com/blog/stale-while-revalidate-stale-if-error-available-today
[69] https://twitter.com/RyanTownsend/status/1072443651844911104
[70] https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
[71] https://jakearchibald.com/2016/caching-best-practices/
[72] https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en
[73] https://www.smashingmagazine.com/2017/11/understanding-vary-header/
[74] https://www.fastly.com/blog/getting-most-out-vary-fastly
[75] https://httpwg.org/http-extensions/draft-ietf-httpbis-variants.html
[76] https://www.fastly.com/blog/headers-we-dont-want
[77] https://www.fastly.com/blog/headers-we-want
[78] https://medium.com/@ankur_anand/the-terrible-performance-cost-of-cors-api-on-the-single-page-application-spa-6fcf71e50147
WecTeam
WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
