Skip to content

Commit

Permalink
Add boilerplate and BuckleScript demo
Browse files Browse the repository at this point in the history
  • Loading branch information
davesnx committed Sep 17, 2020
1 parent 38c485b commit 323a4fa
Show file tree
Hide file tree
Showing 15 changed files with 5,520 additions and 5 deletions.
7 changes: 7 additions & 0 deletions demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
.merlin
.bsb.lock
npm-debug.log
/lib/bs/
/node_modules/
/bundleOutput/
61 changes: 61 additions & 0 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ReasonReact Template & Examples

This is:
- A template for your new ReasonReact project.
- A collection of thin examples illustrating ReasonReact usage.
- Extra helper documentation for ReasonReact (full ReasonReact docs [here](https://reasonml.github.io/reason-react/)).

`src` contains 4 sub-folders, each an independent, self-contained ReasonReact example. Feel free to delete any of them and shape this into your project! This template's more malleable than you might be used to =).

The point of this template and examples is to let you understand and personally tweak the entirely of it. We **don't** give you an opaque, elaborate mega build setup just to put some boxes on the screen. It strikes to stay transparent, learnable, and simple. You're encouraged to read every file; it's a great feeling, having the full picture of what you're using and being able to touch any part.

## Run

```sh
npm install
npm run server
# in a new tab
npm start
```

Open a new web page to `http://localhost:8000/`. Change any `.re` file in `src` to see the page auto-reload. **You don't need any bundler when you're developing**!

**How come we don't need any bundler during development**? We highly encourage you to open up `index.html` to check for yourself!

# Features Used

| | Blinking Greeting | Reducer from ReactJS Docs | Fetch Dog Pictures | Reason Using JS Using Reason |
|---------------------------|-------------------|---------------------------|--------------------|------------------------------|
| No props | || | |
| Has props | | | ||
| Children props || | | |
| No state | | | ||
| Has state || || |
| Has state with useReducer | || | |
| ReasonReact using ReactJS | | | ||
| ReactJS using ReasonReact | | | ||
| useEffect || || |
| Dom attribute ||| ||
| Styling |||||
| React.array | | || |

# Bundle for Production

We've included a convenience `UNUSED_webpack.config.js`, in case you want to ship your project to production. You can rename and/or remove that in favor of other bundlers, e.g. Rollup.

We've also provided a barebone `indexProduction.html`, to serve your bundle.

```sh
npm install webpack webpack-cli
# rename file
mv UNUSED_webpack.config.js webpack.config.js
# call webpack to bundle for production
./node_modules/.bin/webpack
open indexProduction.html
```

# Handle Routing Yourself

To serve the files, this template uses a minimal dependency called `moduleserve`. A URL such as `localhost:8000/scores/john` resolves to the file `scores/john.html`. If you'd like to override this and handle URL resolution yourself, change the `server` command in `package.json` from `moduleserve ./ --port 8000` to `moduleserve ./ --port 8000 --spa` (for "single page application"). This will make `moduleserve` serve the default `index.html` for any URL. Since `index.html` loads `Index.bs.js`, you can grab hold of the URL in the corresponding `Index.re` and do whatever you want.

By the way, ReasonReact comes with a small [router](https://reasonml.github.io/reason-react/docs/en/router) you might be interested in.
29 changes: 29 additions & 0 deletions demo/bsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "reason-react-examples",
"reason": {
"react-jsx": 3
},
"sources": {
"dir": "src",
"subdirs": true
},
"bsc-flags": [
"-bs-super-errors",
"-bs-no-version-header"
],
"package-specs": [
{
"module": "commonjs",
"in-source": true
}
],
"suffix": ".bs.js",
"namespace": true,
"bs-dependencies": [
"reason-react"
],
"ppx-flags": [
"../_build/default/bin/bin.exe"
],
"refmt": 3
}
22 changes: 22 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ReasonReact Examples</title>
</head>
<body>
<script>
// stub a variable ReactJS checks. ReactJS assumes you're using a bundler, NodeJS or similar system that provides it the `process.env.NODE_ENV` variable.
window.process = {
env: {
NODE_ENV: 'development'
}
};
</script>

<!-- This is https://github.com/marijnh/moduleserve, the secret sauce that allows us not need to bundle things during development, and have instantaneous iteration feedback, without any hot-reloading or extra build pipeline needed. -->
<script src="/moduleserve/load.js" data-module="/src/Index.bs.js"></script>
<!-- Our little watcher. Super clean. Check it out! -->
<script src="./watcher.js"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "demo",
"version": "0.1.0",
"scripts": {
"build": "bsb -make-world",
"start": "bsb -make-world -w -ws _ ",
"clean": "bsb -clean-world",
"server": "moduleserve ./ --port 8000",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"BuckleScript",
"ReasonReact",
"reason-react"
],
"author": "",
"license": "MIT",
"dependencies": {
"react": "^16.8.1",
"react-dom": "^16.8.1",
"reason-react": ">=0.7.0"
},
"devDependencies": {
"bs-platform": "^7.0.1",
"moduleserve": "^0.9.0"
}
}
26 changes: 26 additions & 0 deletions demo/src/BlinkingGreeting.bs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

var Curry = require("bs-platform/lib/js/curry.js");
var React = require("react");

function BlinkingGreeting(Props) {
var randomProp = Props.randomProp;
var match = React.useState((function () {
return "sTaTe";
}));
var setShow = match[1];
var show = match[0];
React.useEffect((function () {
console.log(show);
Curry._1(setShow, (function (param) {
return randomProp;
}));

}), [show]);
return React.createElement("div", undefined);
}

var make = BlinkingGreeting;

exports.make = make;
/* react Not a pure module */
16 changes: 16 additions & 0 deletions demo/src/BlinkingGreeting.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[@react.component]
let make = (~randomProp: string) => {
let (show, setShow) = React.useState(() => "sTaTe");

React.useEffect1(
() => {
Js.log(show);
setShow(_ => randomProp);

None;
},
[|show|],
);

<div />;
};
26 changes: 26 additions & 0 deletions demo/src/Index.bs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

var React = require("react");
var ReactDom = require("react-dom");
var BlinkingGreeting$ReasonReactExamples = require("./BlinkingGreeting.bs.js");

function makeContainer(text) {
var container = document.createElement("div");
container.className = "container";
var title = document.createElement("div");
title.className = "containerTitle";
title.innerText = text;
var content = document.createElement("div");
content.className = "containerContent";
container.appendChild(title);
container.appendChild(content);
document.body.appendChild(container);
return content;
}

ReactDom.render(React.createElement(BlinkingGreeting$ReasonReactExamples.make, {
randomProp: "3"
}), makeContainer("Blinking Greeting"));

exports.makeContainer = makeContainer;
/* Not a pure module */
24 changes: 24 additions & 0 deletions demo/src/Index.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[@bs.val] external document: Js.t({..}) = "document";

let makeContainer = text => {
let container = document##createElement("div");
container##className #= "container";

let title = document##createElement("div");
title##className #= "containerTitle";
title##innerText #= text;

let content = document##createElement("div");
content##className #= "containerContent";

let () = container##appendChild(title);
let () = container##appendChild(content);
let () = document##body##appendChild(container);

content;
};

ReactDOMRe.render(
<BlinkingGreeting randomProp="3" />,
makeContainer("Blinking Greeting"),
);
44 changes: 44 additions & 0 deletions demo/watcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// This is our simple, robust watcher. It hooks into the BuckleScript build
// system to listen for build events.
// See package.json's `start` script and `./node_modules/.bin/bsb --help`

// Btw, if you change this file and reload the page, your browser cache
// _might_ not pick up the new version. If you're in Chrome, do Force Reload.

var websocketReloader;
var LAST_SUCCESS_BUILD_STAMP =
localStorage.getItem("LAST_SUCCESS_BUILD_STAMP") || 0;
// package.json's `start` script's `bsb -ws _` means it'll pipe build events
// through a websocket connection to a default port of 9999. This is
// configurable, e.g. `-ws 5000`
var webSocketPort = 9999;

function setUpWebSocket() {
if (websocketReloader == null || websocketReloader.readyState !== 1) {
try {
websocketReloader = new WebSocket(`ws://localhost:${webSocketPort}`);
websocketReloader.onmessage = (message) => {
var newData = JSON.parse(message.data).LAST_SUCCESS_BUILD_STAMP;
if (newData > LAST_SUCCESS_BUILD_STAMP) {
LAST_SUCCESS_BUILD_STAMP = newData;
localStorage.setItem(
"LAST_SUCCESS_BUILD_STAMP",
LAST_SUCCESS_BUILD_STAMP
);
// Refresh the page! This will naturally re-run everything,
// including our moduleserve which will re-resolve all the modules.
// No stable build!
location.reload(true);
}
};
} catch (exn) {
console.error(
"The watcher tried to connect to web socket, but failed. Here's the message:"
);
console.error(exn);
}
}
}

setUpWebSocket();
setInterval(setUpWebSocket, 2000);
Loading

0 comments on commit 323a4fa

Please sign in to comment.