Skip to content

Commit

Permalink
Merge branch 'npm-scripts' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
feihong committed Feb 7, 2024
2 parents ba69137 + 4b72174 commit d8c51a7
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 188 deletions.
2 changes: 1 addition & 1 deletion .githooks/prepush
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

if ! ( make format-check ); then
if ! ( npm run format-check ); then
echo "some files are not properly formatted, refusing to push"
exit 1
fi
6 changes: 3 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ jobs:
with:
ocaml-compiler: 5.1.1
- name: Install all deps
run: make install
run: npm run install-opam-npm
- name: Format check
run: make format-check
run: npm run format-check
- name: Bundle the demo app
run: make bundle
run: npm run bundle
- name: Install dependencies for VitePress
run: |
cd docs
Expand Down
59 changes: 0 additions & 59 deletions Makefile

This file was deleted.

51 changes: 14 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,29 @@ Developers](https://react-book.melange.re/).
## Quick Start

```shell
make init
npm run init

# In separate terminals:
make watch
make serve
```

When running `make init`, you may encounter an error like this:

```
[ERROR] Could not determine which packages to install for this switch:
* Missing dependency:
- melange >= 3.0.0-51
no matching version
```

To address this, first run `opam update`, then rerun `make init`.

## Serving apps

By default, running `make serve` will serve the Counter app located in
`src/counter`. To run another app, you can `cd` into its directory and run
`make serve` there. For example, to run the Celsius Converter app:

```
cd src/celsius-converter-option
make serve
```

Another way is to specify the name of the app via the `app` environment variable
before running `make serve` in the root directory, e.g.

```
app=celsius-converter-option make serve
npm run watch
npm run serve
```

## Commands

You can see all available commands by running `make help` or just `make`. Here
All the build commands are defined in the `scripts` field of `package.json`.
This is completely optional, and other tools like `make` could be used.

You can see all available commands by running `npm run`. There are explanations
of each command in the `scriptsComments` field of the `package.json` file. Here
are a few of the most useful ones:

- `make init`: set up opam local switch and download OCaml, Melange and
- `npm run init`: set up opam local switch and download OCaml, Melange and
JavaScript dependencies
- `make install`: install OCaml, Melange, and JavaScript dependencies
- `make watch`: watch the filesystem and have Melange rebuild on every change
- `make serve`: Serve an application using a local HTTP server
- `npm run install-opam-npm`: install OCaml, Melange, and JavaScript
dependencies
- `npm run watch`: watch the filesystem and have Melange rebuild on every
change
- `npm run serve`: serve the application with a local HTTP server

## Book

Expand Down
2 changes: 1 addition & 1 deletion docs/better-sandwiches/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export default defineConfig({
});
```

Now run `make bundle` again and you should see some output like this:
Now run `npm run bundle` again and you should see some output like this:

```bash{5}
vite v5.0.11 building for production...
Expand Down
4 changes: 2 additions & 2 deletions docs/counter/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ We're going build the classic frontend starter app, the counter, using
1. Go to the root directory of your
[melange-for-react-devs-template](https://github.com/melange-re/melange-for-react-devs-template)
project
1. Run `make watch` to start the Melange compiler in watch mode.
1. In another terminal window, start the Vite dev server by running `make
1. Run `npm run watch` to start the Melange compiler in watch mode.
1. In another terminal window, start the Vite dev server by running `npm run
serve`. As a side effect, it will open a browser tab pointed to
<a href="http://localhost:5174/" target="_blank" rel="noreferrer
noopener">http://localhost:5174/</a>.
Expand Down
14 changes: 7 additions & 7 deletions docs/installation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ template
```bash
git clone https://github.com/melange-re/melange-for-react-devs-template
cd melange-for-react-devs-template
make init
make build
make serve
npm run init
npm run build
npm run serve
```

While `make init` is running, consider grabbing some coffee or other beverage,
as it might take a while to fetch all the dependencies and build them. The last
command, `make serve`, should open a tab in your default browser which points to
<a href="http://localhost:5174/" target="_blank" rel="noreferrer
While `npm run init` is running, consider grabbing some coffee or other
beverage, as it might take a while to fetch all the dependencies and build them.
The last command, `npm run serve`, should open a tab in your default browser which
points to <a href="http://localhost:5174/" target="_blank" rel="noreferrer
noopener">http://localhost:5174/</a> and shows you a typical "Hello World" page.
If you see this page, then the project was successfully installed!

Expand Down
138 changes: 63 additions & 75 deletions docs/intro-to-dune/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,7 @@ Melange project.
`target`'s value is `output`, so the location of `Index.js` is

```
_build/default/stuff/Index.js
```

If the `dune` file was in directory `foo/bar` and the value of `target` was
`fructus`, the location of `Index.js` would be

```
_build/default/foo/bar/fructus/foo/bar/Index.js
_build/default/output/Index.js
```

We need to know the exact location of `Index.js` so that we can reference it in
Expand All @@ -139,8 +132,8 @@ layout](https://melange.re/v3.0.0/build-system/#javascript-artifacts-layout).
::: tip

In this dune file, we're only concerned with building JavaScript to run in the
browser, but if we also wanted to build JavaScript to run on Node, we'd include
another `melange.emit` stanza specifically for that. See
browser, but if we also wanted to build JavaScript to run on Node using
CommonJS, we'd include another `melange.emit` stanza specifically for that. See
[melange-opam-template](https://github.com/melange-re/melange-opam-template/blob/main/src/dune)
for an example of building for Node.

Expand Down Expand Up @@ -176,6 +169,42 @@ src/counter
└─ index.html
```

## Structure of `_build` directory

If you look inside the `_build/default/src/counter` directory, you'll see that
your `src/counter` directory is essentially mirrored there, along with some
extra files:

```
_build/default/src/counter
├─ .merlin-conf/
├─ .output.mobjs/
├─ output/
├─ Counter.re
├─ Counter.re.ml
├─ Counter.re.pp.ml
├─ Index.re
├─ Index.re.ml
└─ Index.re.pp.ml
```

Extra files and directories like `.output.mobjs` and `Counter.re.ml` are build
artifacts and we won't go into any detail about them. If you look into
`_build/default/src/counter/output/src/counter`, you'll see that `src/counter` is mirrored
there as well, but this time the directory only contains the generated `.js`
files:

```
_build/default/src/counter/output/src/counter
├─ .output.mobjs/
├─ Counter.js
└─ Index.js
```

So the `_build` directory contains two mirrored directories for `src/counter`:
one for the original `.re` source files and their intermediate build artifacts,
another for the final generated `.js` files.

## Update root directory `index.html`

Now that we've added `src/counter/index.html`, we don't need the root
Expand All @@ -200,62 +229,12 @@ index page to link to all of our single-page apps. Change `index.html` to this:
</html>
```

Now run `make serve` to check that everything works as expected.

## Why use Make?

By now you might have noticed that even though Dune is used to build your
project, we never execute Dune directly, but instead always go through
[Make](https://en.wikipedia.org/wiki/Make_(software)). One reason is that the
commands for Dune can occasionally be verbose, but the other reason is that Make
is a very good task runner. For example, here are some advantages it has over
`npm run`:

- You can add comments!
- It's trivial to create tasks with multiple commands
- Running `make` lists all the rules inside the `Makefile` (achieved with a few
lines of boilerplate)

## Modifying the `serve` rule

Right now the project is still using `npm run` to serve the app, but let's
migrate it fully to Make. First, take a look at the `serve` rule inside the
`Makefile`:

```make
.PHONY: serve
serve: ## Serve the application with a local HTTP server
npm run serve
```

A breakdown of this rule:

- `.PHONY: serve` tells Make that the `serve` rule is a [phony
target](https://makefiletutorial.com/#phony), meaning `serve` is not a file we
want to generate but just a label for an action. Note that declaring phony
targets is optional.
- The name of the rule is `serve`, and it's followed immediately by a comment
(denoted by whatever follows `#`) explaining its purpose.
- Underneath the rule's name is its *recipe*, basically the command(s) that will
be executed when we run `make serve` at the command line. Here it just runs
`npm run serve`.

There's no particular reason to rely on `npm run`, so change the `Makefile`'s
`serve` rule to:

```make{3}
.PHONY: serve
serve: ## Serve the application with a local HTTP server
npx vite serve --open
```

Run `make serve` again to verify that it does the same thing as before.
Now run `npm run serve` to check that everything works as expected.

::: tip

Feel free to do a little cleanup before moving on:

- Delete the `scripts` section of `package.json`
- Delete the `Index.re` file in the root directory
- Delete the `melange.emit` stanza from the root directory's `dune` file

Expand Down Expand Up @@ -295,9 +274,27 @@ Celsius Converter.
<b>2.</b> Delete `reason-react-ppx` from `src/counter/dune`'s `melange.emit`
stanza. What compiler errors do you get?

<b>3.</b> You might have noticed that every recipe in the Makefile is prefixed
by a tab. What happens if you replace the tab in front of the `serve` rule's
recipe with four spaces?
<b>3.</b> Assume you have a directory `foo/bar` in the root of your project
directory with these files in it:

```
foo/bar
├─ Hello.re
└─ dune
```

The contents of `foo/bar/dune` are:

```clj
(melange.emit
(target dist)
(libraries reason-react)
(preprocess
(pps melange.ppx reason-react-ppx))
(module_systems es6))
```

What is the path of the `Hello.js` file generated by Melange?

## Overview

Expand All @@ -310,9 +307,6 @@ recipe with four spaces?
- Which directories to include and which to exclude
- Which directories contain code that should be transpiled to JavaScript,
using the `melange.emit` stanza
- Make is a great way to run project-related tasks
- A `Makefile` contains rules which can run commands based on the target you
pass to the `make` command

## Solutions

Expand Down Expand Up @@ -345,18 +339,12 @@ That's because putting `reason-react-ppx` in the `preprocess/pps` field will
transform function calls to `div` (which isn't defined anywhere) into calls to
`React.createElement("div", ...)`[^2].

<b>3.</b> Replacing the tab in front of the `serve` rule's
recipe with four spaces will result in a `Makefile` error:
<b>3.</b> The path of the `Hello.js` file generated from `foo/bar/Hello.re` is:

```
Makefile:42: *** missing separator. Stop.
_build/default/foo/bar/dist/foo/bar/Hello.js
```

The line number where it expects the tab is 42. It is a very common mistake to
write spaces instead of tabs in a `Makefile`. Fortunately, most code editors
know that when you press the Tab key inside a `Makefile`, you mean to add a tab
character instead of space characters.

-----

Source code for this chapter:
Expand Down
2 changes: 1 addition & 1 deletion docs/intro/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ teaches the language from the ground up and goes much deeper into its features.
| Numberic Types | Use Melange Playground to explore OCaml’s numeric types | Int, Float, Playground, sharing snippets, comparison operators, arithmetic operators, widgets in Playground |
| Celsius Converter | Single input that converts from Celsius to Fahrenheit | `Js.t` object, string concatenation (`++`), exception handling, ternary expression, if-else expression, labeled argument, partial application |
| Celsius Converter using Option | The same component from the last chapter but replacing exception handling with Option | Option, `Option.map`, `when` guard |
| Introduction to Dune | A introduction to the Dune build system | `dune-project` file, `dune` file, `melange.emit` stanza, `Makefile`, monorepo structure |
| Introduction to Dune | A introduction to the Dune build system | `dune-project` file, `dune` file, `melange.emit` stanza, monorepo structure |
| Order Confirmation | An order confirmation for a restaurant website | variant type, primary type of module (`t`), wildcard (`_`) in switch, `fun` syntax, `Js.Array` functions, `React.array`, type transformation functions |
| Styling with CSS | Styling the order confirmation using CSS | `mel.raw` extension node, `runtime_deps` field, `glob_files` term, `external`, `mel.module` attribute |

Expand Down
Loading

0 comments on commit d8c51a7

Please sign in to comment.