Components: Server-Side vs. Client-Side

Building a website in 2021? I’m guessing you’re going to take a component-driven approach. It’s all the chatter these days. React and Vue are everywhere (is Angular still a thing?), while other emerging frameworks continue to attempt a push into the spotlight.

Over the last decade or so we’ve seen an explosion of frameworks and tools that help us build sites systematically using components. Early frameworks like AngularJS helped shape the generic concept of web components. Web components are also reusable bits of HTML code that are written in JavaScript and made functional by the browser. They are client-side components.

But components, in a more generic sense, have actually been around much longer. In fact, they go back to the early days of the web. They just haven’t typically been called components, though they still function as such. Server components are also reusable bits of code, but are compiled into HTML before the browser sees them. They are server-side components, and they are still very much a thing today.

Even in a world in which all it seems like we hear is “React, React, React,” both types of components are still relevant and can help us build super awesome websites. Let’s explore how client and server components differ from one another. That will give us a clearer picture of where we came from. And then we’ll have the information we need to dream about the future.

Rendering

Perhaps the biggest difference between client-side and server-side components is what makes them what they are. That is the thing that is responsible for rendering them.

Server components are rendered by — you guessed it! — the server. They aren’t typically referred to as components. They’re often called partials, includes, snippets, or templates, depending on the framework in which they are used.

Server components can take two flavors. The first is the classic approach, which is to render components in real-time based on a request from the client. See here:

Illustrated diagram of a browser making a request to an app server that requests components, which compile to a page and are returned to the app server to go back to the browser.
Server-side rendered components

The second flavor is the Jamstack approach. In this case, the entire site is compiled during a build a process, and static HTML is already available when requested by the client. See here:

An illustrated diagram showing the browser requests a page that has already been created, which consists of components that have gone through a build process from the server, then returns to the browser.
Server components on a Jamstack site have already been compiled into HTML.

In both cases, the client (i.e. your browser) never sees the distinction between your components. It simply receives a bunch of HTML from the server.

Client components, on the other hand, are rendered by — you are two-for-two and on a ROLL! — the client. They are written in JavaScript and rendered by the client (your browser). Because the server is the server and it knows all, it can know about your client components, but whether it cares enough to do anything with them depends on the framework you’re using.

Like server components, there are also two flavors of client components. The first is the more official web component, which makes use of the shadow DOM. The shadow DOM helps with encapsulating styles and other functionality (we’ll talk more about this later). Frameworks like Polymer and Stencil make use of the shadow DOM.

The more popular frameworks, like React and Vue, represent the second flavor of component, which handles DOM manipulation and scoping on their own.

Interactivity

Because server components are just HTML when they are sent to the client, if they are to be interactive on the front end, the application must load JavaScript code separately.

Consider a countdown timer. Its presentation is determined by HTML and CSS (we‘ll come back to the CSS part). But if it is to do its thing (count), it also needs some JavaScript. That means not just bringing in that JavaScript, but also having a means by which the JavaScript can attach itself to the countdown’s HTML element(s), which must either be done manually or with (yet) another framework.

An illustrated diagram showing the browser requesting both a JavaScript bundler containing the JavaScript for the component, and a page with the component's markup that both are returned to the browser.
A component’s HTML and JavaScript are separated in SSR components.

Though this may feel unnecessarily tedious (especially if you’ve been around long enough to have been forced into this approach), there are benefits to it. It is a clear separation of concerns, where server-side code lives in one place, while the functionality lives in another. And it brings only the code it needs for the interactivity (theoretically), which can lessen the burden on the browser.

With client components, the markup and interactivity tend to be tightly coupled, often in the same file or directory. While this can quickly become a mess if you’re not diligent about staying organized, one major benefit to client components is that they already have access to the client. And because they are written in JavaScript, their functionality can ship right alongside their markup (and styles).

A diagram showing the same flow as before, but both the component markup and JavaScript are included in the bundler, which then renders on the page.
Client-side components are all wrapped up in JavaScript code.

