Rescript/React/Reprocessing

A couple of weeks ago I asked about reprocessing in a Rescript/React program. I’ve now made enough progress that I feel as if I’m pretty close. But my problem here is with build processes that I don’t understand, so following earlier advice, I’m making code available. What I’ve done is available here.

The ReProcessing part of the program (when run on its own, without React stuff) produces something like this:
Screen Shot 2022-02-13 at 5.35.31 PM
(the red and blue part, not the pale-blue surround).

If you look at public/index.html, you can see that I’ve tried to include the ReProcessing program (Square.res, which becomes Square.bs.js) as a script, followed by a div called root so that the usual react-starter-app can appear below my canvas.That process alone took a long time, because I haven’t developed anything for the web since the days of static web pages! The stock react-demo works fine; the reprocessing part shows nothing.

Changing the .js file included by the first script command seems to have no effect, although I tried various paths, and even main.js, in hopes that the webpack thing I did might produce that.

The webpack.config.js is my crude attempt to mimic something I found in another repo, and it didn’t work.

I’m hoping this is the sort of thing where an expert will look, laugh briefly at my ignorance, say “get rid of the webpack config file, and change line 38 of your public/index.html file to something-or-other and you’ll be on your way.” I sure hope so, because after 12 hours of trying things, I’m getting a bit frustrated. :frowning:

Hello! You’re messing up source files and build artifacts.

When you work through Webpack bundler or something similar, the basic idea is the following:

  • You give the bundler some entry points
  • It scans the entry points and finds their dependencies (what do they import)
  • The process is repeated recursivelly
  • The whole tree is processed/transpiled/shaked/minimized/etc
  • You get final output files in an output directory

Run yarn build:res && yarn build. Then see the build/ directory:

$ tree build                  
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
    ├── css
    │   ├── main.f09a1402.chunk.css
    │   └── main.f09a1402.chunk.css.map
    ├── js
    │   ├── 2.b9467ac3.chunk.js
    │   ├── 2.b9467ac3.chunk.js.LICENSE.txt
    │   ├── 2.b9467ac3.chunk.js.map
    │   ├── main.871d44d5.chunk.js
    │   ├── main.871d44d5.chunk.js.map
    │   ├── runtime-main.90a3cc69.js
    │   └── runtime-main.90a3cc69.js.map
    └── media
        └── logo.6ce24c58.svg

That’s your output. And here, the index.html contains the <script src="../src/Square.bs.js"></script> tag you’ve included literally. As you might imagine, now that path points to nowhere.

The way JavaScript code (produced by ReScript compiler or otherwise) is included in your final bundle is through import chains, not <script/> tags. So, you should use your Square somewhere through the chain starting at the entry point. And now I see Index.res uses App.res, and then App.res uses nothing. Hence the result you have.

1 Like

Hi @spike

This is pretty tricky to set up initially, but all things considered you’ve made great progress.

I’ll add some extra notes that might help:

[1] Install ReScript:

npm i -D rescript

[2] Replace the couple of scripts in package.json

"start:res": "rescript build -w",
"build:res": "rescript build",

[3] In one terminal start the ReScript compiler:

npm run start:res

[4] In another terminal start the main app:

npm start

[5] Here’s a key step - convert your ReProcessing script into a React component.

// Square.res

open Reprocessing

@react.component
let make = () => {
  let id = "reprocessing-square"

  let setup = env => {
    Env.size(~width=200, ~height=200, env)
  }

  let draw = (_state, env) => {
    Draw.background(Constants.red, env)
    Draw.fill(Constants.green, env)
    Draw.rect(~pos=(50, 50), ~width=100, ~height=100, env)
  }

  React.useEffect(() => {
    setScreenId(id)
    run(~setup, ~draw, ())
    None
  })

  <canvas id />
}

[6] Lastly go and add that component to your App.res code:

// App.res

@react.component
let make = () => {
  <div className="App">
    <Square />
    // etc.
  </div>
}

There is lots to clean up in the code you have but if you can get these steps going then you might like to start with a clean Create React App project and apply the steps that work

Hopefully this gets you a bit further.

1 Like

Thank you. “Bundling” and “webpack” have been a black box to me, and seeing this helps open the box a little. That last paragraph is particularly informative, and helps demystify things a lot.

Thank you very much! I believe I’m now ready to go deal with more familiar kinds of bugs, etc. :slight_smile:

As I’m following those directions, various questions/insights are arising.

Item [1]:
I have "rescript": "^9.1.4" in the "devDependencies" in package.json. Shouldn’t that take care of the npm i -D rescript? [I’m still not clear on exactly what “package.json” *does*, but I thought this was one of the things.]

Or were you just saying this in case I’d forgotten and was only using bsb? Changing the scripts seems like a good thing (and something I’d done in earlier drafts), but it also seems to have no real effect, given the simplicity of the code.

Item [1] also:
When I did the recommended install, I got a ton of warnings about deprecated packages, security problems, etc. Here’s a bit of output:
image

Do I just ignore these? Is fixing them something the rescript team needs to get to someday, and just haven’t yet? Or did I install something else incorrectly?

Items 3 & 4:
I had been wondering about this, and it matches what I had been doing (except I tend to build by hand rather than have a watcher, because I tended to use just one terminal in VSCode). I’d really wanted to say “Whenever my rescript file changes, can it recompile so that the js changes, so that the web-serving part notices the difference and my browser-view changes?”, and didn’t really get that this division was probably intentional. I suppose that if you’re saving every few keystrokes, that could get annoying, so it’s split into two phases: do lots of rescript stuff, constantly type-checking, etc., and then when it seems right, go ahead an look at the changes in the resulting web page. Hence the “two different watchers” model.

Step [5]:
Aha! That’s wonderful. It’s not the way that the ReProcessing part gets included in the ReTurbo example that I was trying to mimic, but it clearly works, seems idiomatic, and gets me over the hump.
I don’t suppose we’ll ever cross paths, but if we do, I owe you many beers. :slight_smile: [And if you happen to need some topology/geometry help, I’m here…]

1 Like

Hi @spike

I have "rescript": "^9.1.4" in the "devDependencies" in package.json . Shouldn’t that take care of the npm i -D rescript ?

Yes, great. I didn’t see it in the repo when I took a look, but it sounds like you’d already sorted that out.

When I did the recommended install, I got a ton of warnings about deprecated packages, security problems, etc.

It’s normal to see some warnings, particularly on larger projects, and the warnings listed are for all packages in package.json. I suspect the project you were using as a reference is a bit outdated, so would be good to start a fresh Create React App project if you can which has the latest versions of packages. As a general guideline, if you’re using the latest version of each package then any warnings you see are not usually cause for concern and you can ignore them.

I suppose that if you’re saving every few keystrokes, that could get annoying, so it’s split into two phases: do lots of rescript stuff, constantly type-checking, etc., and then when it seems right, go ahead an look at the changes in the resulting web page. Hence the “two different watchers” model.

Yes, you’ve described it well. There are different ways to go about this, but I’ve personally found the two separate terminals work well - one with a focus on ReScript matters, and one with a focus on web server matters.

It’s not the way that the ReProcessing part gets included in the ReTurbo example that I was trying to mimic, but it clearly works, seems idiomatic

Yes, the ReProcessing example is vanilla HTML/JS but this approach is idiomatic React.