├── .gitignore
├── README.md
├── bsconfig.json
├── bundle.js
├── package-lock.json
├── package.json
└── src
├── App.bundle.js
├── App.mjs
├── App.noreact.js
├── App.res
├── AppOptimized.bundle.js
├── AppOptimized.mjs
├── AppOptimized.res
├── index.html
├── listForEach.bundle.js
├── listForEach.mjs
├── listForEach.res
├── listForEachU.bundle.js
├── listForEachU.mjs
├── listForEachU.res
├── listLength.bundle.js
├── listLength.mjs
├── listLength.res
└── preload-react.html
/.gitignore:
--------------------------------------------------------------------------------
1 | *.exe
2 | *.obj
3 | *.out
4 | *.compile
5 | *.native
6 | *.byte
7 | *.cmo
8 | *.annot
9 | *.cmi
10 | *.cmx
11 | *.cmt
12 | *.cmti
13 | *.cma
14 | *.a
15 | *.cmxa
16 | *.obj
17 | *~
18 | *.annot
19 | *.cmj
20 | *.bak
21 | lib/bs
22 | *.mlast
23 | *.mliast
24 | .vscode
25 | .merlin
26 | .bsb.lock
27 | /node_modules/
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Zero bundle cost for [ReScript](https://github.com/rescript-lang/rescript-compiler)
3 |
4 | This is a repo showing that when adopting ReScript in your projects, it adds close to zero cost to your bundler size unlike many other languages compiled to JS platform.
5 |
6 | We have serveral modules: `listLength`, `listForEachU`, `listForEach`, `App`, `AppOptimized`.
7 |
8 | For each `module`, `module.mjs` is the generated js code using Ecmascript module format,
9 |
10 | `module.bundle.js` is the bundled output using a bundler -- it is a self contained script that runs with all dependencies bundled in.
11 |
12 |
13 | For [listLength](./src/listLength.bundle.js), and [listForEachU](./src/listForEachU.bundle.js) the bundled code is tiny (a couple of hundered bytes including comments).
14 |
15 | [listForEach](./src/listForEach.bundle.js) is slightly larger since it needs curried runtime support, but its output is still tiny.
16 |
17 | [App.res](./src/App.res) is a working example using Rescript with React. You can see the bundled output: [App.bundle.js](./src/App.bundle.js) by grepping `bs-platform`, only lines from 5536-5594 -- less than 60 lines of code -- are needed for ReScript runtime.
18 |
19 | Even for such 60 lines of code, it can be optmized away using uncurried calling convention in [AppOptimized.res](./src/AppOptimized.res). In the [AppOptimized.bundle.js](./src/AppOptimized.bundle.js), the ReScript app using React is completely ReScript runtime free.
20 |
21 | Note the bundler is configured to not rename variables so that we can have a clear look at the impact of using ReScript.
22 |
23 | # Build
24 | ```
25 | npm run build
26 | ```
27 | # Bundle
28 |
29 | The bundle demo uses the open source bundler esbuild
30 | ```
31 | node ./bundle.js
32 | ```
33 |
34 |
--------------------------------------------------------------------------------
/bsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-esbuild",
3 | "version": "0.1.0",
4 | "sources": {
5 | "dir" : "src",
6 | "subdirs" : true
7 | },
8 | "bs-dependencies": ["@rescript/react"],
9 | "package-specs" : {"module": "es6" , "in-source" : true,"suffix": ".mjs"},
10 |
11 | "reason": {"react-jsx": 3}
12 | }
13 |
--------------------------------------------------------------------------------
/bundle.js:
--------------------------------------------------------------------------------
1 | //@ts-check
2 | var fs = require("fs");
3 | var cp = require("child_process");
4 | var esbuild = require("esbuild");
5 | const { readdirSync } = fs;
6 |
7 | var path = require("path");
8 |
9 | var src = path.join(__dirname, "src");
10 |
11 | var targets = readdirSync(src)
12 | .filter((x) => x.endsWith(".mjs"))
13 | .map((file) => path.join(src, file));
14 |
15 | var plugin = {
16 | name: "react",
17 | setup(build) {
18 | build.onResolve({ filter: /^(react|react-dom)$/ }, (args) => {
19 | return {
20 | path: args.path,
21 | namespace: "globalExternal",
22 | };
23 | });
24 | build.onLoad({ filter: /^react/, namespace: "globalExternal" }, (args) => {
25 | var map = {
26 | react: `React`,
27 | "react-dom": `ReactDOM`,
28 | };
29 |
30 | return {
31 | contents: `module.exports = globalThis.${map[args.path]}`,
32 | loader: "js",
33 | };
34 | });
35 | },
36 | };
37 | esbuild.build({
38 | entryPoints: targets,
39 | bundle: true,
40 | minifySyntax: true,
41 | sourcemap: false,
42 | define: {
43 | ["process.env.NODE_ENV"]: "'production'",
44 | },
45 | outdir: "src",
46 | outExtension: {
47 | ".js": ".bundle.js",
48 | },
49 | plugins: [plugin],
50 | });
51 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-demo",
3 | "version": "0.1.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "rescript-demo",
9 | "version": "0.1.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "@rescript/react": "^0.10.1",
13 | "esbuild": "^0.8.42",
14 | "react": "^17.0.1",
15 | "react-dom": "^17.0.1",
16 | "reason-react": "^0.9.1"
17 | },
18 | "devDependencies": {
19 | "bs-platform": "9.0.1"
20 | }
21 | },
22 | "node_modules/@rescript/react": {
23 | "version": "0.10.1",
24 | "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.10.1.tgz",
25 | "integrity": "sha512-5eIfGnV1yhjv03ktK6fQ6iEfsZKXKXXrq5hx4+ngEY4R/RU8o/oH9ne375m9RJMugV/jsE8hMoEeSSg2YQy3Ag==",
26 | "peerDependencies": {
27 | "bs-platform": "^8.3.0",
28 | "react": "^16.8.1",
29 | "react-dom": "^16.8.1"
30 | }
31 | },
32 | "node_modules/bs-platform": {
33 | "version": "9.0.1",
34 | "resolved": "https://registry.npmjs.org/bs-platform/-/bs-platform-9.0.1.tgz",
35 | "integrity": "sha512-RxUrwxVBCx9AiiyFIthZwfPn+tAn9noRHCb9xJK4Uw2deGxIytqyoWDepMbH35v7EpxX0OhfXL5RrjHTaXersA==",
36 | "dev": true,
37 | "hasInstallScript": true,
38 | "bin": {
39 | "bsb": "bsb",
40 | "bsc": "bsc",
41 | "bsrefmt": "bsrefmt",
42 | "bstracing": "lib/bstracing"
43 | }
44 | },
45 | "node_modules/esbuild": {
46 | "version": "0.8.42",
47 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.42.tgz",
48 | "integrity": "sha512-zUtj5RMqROCCCH0vV/a7cd8YQg8I0GWBhV3A3PklWRT+oM/YwVbnrtFnITzE1otGdnXplWHWdZ4OcYiV0PN+JQ==",
49 | "hasInstallScript": true,
50 | "bin": {
51 | "esbuild": "bin/esbuild"
52 | }
53 | },
54 | "node_modules/js-tokens": {
55 | "version": "4.0.0",
56 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
57 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
58 | },
59 | "node_modules/loose-envify": {
60 | "version": "1.4.0",
61 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
62 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
63 | "dependencies": {
64 | "js-tokens": "^3.0.0 || ^4.0.0"
65 | },
66 | "bin": {
67 | "loose-envify": "cli.js"
68 | }
69 | },
70 | "node_modules/object-assign": {
71 | "version": "4.1.1",
72 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
73 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
74 | "engines": {
75 | "node": ">=0.10.0"
76 | }
77 | },
78 | "node_modules/react": {
79 | "version": "17.0.1",
80 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz",
81 | "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==",
82 | "dependencies": {
83 | "loose-envify": "^1.1.0",
84 | "object-assign": "^4.1.1"
85 | },
86 | "engines": {
87 | "node": ">=0.10.0"
88 | }
89 | },
90 | "node_modules/react-dom": {
91 | "version": "17.0.1",
92 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz",
93 | "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==",
94 | "dependencies": {
95 | "loose-envify": "^1.1.0",
96 | "object-assign": "^4.1.1",
97 | "scheduler": "^0.20.1"
98 | },
99 | "peerDependencies": {
100 | "react": "17.0.1"
101 | }
102 | },
103 | "node_modules/reason-react": {
104 | "version": "0.9.1",
105 | "resolved": "https://registry.npmjs.org/reason-react/-/reason-react-0.9.1.tgz",
106 | "integrity": "sha512-nlH0O2TDy9KzOLOW+vlEQk4ExHOeciyzFdoLcsmmiit6hx6H5+CVDrwJ+8aiaLT/kqK5xFOjy4PS7PftWz4plA==",
107 | "peerDependencies": {
108 | "bs-platform": "^7.1.1",
109 | "react": "^16.8.1",
110 | "react-dom": "^16.8.1"
111 | }
112 | },
113 | "node_modules/scheduler": {
114 | "version": "0.20.1",
115 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz",
116 | "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==",
117 | "dependencies": {
118 | "loose-envify": "^1.1.0",
119 | "object-assign": "^4.1.1"
120 | }
121 | }
122 | },
123 | "dependencies": {
124 | "@rescript/react": {
125 | "version": "0.10.1",
126 | "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.10.1.tgz",
127 | "integrity": "sha512-5eIfGnV1yhjv03ktK6fQ6iEfsZKXKXXrq5hx4+ngEY4R/RU8o/oH9ne375m9RJMugV/jsE8hMoEeSSg2YQy3Ag=="
128 | },
129 | "bs-platform": {
130 | "version": "9.0.1",
131 | "resolved": "https://registry.npmjs.org/bs-platform/-/bs-platform-9.0.1.tgz",
132 | "integrity": "sha512-RxUrwxVBCx9AiiyFIthZwfPn+tAn9noRHCb9xJK4Uw2deGxIytqyoWDepMbH35v7EpxX0OhfXL5RrjHTaXersA==",
133 | "dev": true
134 | },
135 | "esbuild": {
136 | "version": "0.8.42",
137 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.42.tgz",
138 | "integrity": "sha512-zUtj5RMqROCCCH0vV/a7cd8YQg8I0GWBhV3A3PklWRT+oM/YwVbnrtFnITzE1otGdnXplWHWdZ4OcYiV0PN+JQ=="
139 | },
140 | "js-tokens": {
141 | "version": "4.0.0",
142 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
143 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
144 | },
145 | "loose-envify": {
146 | "version": "1.4.0",
147 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
148 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
149 | "requires": {
150 | "js-tokens": "^3.0.0 || ^4.0.0"
151 | }
152 | },
153 | "object-assign": {
154 | "version": "4.1.1",
155 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
156 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
157 | },
158 | "react": {
159 | "version": "17.0.1",
160 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz",
161 | "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==",
162 | "requires": {
163 | "loose-envify": "^1.1.0",
164 | "object-assign": "^4.1.1"
165 | }
166 | },
167 | "react-dom": {
168 | "version": "17.0.1",
169 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz",
170 | "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==",
171 | "requires": {
172 | "loose-envify": "^1.1.0",
173 | "object-assign": "^4.1.1",
174 | "scheduler": "^0.20.1"
175 | }
176 | },
177 | "reason-react": {
178 | "version": "0.9.1",
179 | "resolved": "https://registry.npmjs.org/reason-react/-/reason-react-0.9.1.tgz",
180 | "integrity": "sha512-nlH0O2TDy9KzOLOW+vlEQk4ExHOeciyzFdoLcsmmiit6hx6H5+CVDrwJ+8aiaLT/kqK5xFOjy4PS7PftWz4plA=="
181 | },
182 | "scheduler": {
183 | "version": "0.20.1",
184 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz",
185 | "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==",
186 | "requires": {
187 | "loose-envify": "^1.1.0",
188 | "object-assign": "^4.1.1"
189 | }
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rescript-demo",
3 | "version": "0.1.0",
4 | "scripts": {
5 | "clean": "bsb -clean-world",
6 | "build": "bsb -make-world",
7 | "watch": "bsb -make-world -w"
8 | },
9 | "keywords": [
10 | "ReScript"
11 | ],
12 | "author": "",
13 | "license": "MIT",
14 | "devDependencies": {
15 | "bs-platform": "9.0.1"
16 | },
17 | "dependencies": {
18 | "@rescript/react": "^0.10.1",
19 | "esbuild": "^0.8.42",
20 | "react": "^17.0.1",
21 | "react-dom": "^17.0.1",
22 | "reason-react": "^0.9.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/App.bundle.js:
--------------------------------------------------------------------------------
1 | (() => {
2 | var __create = Object.create, __defProp = Object.defineProperty, __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty, __getOwnPropNames = Object.getOwnPropertyNames, __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3 | var __markAsModule = (target) => __defProp(target, "__esModule", {value: !0});
4 | var __commonJS = (callback, module) => () => (module || (module = {exports: {}}, callback(module.exports, module)), module.exports);
5 | var __exportStar = (target, module, desc) => {
6 | if (__markAsModule(target), module && typeof module == "object" || typeof module == "function")
7 | for (let key of __getOwnPropNames(module))
8 | !__hasOwnProp.call(target, key) && key !== "default" && __defProp(target, key, {get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable});
9 | return target;
10 | }, __toModule = (module) => module && module.__esModule ? module : __exportStar(__defProp(module != null ? __create(__getProtoOf(module)) : {}, "default", {value: module, enumerable: !0}), module);
11 |
12 | // globalExternal:react
13 | var require_react = __commonJS((exports, module) => {
14 | module.exports = globalThis.React;
15 | });
16 |
17 | // globalExternal:react-dom
18 | var require_react_dom = __commonJS((exports, module) => {
19 | module.exports = globalThis.ReactDOM;
20 | });
21 |
22 | // node_modules/bs-platform/lib/es6/caml_array.js
23 | function caml_array_sub(x, offset, len) {
24 | for (var result = new Array(len), j = 0, i = offset; j < len; )
25 | result[j] = x[i], j = j + 1 | 0, i = i + 1 | 0;
26 | return result;
27 | }
28 |
29 | // node_modules/bs-platform/lib/es6/curry.js
30 | function app(_f, _args) {
31 | for (; ; ) {
32 | var args = _args, f = _f, init_arity = f.length, arity = init_arity === 0 ? 1 : init_arity, len = args.length, d = arity - len | 0;
33 | if (d === 0)
34 | return f.apply(null, args);
35 | if (d >= 0)
36 | return function(f2, args2) {
37 | return function(x) {
38 | return app(f2, args2.concat([x]));
39 | };
40 | }(f, args);
41 | _args = caml_array_sub(args, arity, -d | 0), _f = f.apply(null, caml_array_sub(args, 0, arity));
42 | }
43 | }
44 | function _1(o, a0) {
45 | var arity = o.length;
46 | if (arity === 1)
47 | return o(a0);
48 | switch (arity) {
49 | case 1:
50 | return o(a0);
51 | case 2:
52 | return function(param) {
53 | return o(a0, param);
54 | };
55 | case 3:
56 | return function(param, param$1) {
57 | return o(a0, param, param$1);
58 | };
59 | case 4:
60 | return function(param, param$1, param$2) {
61 | return o(a0, param, param$1, param$2);
62 | };
63 | case 5:
64 | return function(param, param$1, param$2, param$3) {
65 | return o(a0, param, param$1, param$2, param$3);
66 | };
67 | case 6:
68 | return function(param, param$1, param$2, param$3, param$4) {
69 | return o(a0, param, param$1, param$2, param$3, param$4);
70 | };
71 | case 7:
72 | return function(param, param$1, param$2, param$3, param$4, param$5) {
73 | return o(a0, param, param$1, param$2, param$3, param$4, param$5);
74 | };
75 | default:
76 | return app(o, [a0]);
77 | }
78 | }
79 |
80 | // src/App.mjs
81 | var React = __toModule(require_react()), ReactDom = __toModule(require_react_dom());
82 | function reducer(state, action) {
83 | return action ? {
84 | count: state.count - 1 | 0
85 | } : {
86 | count: state.count + 1 | 0
87 | };
88 | }
89 | function App$App(Props) {
90 | var match = React.useReducer(reducer, {
91 | count: 0
92 | }), dispatch = match[1];
93 | return React.createElement("main", void 0, "Simple counter with reducer", React.createElement("div", void 0, React.createElement("button", {
94 | onClick: function(param) {
95 | return _1(dispatch, 1);
96 | }
97 | }, "Decrement"), React.createElement("span", {
98 | className: "counter"
99 | }, String(match[0].count)), React.createElement("button", {
100 | onClick: function(param) {
101 | return _1(dispatch, 0);
102 | }
103 | }, "Increment")));
104 | }
105 | var e = document.querySelector("#root");
106 | e != null && ReactDom.render(React.createElement(App$App, {}), e);
107 | })();
108 |
--------------------------------------------------------------------------------
/src/App.mjs:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Curry from "bs-platform/lib/es6/curry.js";
4 | import * as React from "react";
5 | import * as ReactDom from "react-dom";
6 |
7 | function reducer(state, action) {
8 | if (action) {
9 | return {
10 | count: state.count - 1 | 0
11 | };
12 | } else {
13 | return {
14 | count: state.count + 1 | 0
15 | };
16 | }
17 | }
18 |
19 | function App$App(Props) {
20 | var match = React.useReducer(reducer, {
21 | count: 0
22 | });
23 | var dispatch = match[1];
24 | return React.createElement("main", undefined, "Simple counter with reducer", React.createElement("div", undefined, React.createElement("button", {
25 | onClick: (function (param) {
26 | return Curry._1(dispatch, /* Decrement */1);
27 | })
28 | }, "Decrement"), React.createElement("span", {
29 | className: "counter"
30 | }, String(match[0].count)), React.createElement("button", {
31 | onClick: (function (param) {
32 | return Curry._1(dispatch, /* Increment */0);
33 | })
34 | }, "Increment")));
35 | }
36 |
37 | var e = document.querySelector("#root");
38 |
39 | if (!(e == null)) {
40 | ReactDom.render(React.createElement(App$App, {}), e);
41 | }
42 |
43 | export {
44 |
45 | }
46 | /* e Not a pure module */
47 |
--------------------------------------------------------------------------------
/src/App.noreact.js:
--------------------------------------------------------------------------------
1 | (() => {
2 | var __create = Object.create;
3 | var __defProp = Object.defineProperty;
4 | var __getProtoOf = Object.getPrototypeOf;
5 | var __hasOwnProp = Object.prototype.hasOwnProperty;
6 | var __getOwnPropNames = Object.getOwnPropertyNames;
7 | var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8 | var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
9 | var __exportStar = (target, module, desc) => {
10 | __markAsModule(target);
11 | if (module && typeof module === "object" || typeof module === "function") {
12 | for (let key of __getOwnPropNames(module))
13 | if (!__hasOwnProp.call(target, key) && key !== "default")
14 | __defProp(target, key, {get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable});
15 | }
16 | return target;
17 | };
18 | var __toModule = (module) => {
19 | if (module && module.__esModule)
20 | return module;
21 | return __exportStar(__defProp(module != null ? __create(__getProtoOf(module)) : {}, "default", {value: module, enumerable: true}), module);
22 | };
23 |
24 | // node_modules/bs-platform/lib/es6/caml_array.mjs
25 | function caml_array_sub(x, offset, len) {
26 | var result = new Array(len);
27 | var j = 0;
28 | var i = offset;
29 | while (j < len) {
30 | result[j] = x[i];
31 | j = j + 1 | 0;
32 | i = i + 1 | 0;
33 | }
34 | ;
35 | return result;
36 | }
37 |
38 | // node_modules/bs-platform/lib/es6/curry.mjs
39 | function app(_f, _args) {
40 | while (true) {
41 | var args = _args;
42 | var f = _f;
43 | var init_arity = f.length;
44 | var arity = init_arity === 0 ? 1 : init_arity;
45 | var len = args.length;
46 | var d = arity - len | 0;
47 | if (d === 0) {
48 | return f.apply(null, args);
49 | }
50 | if (d >= 0) {
51 | return function(f2, args2) {
52 | return function(x) {
53 | return app(f2, args2.concat([x]));
54 | };
55 | }(f, args);
56 | }
57 | _args = caml_array_sub(args, arity, -d | 0);
58 | _f = f.apply(null, caml_array_sub(args, 0, arity));
59 | continue;
60 | }
61 | ;
62 | }
63 | function _1(o, a0) {
64 | var arity = o.length;
65 | if (arity === 1) {
66 | return o(a0);
67 | } else {
68 | switch (arity) {
69 | case 1:
70 | return o(a0);
71 | case 2:
72 | return function(param) {
73 | return o(a0, param);
74 | };
75 | case 3:
76 | return function(param, param$1) {
77 | return o(a0, param, param$1);
78 | };
79 | case 4:
80 | return function(param, param$1, param$2) {
81 | return o(a0, param, param$1, param$2);
82 | };
83 | case 5:
84 | return function(param, param$1, param$2, param$3) {
85 | return o(a0, param, param$1, param$2, param$3);
86 | };
87 | case 6:
88 | return function(param, param$1, param$2, param$3, param$4) {
89 | return o(a0, param, param$1, param$2, param$3, param$4);
90 | };
91 | case 7:
92 | return function(param, param$1, param$2, param$3, param$4, param$5) {
93 | return o(a0, param, param$1, param$2, param$3, param$4, param$5);
94 | };
95 | default:
96 | return app(o, [a0]);
97 | }
98 | }
99 | }
100 |
101 | // src/App.mjs
102 | var React2 = globalThis.React;
103 |
104 | // node_modules/reason-react/src/legacy/ReactDOMRe.bs.js
105 | var React = globalThis.React;
106 | var ReactDom = globalThis.ReactDOM;
107 | function renderToElementWithId(reactElement, id) {
108 | var element = document.getElementById(id);
109 | if (element == null) {
110 | console.error("ReactDOMRe.renderToElementWithId : no element of id " + (id + " found in the HTML."));
111 | } else {
112 | ReactDom.render(reactElement, element);
113 | }
114 | }
115 |
116 | // src/App.mjs
117 | function reducer(state, action) {
118 | if (action) {
119 | return {
120 | count: state.count - 1 | 0
121 | };
122 | } else {
123 | return {
124 | count: state.count + 1 | 0
125 | };
126 | }
127 | }
128 | function App$App(Props) {
129 | var match = React2.useReducer(reducer, {
130 | count: 0
131 | });
132 | var dispatch = match[1];
133 | return React2.createElement("main", void 0, "Simple counter with reducer", React2.createElement("div", void 0, React2.createElement("button", {
134 | onClick: function(param) {
135 | return _1(dispatch, 1);
136 | }
137 | }, "Decrement"), React2.createElement("span", {
138 | className: "counter"
139 | }, String(match[0].count)), React2.createElement("button", {
140 | onClick: function(param) {
141 | return _1(dispatch, 0);
142 | }
143 | }, "Increment")));
144 | }
145 | renderToElementWithId(React2.createElement(App$App, {}), "root");
146 | })();
147 |
--------------------------------------------------------------------------------
/src/App.res:
--------------------------------------------------------------------------------
1 | @@config({no_export})
2 | type state = {count: int}
3 |
4 | type action =
5 | | Increment
6 | | Decrement
7 |
8 | let initialState = {count: 0}
9 |
10 | let reducer = (state, action) =>
11 | switch action {
12 | | Increment => {count: state.count + 1}
13 | | Decrement => {count: state.count - 1}
14 | }
15 | module App = {
16 | @react.component
17 | let make = () => {
18 | let (state, dispatch) = React.useReducer(reducer, initialState)
19 |
20 |