Performance

In a one-to-one comparison, server-side components tend to perform better. When the page that a browser receives contains everything it needs for presentation, it’s going to be able to deliver that presentation to the user much quicker.

Diagram showing the browser asking for a page of HTML in a single request.
Technically all you need when rendering SSR components is a single request.

Because client-side components require JavaScript, the browser must download or process additional information (often in separate files) to be able to render the component.

Same diagram as before, but a bundler is requested by the browser along with the page.
Client component often require more code and requests.

That said, client-side components are often used within the context of a larger framework. React has Gatsby and Next, while Vue has Nuxt. These frameworks have mechanisms for creating a superior in-app experience. What I mean is that, while they may be slower to load the first page you visit on a site, they can then focus their energy on delivering subsequent views extremely fast — often faster than a server-side rendered site can deliver its content.

If you’re thinking, Yeah but what about pre-rendering and…

Yes, you’re right. We’ll get there. Also, no more spoilers, please. The rest of us are along for the ride.

Languages

Server components can be written in (almost) any server-side language. This enables you to write your templates in the same language as your application’s logic. For example, applications written with Ruby on Rails use ERB templating by default, which is a form of Ruby. Thus, Rails apps use the same language for the application itself as it does for its components.

The reason client components are written in JavaScript is because that’s the language browsers parse for interactivity on a website. However, JavaScript also has server-based runtimes, the most popular of which is Node.js. That means code for client components could be written in the same language as the application, as long as the application is written with Node (or similar).

Styling (CSS)

When it comes to styling components, server-side components run into the same trouble they face with JavaScript. The styles are typically detached from the components, and require a bit of extra effort to tie styles to the elements on the page.

However, there are frameworks like Tailwind CSS that are working to make this process less painful.

Many client-side component libraries come with CSS support (or at least a pattern for styling) right out of the box. That often means including the styles in the same file as the markup and logic, which can get messy. But typically, with a little effort, you can adjust that approach to your liking.

Welcome to the (hybrid) future

Neither type of component is the answer by itself. Server-side components require additional effort in styling and interactivity that feels unnecessary when we look at the offerings of client components. But then client components have a tendency to take away from performance on the front end. And because the success of a website often depends on user engagement, a lack of performance can hurt the end result and be enough not to want to use client components.

What does that mean for a future that demands both performance and a good developer experience? More than likely, a hybrid approach.

Components are going to have to be rendered on the server side. They just are. That‘s how we optimize performance, and good performance is going to continue to be an attribute of successful websites. But, now that we’ve seen the ease of front-end logic and interactivity using frameworks, again, like React and Vue, those frameworks are here to stay (at least for awhile).

So where are we going?

I think we’re going to see these components come together in three ways in the very near future.

1. Advancement of JavaScript framework frameworks

Remember when you thought up that spoiler about pre-rendering? Well, let’s talk about it now.

Frameworks like Gatsby, Next, and Nuxt act as front-end engines built on top of component frameworks, like React and Vue. They bring together tooling to build a comprehensive front-end experience using their preferred framework. One such feature is pre-rendering, which means these engines will introspect components and then write static HTML on the page while the site is being built. Then, when users view that page, it‘s actually already there. They don’t need JavaScript to view it.

However, JavaScript comes into play through a process called hydration. After the page loads and your user sees all the (static) content, that’s when JavaScript goes to work. It takes over the components to make them interactive. This provides the opportunity to build a client-side, component-based website with some of the benefits of the server, namely performance and SEO.

These tools have gotten super popular because of this approach, and I suspect we’ll see them continue to advance.

2. Baked-in client-side pre-rendering

That’s a lot of compound words.

What I‘ve been thinking about a lot the last couple years is: Why doesn’t React (or Vue) take on server-side rendering? They do, it’s just not super easy to understand or implement without another framework to help.

