Telerik blogs
Industry NewsT2 Dark_1200x303

In this post, we will create a simple React app that is server-side rendered using Deno.

Over the years, browsers have evolved and are now more powerful. We started to create entire websites and web apps with client-side JavaScript. This is called “Single Page Application.” This leads us to create more interactive real-time updated web applications.

Now the alternative to rendering on the client-side is the use of server-side rendering. In this post, we will take that alternative route to create a simple React app that is server-side rendered using Deno. Before we dive in, let’s talk a bit about server-side rendering.

What is server-side rendering? It is a technique for rendering a normally client-side only Single-Page App (SPA) on the server and then sending a fully rendered page to the browser. Alternatively, in client-side rendering the initial HTML rendered by the server is a placeholder and the entire user interface and data are rendered in the browser once all your scripts load.

Advantages of Server-Side Rendering

  • Performance: In server-side rendering (SSR), the application performance depends on the server’s resources and the user’s network speed. This makes it very useful for content-heavy sites.
  • Search Engine Optimization: Google isn’t the only search engine. If you value SEO, then server-side rendering is your only guaranteed way for crawlers to see the data you want them to.

Disadvantages of Server-Side Rendering

  • Increase in the complexity of the application
  • The server will be busier, causing it to execute fewer requests per second
  • Full page reloads after routes change

Requirement

Getting Started

Create a project directory:

mkdir deno-ssr
cd deno-ssr

Setting up the Dependencies

We need to import our dependencies from their URL, and also export them to be used in their appropriate files. Create the dep.ts file inside the project folder and paste the following code.

touch dep.ts
export { default as React } from "https://dev.jspm.io/react@16.13.1";
export { default as ReactDOMServer } from "https://dev.jspm.io/react-dom@16.13.1/server";
export { opine } from "[https://deno.land/x/opine@0.21.2/mod.ts](https://deno.land/x/opine@0.21.2/mod.ts)";

Note: I used jspm to import React and ReactDOMServer, but you can use any other CDN that provides the same modules.

Now, create the following files inside the project folder.

touch server.tsx
touch app.tsx

Create Your React Component

This is how our app.tsx component will look:

import { React } from "./dep.ts";
// import './style.css'
declare global {
  namespace JSX {
    interface IntrinsicElements {
      button: any;
      div: any;
      h1: any;
      p: any;
    }
  }
}
const App = () => {
  return (
    <div className="app">
      <h1>Hello! i was ready before i got here</h1>
    </div>
  );
}
export default App;

First, we import React. Then we declare some intrinsic elements for TypeScript to use when compiling our App. Lastly, we created a React component called App that uses a hook to change the text.

Note: I’ve cast React as any in this example, but you can equally use fully typed React by importing the types from the DefinitelyTyped GitHub repo or by using the Deno Types hint above any import lines for React. For example:

// @deno-types="https://deno.land/x/types/react/v16.13.1/react.d.ts"
import React from "https://dev.jspm.io/react@16.13.1"

Set up Server

Here’s the code we’ll be using for server.tsx:

import {
  opine,
  React,
  ReactDOMServer,
} from "./dep.ts";

import App from "./app.tsx";

const app = opine();
const browserBundlePath = "/browser.js";

const js =
`import React from "https://dev.jspm.io/react@16.13.1";\nimport ReactDOM from "https://dev.jspm.io/react-dom@16.13.1";\nconst App = ${App};\nReactDOM.hydrate(React.createElement(App), document.body);`;

const html =
`<html><head><script type="module" src="${browserBundlePath}"></script><style>* { font-family: Helvetica; }</style></head><body>${
    (ReactDOMServer as any).renderToString(<App />)
}</body></html>`;

// server our app's code so we can hydrate the React application on the client
app.use(browserBundlePath, (req, res, next) => {
  res.type("application/javascript").send(js);
});

// serve a simple HTML page containing our rendered app
app.use("/", (req, res, next) => {
  res.type("text/html").send(html);
});

app.listen({ port: 3000 });
console.log("App listening on port 3000");

Here’s what is going on: First, we import our main dependencies; we then import the React app we just created.

Note: Unlike Node.js, in Deno file extensions are required, so be careful to include the .tsx extension.

Next, we created an Opine app, much like you would do with Express.js, and define some routes: one to serve a simple HTML page containing our rendered app, and another /browser.js route to serve our app’s code so we can hydrate the React application on the client. Finally, we start the server using the listen() method on port 3000.

Note: Hydration is the entire process of putting functionality back into the HTML that was already rendered in server-side React. So basically it is the process of re-rendering over the once-rendered HTML.

Run the Application

We can now run our React SSR application using the following deno command:

deno run --allow-net --allow-read ./server.tsx

Run Server

Make sure to add the appropriate flags as specified. Any action that needs to access the web, read or write to files, or even consume environment variables needs to have the permission granted before Deno allows it.

Should I use Server-Side Rendering?

If the following are important for your project, then you need to consider using SSR.

  • SEO
  • Social sharing
  • Enough server resources

Conclusion

I hope you enjoyed the brief tutorial illustrated in the post. Keep in mind this is just a basic server and app setup intended to give you a foundational understanding. From here, you can go on to create or port more complex applications.


Chinedu
About the Author

Chinedu Imoh

Chinedu is a tech enthusiast focused on full-stack JavaScript and Infrastructure engineering.

Related Posts

Comments

Comments are disabled in preview mode.