Lazy Loading Principles
Recently working on web frontend performance optimization - bundle size reduction. Today’s frameworks have maturely encapsulated functionality, seemingly allowing foolish usage. But knowing only the surface causes problems when any issue arises - you can only wait helplessly for so-called upgrades and seek help in forums, which is pitiful.
Therefore, here’s a simple overview of lazy loading.
Implementation Principles
Whether it’s React.lazyLoad or Angular’s loadChildren, they all use dynamic imports import() in usage
The reason TS allows this syntax is TypeScript support; the reason JS allows this is webpack support. Of course, after TS compilation, it’s still JS that continues webpack bundling.
The final result of import() is:
- The imported resource becomes a separate file, so the bundle size is removed from the original main bundle
- The main file executing import gains additional code that, when import is triggered, dynamically creates script tags to request chunk JS resources.
Yes, it’s that simple.
Worth Noting
- TypeScript
2.4
added dynamic import import() expression support. Current TypeScript version is already3.9
, so you can use it with confidence - Webpack supports not only
import()
for code splitting, but alsorequire.ensure
, which is webpack-specific. Of course, ESModule is the standard, so maintaining one habit is better - ES import() is currently only a proposal and not yet an official standard, so even when compiling and bundling ES6, import() won’t exist
Extension
The above uses script tag creation, but we could also use XHR async requests then eval execution. Below is an example, but note that XHR has cross-origin issues.
function xhrLoad(e) {
const xhr = new XMLHttpRequest();
xhr.open('GET', './xhr-content.js', true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
eval(xhr.responseText);
}
}
}