On one hand, I understand the single-responsibility principle, and that these component frameworks are just ways to build client-side components. But it felt like a huge miss to delegate server-side rendering to bigger, more complex tools like Gatsby and Next (among others).

Well, React has started moving that way. Vue is already there. And Svelte has made this approach a priority from the beginning.

I think we‘re going to see a lot more development while these traditionally client-side-focused tools solve for server-side rendering. I suspect that also means we‘ll hear a little more from Svelte in the future, which seems like it’s ahead of the game in this regard.

That may also lead to the development of more competitors to bulkier tools like Gatsby and Next. For example, look at what Netlify is doing with their website. It‘s an Eleventy project that pulls in Vue components and renders them for use on the server. What it’s missing is the hydration and interactivity piece. I expect that to come together in the very near future.

3. Server-side component interactivity

And still, we can‘t discount the continued use of server-side components. The one side effect of both of the other two advancements is that they’re still using JavaScript frameworks that can feel unnecessary when you only need just a little interactivity.

There must be a simpler way to add just a little JavaScript to make a server-side component that are written in a server-side language more interactive.

Solving that problem seems to be the approach from the folks at Basecamp, who just released Hotwire, which is a means to bring some of the gains of client components to the server, using (almost) any server-side language.

I don‘t know if that means we‘re going to see competition to Hotwire emerge right away. But I do think Hotwire is going to get some attention. And that might just bring folks back to working with full-stack monolithic frameworks like Rails. (Personally, I love that Rails hasn’t become obsolete in this JavaScript-focused world. The more competition we have, the better the web gets.)

Where do you think all this component business is going? Let’s talk about it.


The post Components: Server-Side vs. Client-Side appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Rendering Spectrum

Here are the big categories of rendering websites:

  • Client: ship a <div id="root"></div> and let a JavaScript template render all of it.
  • Static: pre-render the HTML.
  • Server: let a live server process requests and generate the HTML response.

They are not mutually exclusive.

  • A website could statically pre-render 75% of it’s pages (say, blog posts), but the other 25% have a server respond to (say, forums).
  • A website could statically pre-render all the pages, but have a couple of empty <div>s in there that have client-side rendered content in them (e.g. a dynamically generated menu based on the logged-in user).
  • A website could be primarily server-rendered, but has caching in front of it such that it behaves statically.
  • A website could render statically, but then “hydrate” itself into an entirely client-rendered site.
  • A website could be a mix of server and static rendering, but have dynamic parts similar to client-side rendering, but actually happen in an edge function, so it ends up more like server-side rendering.

Next.js is interesting in that it can do all three. Here’s Tim Neutkens in a recent interview:

Next.js allows you to pre-render pages. It creates HTML on a server at build time with static site generation or uses run-time rendering on the server side. Next allows you to do a hybrid of those. Unlike most other frameworks, you are not bound by, oh, I’m going to build my app completely statically generated. Instead, you’re allowed to have some pages be server-side rendered and some pages be statically generated.

In the new release we make it possible to update these statically generated pages without having to run a new build, rebuilding your whole app.

Cool. Love to see that happening at the framework level. Seems like having to go all-in on one rendering style isn’t practical for a lot of sites.

Client rendering is the most flexible, but comes with all these serious downsides like worse performance, worse reliability, more strain on devices, bad SEO, etc. Static pre-rendering is the most robust, speedy, and secure, but is the most limited. Edge functions on top of static is starting to open doors, but server-rendering is the classic mix of flexibility and speed that has dominated the web for good reason.

Client rendering also opens the door for that “SPA” (Single Page App) feel. I still like that, personally. I like the no-page-refresh feel. It’s makes a site feel snappy and opens the door for page transitions. Gatsby is famous for popularizing hydration, where you get the pre-rendered static bonus, but then the upgrade into SPA as the JavaScript downloads.

