DEV Community

loading...

React SSR in Deno: The Simple Way

ynwd profile image ynwd Updated on ・3 min read

No need babel and webpack anymore. With minimum setup, you can get started coding right away.

Install fastro command line interface (cli):

deno install -A https://deno.land/x/fastro@v0.30.45/cli/fastro.ts
Enter fullscreen mode Exit fullscreen mode

Create webapp folder, generate initial folders and files:

mkdir webapp && cd webapp && fastro init
Enter fullscreen mode Exit fullscreen mode

It will create folders and files like this:

.
├── app.yaml
├── container.ts
├── deps.ts
├── Dockerfile
├── main.ts
├── middleware
│   └── support.ts
├── module
│   ├── hello.controller.ts
│   ├── hello.template.html
│   ├── react.page.tsx
│   └── react.template.html
├── public
│   ├── favicon.ico
│   └── index.html
└── readme.md

3 directories, 13 files
Enter fullscreen mode Exit fullscreen mode

Open module/react.page.tsx:

  • You can change the react template and the html title with your own via options
  • You can define react props via props
import { Container } from "../container.ts";
import { React, Request } from "../deps.ts";

export const options = {
  // Define custom html template
  template: "react.template.html",
  // Define html title
  title: "React Demo",
};

// Define react props: https://reactjs.org/docs/components-and-props.html
export const props = async (request: Request) => {
  // You can access container and its type defined in deps.ts with this way
  const c: Container = request.container;
  return {
    params: request.getParams(),
    header: "Hello, Deno land",
    repository: await c.repository,
  };
};

// Define component: https://reactjs.org/docs/components-and-props.html
const App = (props: { params: string[]; header: string }) => {
  const [count, setCount] = React.useState(0);
  return (
    <div>
      <h2>{props.header}</h2>
      <p>
        This page was created using Deno, Fastro and React's server-side
        rendering (SSR). Click to try the react hook.
      </p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
      <p>You clicked me {count} times</p>
    </div>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

Open react.template.html:

  • This is the usual react template.
  • You can change it as needed.
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{title}}</title>
</head>

<body>
    <div id="root"></div>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Run your webapp:

deno run -A main.ts
Enter fullscreen mode Exit fullscreen mode

Or if you want to monitor any changes and automatically restart:

fastro serve
Enter fullscreen mode Exit fullscreen mode

Open the react page

http://localhost:3000/react
Enter fullscreen mode Exit fullscreen mode

You can see the live demo at this link:
https://phonic-altar-274306.ue.r.appspot.com/react

  • Elements and props created in TSX are rendered into html elements.
  • You can try the implemented react hook by click the button
  • If you open html source, you will get this:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hello Deno Land!</title>
</head>

<body>

<div id="root"><div data-reactroot=""><h2>Hello Deno Land!</h2><p>This page was created using Deno, Fastro and React&#x27;s server-side rendering (SSR). Click to try the react hook.</p><button>Click me</button><p>You clicked me <!-- -->0<!-- --> times </p></div></div>
<script type="module">
  import React from "https://esm.sh/react";
  import ReactDOM from "https://esm.sh/react-dom";
  ReactDOM.hydrate(React.createElement((props)=>{
    const [count, setCount] = React.useState(0);
    return React.createElement("div", null, React.createElement("h2", null, props.msg), React.createElement("p", null, "This page was created using Deno, Fastro and React's server-side rendering (SSR). Click to try the react hook."), React.createElement("button", {
        onClick: ()=>setCount(count + 1)
    }, "Click me"), React.createElement("p", null, "You clicked me ", count, " times "));
}, {"msg":"Hello Deno Land!"}), document.getElementById('root'))
</script>

</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Discussion (0)

pic
Editor guide