Hello World! in Rescript-React
Tags: react, tutorial, functional, programming
Published: 2021-03-05 04:50:46

# Hello World! in Rescript React

Talking a bit about Rescript, it is a new language that combines the best parts of JS and OCaml. It has a compiler that compiles to JS and leverages OCaml’s static and sound type system. Many people prefer this approach to TypeScript. The compiler was originally named BuckleScript but in 2020, it was rebranded to ReScript because of its Reason-like syntax.

Rescript docs are well written, organized, and maintained actively. [Link to their documentation](https://rescript-lang.org/docs/manual/latest/introduction).

If you have a basic knowledge of Rescript syntax and React, then we are good to go. 

## Setting up the project
- Start with the command `npm init -y`. If you simply do `npm init` it will ask you to fill in a couple of data, if you want them to be default values add the `-y` tag. 

```bash
$ npm init -y
```

- Now, let's install the ReScript compiler locally. The reason we are installing it with `--save-dev` is because we need it as a dev dependency.The Rescript compiler will compile the `*.res` files to JS files. This is actually called source to source compilation. 

```bash 
$ npm install --save-dev bs-platform
```

- Before, moving on to the configuration part, let's install the `rescript-react` plugin. 

```bash
$ npm install @rescript/react --save
```

- Now, we have to set up a `bsconfig.json` file. Create this file and then copy and paste the following into it:

**bsconfig.json**

```json
{
    "$schema": "https://raw.githubusercontent.com/rescript-lang/rescript-compiler/master/docs/docson/build-schema.json",
    "name": "project-name",
    "sources": [
        {
        "dir": "src",
        "subdirs": true
        }
    ],
    "package-specs": [
        {
        "module": "es6",
        "in-source": true
        }
    ],
    "suffix": ".bs.js",
    "namespace": true,
    "bs-dependencies": ["@rescript/react"],
    "ppx-flags": [],
    "reason": {"react-jsx": 3},
    "warnings": {
        "error": "+101"
      },
    "refmt": 3
}
```

Let's understand the config for a moment, going line by line:
1. **$schema**: Editors like VSCode have a feature of schema autocompletion, and to get that we need to specify the schema. 
2. **name**: It is the name of the library or the main project name in simple words.

>**Note:** *the bsconfig.json name should be the same as the package.json name, to avoid confusing corner-cases. However, this means that you can't use a camelCased names such as MyProject, since package.json and npm forbid you to do so (some file systems are case-insensitive).*

3. **sources**: We have to specify where the source files will reside. Usually, it is the `/src` directory.
4. **suffix**: The file extensions after compilation by the Rescript compiler, can be `.js` or `.bs.js`. ( Although, the latter is always preferred )
5. **bs-dependencies**: The list of Rescript dependencies, and since we are using the `rescript-react` we have to specify that here. There is also `bs-dev-dependencies`. These are very similar to how we mention node dependencies in `package.json`.
6. **reason**: Since we will be using React-JSX, we have to specify `{"react-jsx": 3}`. 

> *For normal Rescript projects, the `bs-dependencies` will have `[]` and `reason` will be `{}`. To learn more about the config refer [here](https://rescript-lang.org/docs/manual/latest/build-configuration-schema)*

- To compile the source files we have to add two scripts in our `package.json`. 

**package.json**

```json
"scripts": {
    "clean": "bsb -clean-world",
    "start": "bsb -make-world -w",
}
```

**start**: will compile the res files and will run in watch mode i.e will continuously look for changes and compile it. It is always advised to run the start script and then code the Res files, cause the intelligent rescript compilation helps a lot and makes the coding easier for beginners to the language. 
**clear**: will clean/remove the previously compiled `*.bs.js`files. 

- Now, install `react` and `react-dom` packages.

```bash
$ npm install react react-dom --save
```

- Finally, we will use `snowpack` to build and bundle the project during development. In `snowpack` each file needs to be built only once and then is cached forever. When a file changes, Snowpack rebuilds that single file. There’s no time wasted re-bundling every change, just instant updates in the browser (made even faster via Hot-Module Replacement (HMR)). It is really fast. 
![img](https://www.snowpack.dev/img/snowpack-unbundled-example-3.png)
Again we will install snowpack as a dev dependency:

```bash
$ npm install --save-dev snowpack
```

- Make a `snowpack.config.js` file and copy-paste this. Since we are not using any kind of plugins there is nothing to specify over here.

**snowpack.config.j**

```js
// Example: snowpack.config.js
// The added "@type" comment will enable TypeScript type information via VSCode, etc.

/** @type {import("snowpack").SnowpackUserConfig } */
module.exports = {
    plugins: [
        /* ... */
    ],
};
```

- Now, we have to add a couple of npm scripts for snowpack to start the server and build the project.

**package.json**

```json
"scripts": {
    "dev": "snowpack dev",
    "build": "snowpack build"
}
```

At, this point we are done setting up dependencies, and your final `package.json` should look like this:

**package.json**

```json
{
  "name": "react-res-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "clean": "bsb -clean-world",
    "start": "bsb -make-world -w",
    "dev": "snowpack dev",
    "build": "snowpack build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "bs-platform": "^9.0.1",
    "snowpack": "^3.0.13"
  },
  "dependencies": {
    "@rescript/react": "^0.10.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  }
}
```

## Start writing your Hello World Code!!

- First start off with a simple `index.html` in your root directory. Paste this basic template. One important thing is that there should be a `<div>` with `id="root"` inside which the React components will be rendered. This is how React works, if you already have some experience then you would know. Also, we have to include the compiled `index.bs.js` file. You can simply copy-paste this HTML. If you will use `index.css` then create a file and add its relative path.

**index.html**

```html
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>ReScript React</title>
    <link rel="stylesheet" href="index.css" />
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="src/index.bs.js"></script>
  </body>
</html>
```

- Now create a folder `src` and create a new file `src/index.res`. Inside the `index.res` file just copy-paste this for the time being. We will dive into the code later on. Currently, let's test if all the setup we did was a success. 

```rescript
switch ReactDOM.querySelector("#root") {
| Some(root) => ReactDOM.render(<div> {React.string("Hello World!")} </div>, root)
| None => Js.log("Error: could not find react element")
}
```

> **NOTE**: *Here we are querying for `#root` in the DOM(index.html) i.e looking for an element with `id="root"`. If in the `index.html` you have created some other id let's say `xyz` then over here you have to replace `#root` with `#xyz`.*

- Now, in the terminal run the command to compile the `index.res` file. 

```bash
$ npm run start
```

Once you run this, a new file `index.bs.js` will be created. ( This is why we included the `index.bs.js` file in `<script>` tag in `index.html` ).

To build the react app run this is another terminal window.

```bash
$ npm run dev
```

This will start a snowpack server at `localhost:8080` with hot reload. Visit the URL in your browser and if you see `Hello World!` Congratulations!! You are now ready to create your rescript-react project.

> **NOTE:** Don't keep your `index.css` file empty if you have linked it to the `index.html`. 

Final folder structure will be like this:

```
├── bsconfig.json
├── index.css
├── index.html
├── package.json
├── package-lock.json
├── snowpack.config.js
└── src
    ├── index.bs.js
    └── index.res
```

Was it a long process? Yeah, kind of. But every time you won't have to go through all. Here I have already created a repo with all these steps. Simply clone it and get started:

<a href="https://github.com/arnabsen1729/rescript-react-starter"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/arnabsen1729/rescript-react-starter.png" width="460px"></a>