I’d love to see the web get to the point where we get all that “good feel” bonus of an SPA without actually having to build an SPA. It’s notable when frameworks provide SPA feels without having to manage much of that yourself, but still, something is managing it and that something is a bunch of JavaScript.

Tom MacWright wrote about that recently in his “If not SPAs, What?” post. Some of today’s alternatives:

Turbolinks … what is the bare minimum you need to do to get the SPA experience without any cooperation from your application?

Turbolinks is like… click link, click is intercepted, Ajax request for new page is made, JavaScript flops out the content on the page with the new content. Super easy to implement, but it’s still JavaScript, and not particularly intelligent about sending less data across the wire.

barba.js and instant.page are alternative approaches to the same sort of problem.

Barba is all about getting page transitions going (more detail on that concept). instant.page is all about pre-loading/rendering pages right before you click then, so even though you get a page refresh, it feels less intrusive (particularly with paint holding). Both are cool, but not quite one-to-one replacements for an SPA. (Even with paint holding, pre-rendering, and lightweight pages, I still don’t think the experience is quite a smooth as an SPA. For example, you still get the page loading spinner.)

So… is the anything else cooking? Kinda. There is <portal>. Possibly too simplified, but here goes: portals are like iframes. They can even be visually displayed just like an iframe. That means the rendering of the URL in the portal is already done. Then you can “promote” the portal to be the active page, and even animate the portal itself while doing so.

I don’t hate it. I can imagine someone building a turbolinks-like library on portals so they are “easy to use” and make a site more SPA-like.

Still, animating a rectangle into position isn’t often what is desired from animated page transitions. Just look at Sarah’s “Native-Like Animations for Page Transitions on the Web” article. That’s what the people want (at least the possibility of it). That’s why Jeremy said not portals the other day when he cheekily said that “[m]ost single page apps are just giant carousels.” He also points to Jake’s navigation-transitions proposal from a few years back.

I love this proposal. It focuses on user needs. It also asks why people reach for JavaScript frameworks instead of using what browsers provide. People reach for JavaScript frameworks because browsers don’t yet provide some functionality: components like tabs or accordions; DOM diffing; control over styling complex form elements; navigation transitions. The problems that JavaScript frameworks are solving today should be seen as the R&D departments for web standards of tomorrow. (And conversely, I strongly believe that the aim of any good JavaScript framework should be to make itself redundant.)

So what’s the best rendering method? Whatever works best for you, but perhaps a hierarchy like this makes some general sense:

  1. Static HTML as much as you can
  2. Edge functions over static HTML so you can do whatever dynamic things
  3. Server generated HTML what you have to after that
  4. Client-side render only what you absolutely have to

The post Rendering Spectrum appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Deploying a Client-Side Rendered create-react-app to Microsoft Azure

Deploying a React app to Microsoft Azure is simple. Except that... it isn’t. The devil is in the details. If you're looking to deploy a create-react-app — or a similar style front-end JavaScript framework that requires pushState-based routing — to Microsoft Azure, I believe this article will serve you well. We’re going to try to avoid the headaches of client and server side routing reconciliation.

First, a quick story.

Back in 2016, when Donovan Brown, a Senior DevOps Program Manager at Microsoft, had given a "but it works on my machine speech" at Microsoft Connect that year, I was still in my preliminary stages as a web developer. His talk was about micro-services and containers.

[...] Gone are the days when your manager comes running into your office and she is frantic and she has found a bug. And no matter how hard I try, I can't reproduce it and it works perfectly on my machine. She says: fine Donovan, then we are going to ship your machine because that is the only place where it works. But I like my machine, so I'm not going to let her ship it...

I had a similar sort of challenge, but it had to do with routing. I was working on a website with a React front end and ASP.NET Core back end, hosted as two separate projects that were deployed to Microsoft Azure. This meant we could deploy both apps separately and enjoy the benefits that comes with separation of concern. We also know who to git blame if and when something goes wrong. But it had downsides as well, as front-end vs. back-end routing reconciliation was one of those downsides.

