This blog post was originally written for and posted on Rangle’s blog. You can find a link to the original here.
Web applications have been evolving dramatically in recent years and many techniques have evolved to help our applications run faster, respond quickly, and load easily. With a wide array of modern development techniques it’s easy to overlook all of the options. Server-side Rendering web apps is one such option that has really impressive benefits when implemented in our applications.
Server-side rendering is the process of both building and serving an application from the server when a user requests a page. This built application, in terms of web apps, is often a HTML page that can quickly be parsed by the user’s browser in order to render the application. The server “rendering” is preparing that view for the user to render, not actually rendering the page on a browser running on the server.
This type of rendering has been popular over the last several decades as an easy way to populate pages of data in one trip to the server. Many developers could write these pages in JSP or other languages that felt familiar without having to dabble in JavaScript. However, when developers began working with larger frontends it became easier to just decouple the frontend code from the server application. Now we’re seeing the resurgence of server side rendering in the form of universal applications as state management, SEO, and performance needs continue to drive application design.
How Does it Work
When the server receives a request from a user requesting an application the intent is to quickly return the everything for the user to display the page requested. The code to interact with the application comes in as the last part of the request string establishing a clear order to how the application will render at the destination. First the viewable application will be rendered with just the critical CSS and HTML required to render the first view the user will see. Next, while the DOM is being rendered, the JavaScript will be parsed and initialized. Finally, when the application JavaScript has been fully loaded, the app will hydrate and the user will be able to interact with the full application.
This pipeline makes several compromises on the goals of delivering the application to the client. Since the application view is rendered in a specific order, the developer has to think about how the application will be consumed by the end user. Without forethought, the user can have an experience where they see the application fully rendered but are unable to interact with the application. The render “flicker” that modern applications have upon bootstrapping the root application tag is eliminated by this approach to rendering, but the lack of interactivity can still be frustrating for a user.
An added benefit can come with the ability to SEO for bots crawling pages. Because the application doesn’t need to be rendered on the client side, bots easily have access to all of the rendered data offered by the page without waiting or just skipping over the application entirely. Just keep in mind that servers are going to be building the application for each request which isn’t free. Caching app renders can be done intelligently and dynamically with server side rendering which can help eliminate the overhead of serving the application in these cases.
Web Applications are driven by data. Server side rendered applications can have pretty incredible request times by sending initialization values along with the application. The server often has some of these data points stored locally in caches or in static variables which makes the request time extremely fast. Some implementations can even go out to the database on request and access data without the round trip the client would have to make to request this data.
These data driven applications have also begun to use Redux state management techniques. Populating the initial state can easily be passed along with the initial page payload from the server and these values can even be initialized ahead of time on the server. This means that the end user’s application can have a dynamic, user-specific state delivered at request time.
When Should I Use It?
Server rendering an application, although providing several benefits, is sort of a mixed bag. While it allows developers to really streamline how their users receive data, it may not be the best bet for all applications. Developers interested in taking advantage of the benefits should deeply research just how much development time and production cost they’re going to incur for pursuing these advantages. Here’s a short list of some that stand out:
Use
- Fast initial page load especially on slower networks
- Improved SEO across all search engines
- Initialized data at render time
- User requesting can get unique page
- Users with javascript disabled can still see the application
Don’t Use
- Initial page load not most important
- Don’t have ability to spin up and maintain servers
- Static site meets the business need
- Framework in use doesn’t support server side rendering
Where Can I Use It?
Most major frontend frameworks provide a way to develop universal applications for developers seeking this specific path for performance. I encourage contrasting and comparing these solutions and taking a longer look at what problem each framework is prioritizing with their offering. Happy rendering!
React
React keeps it’s consistent and lightweight approach to developing serverless applications by providing an html render method for easily rendering the root application as a string for rendering.
import App from ‘./App’
const renderApp = () => {
const html = renderToString(
React.createFactory(App)({ welcome: 'Hello' })
)
return `
<!DOCTYPE html>
<html>
<head>
<title>Server side rendered app</title>
</head>
<body>${html}</body>
</html>
`
}
In practice, you might want to use
renderToNodeStream
instead ofrenderToString
so as not to block the server while the main application is running.
Furthermore, if Redux is your state management architecture of choice, then look to the docs for a look at integrating Redux into your React application.
Electrode
A full fledged application framework complete with tooling aimed at delivering server rendered applications can be found in WalmartLabs’s Electrode framework. It provides builds for setting up Progressive Web Applications, a focus on performance, as well as integrations for Redux state management. Applications already thinking about a React and NodeJS stack should really consider this offering.
Angular Universal
Still somewhat in progress, Angular Universal is the Angular solution for delivering server rendered universal applications. It targets a larger audience of developers working with either .NET Core and NodeJS backends with more to come in the future. Keep an eye on this project for developing Angular server rendered applications.
Nuxt.js
Vue is really carving out an ever growing market share of the frontend development space with its accessible and highly extendable framework. Nuxt.js is a framework built for Vue applications that provides functionality for developing server-side rendered applications. Showing of its own extensibility it also allows developers to disable the default Single Page Application mode and even generate static pages for serving simply on a CDN. That sort of flexibility is extremely rare and allows developers to really adapt to changes in application development.