Static Hoisting
@QiWenWang1|May 2, 2020 (over 6 years ago)|3 min read
Since I published my 2019 in Review, detailing the industry trend towards static hosting and the rise of Jamstack CDNs like Vercel, a question has persistently come up: how is this different from a server and a traditional CDN on top (opens in a new tab)? Why not then just use servers with containers (even serverless ones)?
The answer boils down to our ability to not just host static assets and cache them, but also hoist them.
#An Intro to Hoisting
The word hoisting is used quite frequently in JavaScript to describe how the compiler extracts and "moves" declarations (opens in a new tab) to the "top" of a scope, which makes the following code actually work:
function a () { return b() // this works with no errors! function b() { return "hello world" }}The term is also used in compiler optimization lingo (opens in a new tab) to describe a class of optimization where the code is analyzed, and parts that look "static" or invariant are moved (hoisted) outside of loops.
function a (b, c) { let sum = [] for (let i = 0; i < 100000; i++) { sum[i] = i + /* hoist ↗ */ (b + c) /* hoist ↗ */ }}a(314, 159)Notice that the sum b + c has nothing to do with the context of the loop: it's loop-invariant (opens in a new tab). An optimizing compiler can recognize it, and hoist it automatically so that the computation behaves as if you had written it outside of the loop yourself.
#Hoisting to the Edge
Hoisting computation within a program is great, and odds are the compilers and VMs you use every day have plenty of optimizations like it.
What Jamstack as a software architecture has now made possible, however, is to hoisting the results of computation to the edge, right next to where your visitors are.
A core tenet of Jamstack has been to pre-render (pre-compute) as much as possible, which has given prominence to static site generation. The key idea is that computation that would have happened later on, in the request's timeline, has now been shifted to the build phase, performed once and made available for all users to share.
#Edge-aware Frameworks
Since Next.js 9 (opens in a new tab), the next build process has started automatically outputting the optimal asset on a per-page
Since Next.js 9 (opens in a new tab), the next build process has started automatically outputting the optimal asset on a per-page (entrypoint) basis. Futher, with Next.js 9.3 (opens in a new tab) the hooks for static-site generation were refined, and incremental static generation (opens in a new tab) was introduced for appending (opens in a new tab) and updating (opens in a new tab) pages.
Next.js makes hoisting the static parts of your site or app to the edge a breeze. Let's look at the build output of a complex site (vercel.com (opens in a new tab)) as an example:
$ next build Page Size First Load JS ┌ ○ / 215 B 191 kB ├ ○ /about 4.53 kB 171 kB ├ λ /api/sso ├ ○ /dashboard 228 B 192 kB ├ ○ /bitbucket 11 kB 164 kB ├ ● /blog 54.6 kB 224 kB ├ └ css/a73431369cd0a9ce449f.css 960 B ├ ● /blog/[post] 3.54 kB 206 kB ├ ├ /blog/environment-variables-ui ├ ├ /blog/simpler-pricing ├ ├ /blog/canceling-ongoing-deployments └ └ [+95 more paths]λ (Lambda) server-side renders at runtime (uses getInitialProps or getServerSideProps)○ (Static) automatically rendered as static HTML (uses no initial props)● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)As you can see from the symbols (○ ● λ), which represent the output types:
- We build the homepage statically. Our company's homepage, our "cover letter", gets built as
index.htmland pushed to the edge for maximum speed and reliability. - The
/apifunctions are exported as serverless (lambda) functions. These are created by placing files inside./pages/api(more) (opens in a new tab). - At build time, we create blog posts by querying an API using Static Site Generation (opens in a new tab) hooks. Blog posts, like our homepage, are thus statically hoisted (optimized) to the edge network.
- Our dashboard (opens in a new tab), despite being super dynamic in nature, is a static HTML page that queries data securely using React Hooks (opens in a new tab) from the client side.
#Conclusion
CDNs are great and have been around for a long time, and so have static hosts. However, for the longest time, CDNs have been treating the "origin" as an opaque black box.
It's now possible, instead, to push content directly to the network and design frameworks that optimize for this capability. As a result, with optimizations like static asset hoisting, websites are now becoming faster and more reliable than ever before.
To start developing a Jamstack site or app, check out Next.js (opens in a new tab) which you can deploy to the Vercel (opens in a new tab) edge network with a couple clicks.
Related writing
Measure the User Journey, Not Just the Server
A service can be healthy while a reader is still unable to complete the task that brought them to the site.
Frontend · Web Performance
Making the Web. Faster
Our vision of the Web is a global realtime medium for both creators and consumers, where all friction and latency are eliminated
Web Performance · Frontend
7 Principles of Rich Web Applications
7 actionable principles for websites that want to make use of JavaScript to control their UI and deliver the best performance
Frontend · Web Performance