One day I pushed some new code to our staging servers. I received a message shortly after telling me the website was failing on page refresh. It was throwing a 404 error. At first, I didn’t think it was my responsibility to fix the error. It had to be some server configuration issue. Turns out I was both right and wrong.

I was right to know it was a server configuration issue (though at the time, I didn’t know it had to do with routing). I was wrong to deny it my responsibility. It was only after I went on a web searching rampage that I found a use case for deploying a create-react-app to Azure under the Deployment tab on the official documentation page.

Building React for production

When building a React app for production (assuming we’re are using create-react-app), it’s worth noting the folders that get generated. Running npm run build will generate a build folder where an optimized static version of the application lives. To get the application on a live server, all we need do is feed the server the content of the build folder. If we were working on localhost, there is no live server involved, so it is not always equivalent to having the application on a live server.

Generally, the build folder will have this structure:

→ build
  → static
    → css
      → css files
    → js
      → js files
    → media
      → media files
  → index.html
  → other files...

Client-side routing with React Router

React Router uses the HTML5 pushState history API internally. What pushState does is quite interesting. For example, navigating (or using Link in react router) from the page https://css-tricks.com to the page https://css-tricks.com/archives/ will cause the URL bar to display https://css-tricks.com/archives/ but won't cause the browser to load the page /archives or even check that it exists. Couple this with the component-based model of React, it becomes a thing to change routes while displaying different pages based on those routes — without the all-seeing eye of the server trying to serve a page in its own directory. What happens, then, when we introduce servers by pushing the code to a live server? The docs tell it better:

If you use routers that use the HTML5 pushState history API under the hood (for example, React Router with browserHistory), many static file servers will fail. For example, if you used React Router with a route for /todos/42, the development server will respond to localhost:3000/todos/42 properly, but an Express serving a production build as above will not. This is because when there is a fresh page load for a /todos/42, the server looks for the file build/todos/42 and does not find it. The server needs to be configured to respond to a request to /todos/42 by serving index.html.

Different servers require different configuration. Express, for example, requires this:

app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});

...as documented in the create-react-app docs. Keep in mind though, this assumes that we’re hosting create-react-app at the server root, which is making use of a wildcard route (*) that catches all route and respond to all route request by serving the index.html file in the build folder which sits at the root of the server application. Also, this is tightly coupled with the back-end. If that’s the case, we would most likely have this kind of folder structure (assuming the back-end is in NodeJS):

→ Server
  → Client (this is where your react code goes)
    → build (this is the build folder, after you npm run build)
    → src
    → node_modules
    → package.json
    → other front-end files and folders
  → Other back-end files and folders

Since my front-end (create-react-app) and back-end (ASP.NET) were two different projects, serving static files by navigating the directory was sort of an impossibility.

In fact, since we are deploying a static app, we do not need the back-end. As Burke Holland put it: "Static" means that we aren’t deploying any server code; just the front-end files.

I keep mentioning ASP.NET here because during the course of my research, I figured configuring Azure required a configuration file in a wwwroot folder and ASP.NET's folder structure typically has a wwwroot folder. Remember the application’s back-end was in ASP.NET? But that’s just about it. The wwwroot folder seemed to be hidden somewhere on Azure. And I can’t show you without deploying a create-react-app. So let’s go do that.

Getting started with App Services on Microsoft Azure

To get started, if you do not already have a Azure account, get a free trial then head over to the Azure portal.

  1. Navigate to All servicesWebApp Services
    Navigating on the Azure portal from All services, to Web, to App services

  2. We want to add a new app, give it a name, subscription (should be free if you’re on a free trial, or if you already have one), resource group (create one or use existing), then click on the Create button down at the bottom of the panel.
    Creating a new App service on the Azure portal.
  3. We should get a notification that the resource has been created. But it won’t immediately show up, so hit "Refresh" — I have other resources, but the AzureReactDemo2 is what I’m using here. You’ll click on the name of your newly created app, which is AzureReactDemo2 in my case.
    Displaying all App Services on the Azure portal.
  4. The blade shows you information about your app, the navigation to the left has everything you need to manage your application (overview, activity log, deployment center...).

For example, the Deployment Center is where the app deployment is managed, Slots is where things like staging, production, test are managed. Configuration is where things like environmental variables, node versions and — an important one — Kudu are managed.

The overview screen shows a general view of the application Status, URL... Click on the URL to see the live site.

Showing the various parts of an App Service on the Azure CLI.

The app is up and running!

Showing the default live page of an App Service.

What we’ve done is create a new App Service, but we have none of our code on Azure yet. As said earlier, all we need to do is to feed Azure the content of the build folder generated by building React for production, but we don’t have one yet. So let’s go local and get some React app.

Going local

We need to create a new React app, and install react-router as a dependency.

npx create-react-app azure-react-demo
cd azure-react-demo

We also want to install react-router (react-router-dom, actually)

npm i react-router-dom

All things being equal, starting the app with npm start, we should get the default page.

Showing the default page generated by React.

Because this will be about testing routes, I needed to make some pages. I’ve modified my local version and uploaded it to GitHub. I’m banking on the fact that you can find your way around react and react-router. Download a demo.

My folder looks like this:

Showing the folders and files in the modified create-react-app app.

The changed files have the following code:

// App.js
import React, { Component } from "react";
import "./App.css";
import Home from "./pages/Home";
import Page1 from "./pages/Page1";
import Page2 from "./pages/Page2";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/page1" component={Page1} />
          <Route path="/page2" component={Page2} />
        </Switch>
      </Router>
    );
  }
}

export default App;
// Page1.js
import React from "react";
import { Link } from "react-router-dom";

const Page1 = () => {
  return (
    <div className="page page1">
      <div className="flagTop" />
      <div className="flagCenter">
        <h1 className="country">Argentina (PAGE 1)</h1>
        <div className="otherLinks">
          <Link to="/page2">Nigeria</Link>
          <Link to="/">Home</Link>
        </div>
      </div>
      <div className="flagBottom" />
    </div>
  );
};

export default Page1;
// Page2.js
import React from "react";
import { Link } from "react-router-dom";

const Page2 = () => {
  return (
    <div className="page page2">
      <div className="flagTop" />
      <div className="flagCenter">
        <h1 className="country">Nigeria (PAGE 2)</h1>
        <div className="otherLinks">
          <Link to="/page1">Argentina</Link>
          <Link to="/">Home</Link>
        </div>
      </div>
      <div className="flagBottom" />
    </div>
  );
};

export default Page2;
/* App.css */
html {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  height: 100vh;
}

.page1 .flagTop,
.page1 .flagBottom {
  background-color: blue;
}

.page2 .flagTop,
.page2 .flagBottom {
  background-color: green;
}

.flagCenter {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}

.page a {
  border: 2px solid currentColor;
  font-weight: bold;
  margin: 0 30px;
  padding: 5px;
  text-decoration: none;
  text-transform: uppercase;
}

.flags {
  display: flex;
  width: 100%;
}

.flags > .page {
  flex: 1;
}

Running the app works locally, so the routes deliver when links are clicked and even when the page is refreshed.

Deploy the app to Azure

Now, let’s get it up on Azure! There are a few steps to make this happen.

Step 1: Head to the Deployment Center

On Azure, we need to go to the Deployment Center. There are quite a few options each with its pros and cons. We’ll be using Local Git (which means your local git app straight directly to Azure) for source control, Kudu for Build Provider.

Remember to click continue or finish when you select an option, or else, the portal will just keep staring at you.

Showing Deployment Center on the Azure portal and choosing a source control as the first step in deploying a new App Service.
Showing the Build Provider section in the Deployment Center on Azure portal.

After the third step, Azure generates a local git repo for you. And it gives you a remote link to point your react app to.

One thing to note at this point. When you push, Azure will ask for your GitHub credentials. It is under the deployment tab. There are two: App and User. App credential will be specific to an app. User will be general to all the apps you as a user has Read/Write access to. You can do without User Credentials and use App credentials, but I find that after a while, Azure stops asking for credentials and just tells me authentication failed automatically. I set a custom User Credentials. Either way, you should get past that.

Showing the Deployment Credentials for the App Service on Azure portal.

In the React app, after modification, we need to build for production. This is important because what we want to upload is the content of the build folder.

We need to tell Kudu what node engine we’ll be using, or else, the build will most likely fail,
due to the reported fact that react-scripts requires a node version higher than the default set on Azure. There are other ways to do that, but the simplest is to add a nodes engine in package.json. I’m using version 10.0 here. Unfortunately, we can’t just add what we like, since Azure has Node versions it supports and the rest are unsupported. Check that with the CLI with the command: az webapp list-runtimes

Add the preferred node version to the package.json file, as in:

"engines": {
  "node": "10.0"
}
Displaying a list of Azure runtimes in the Azure CLI.

Step 2: Build the App

To build the React app, let’s run npm build in the Terminal.

Step 3: Initialize the Git repo

Navigate into the build folder and initialize a Git repo in there. The URL to clone the repo is in the overview page. Depending on what credentials you’re using (App or User), it will be slightly different.

Showing the overview of the App Service on Azure and the Git clone URL.
git init
git add .
git commit -m "Initial Commit"
git remote add azure <git clone url>
git push azure master

Now, visit the live app by using the URL on the overview page. As you can see, the app fails on /page2 refresh. Looking at the network tab, a 404 is thrown because the page tried to be fetched from the server — with client-side routing, as we have already set up, the page shouldn’t even be server fetched at all.

Showing the failed page request and the network tab to verify.

Configuring Azure to reconcile client and server side routing

In the public folder, let’s add a web.config XML file with the following content:

<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

I’ve intentionally decided to not format the code snippet because XML is strict about that. If you miss the formatting, the file has no effect. You can download an XML formatter for your text editor. For VSCode, that would be the XML Tools plugin.

Showing an XML formatter and an XML formatted file in VSCode.

The app can be built again at this point, although we’ll lose the Git info in the build folder since the new build overrides the old build. That means it would have to be added again, then pushed.

Now the app works as shown below! Whew.

We don’t want to have to npm run build every time — that’s where continuous deployment comes in. Check out the link below for appropriate references.

Conclusion

There is a lot to Azure, as it can do a lot for you. That’s nice because there are times when you need it to do something that seems super specific — as we’ve seen here with client and server side routing reconciliation — and it already has your back.

That said, I’ll leave you with a couple of related resources you can turn to as you look to deploying a React app to Azure.

The post Deploying a Client-Side Rendered create-react-app to Microsoft Azure appeared first on CSS-Tricks.

The Client/Server Rendering Spectrum

I've definitely been guilty of thinking about rendering on the web as a two-horse race. There is Server-Side Rendering (SSR, like this WordPress site is doing) and Client-Side Rendering (CSR, like a typical React app). Both are full of advantages and disadvantages. But, of course, the conversation is more nuanced. Just because an app is SSR doesn't mean it doesn't do dynamic JavaScript-powered things. And just because an app is CSR doesn't mean it can't leverage any SSR at all.

It's a spectrum! Jason Miller and Addy Osmani paint that picture nicely in Rendering on the Web.

My favorite part of the article is the infographic table they post at the end of it. Unfortunately, it's a PNG. So I took a few minutes and <table>-ized it, in case that's useful to anyone.

See the Pen
The Client/Server Rendering Spectrum
by Chris Coyier (@chriscoyier)
on CodePen.

Direct Link to ArticlePermalink

The post The Client/Server Rendering Spectrum appeared first on CSS-Tricks.