How can I run both my server and also build client?

I am reading the book “introducing rescript” and having little bit difficulty in organizing my code.

currently my structure looks like

src
|-->Client.res
|-->Server.res
bsconfig.json
package.json

Here my package.json looks like

{
  "name": "example1",
  "version": "0.1.0",
  "type":"module",
  "scripts": {
    "clean": "rescript clean -with-deps",
    "build": "rescript build && webpack",
    "watch": "rescript build -w",
    "serve": "node src/Server.bs.js"
  },
  "keywords": [
    "ReScript"
  ],
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "copy-webpack-plugin": "^11.0.0",
    "css-loader": "^6.7.3",
    "html-webpack-plugin": "^5.5.0",
    "rescript": "^10.0.1",
    "style-loader": "^3.3.1",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-html-plugin": "^0.1.1"
  },
  "dependencies": {
    "@rescript/react": "^0.11.0",
    "express": "^4.18.2",
    "rescript-express": "^0.4.1",
    "rescript-nodejs": "^14.3.1",
    "rescript-webapi": "^0.7.0"
  }
}

With this code when I do npm run serve it runs my server successfully. But now when I do npm run build it gives an error message

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' 
file extension and '/Users/foo/code/Rescript/example1/package.json' 
contains "type": "module". To treat it as a CommonJS script, rename 
it to use the '.cjs' file extension.
    at file:///Users/foo/code/Rescript/example1/webpack.config.js:1:14
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)

Now if I take out the like "type":"module" from the package.json. Now I can successfully do npm run build but now the command npm run serve it throws error

(node:99699) Warning: To load an ES module, set "type": "module" in 
the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was 
created)
/Users/foo/code/Rescript/example1/src/Server.bs.js:3
import * as Url from "url";
^^^^^^
SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1195:20)
    at Module._compile (node:internal/modules/cjs/loader:1239:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1329:10)
    at Module.load (node:internal/modules/cjs/loader:1133:32)
    at Module._load (node:internal/modules/cjs/loader:972:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47

How can I structure my package.json file in a way that I can run both the server as well as build my client?

Hey,

Maybe you’re missing a setting in your bsconfig?

In one of my projects, I’m using ES6 modules for the backend and frontend part.
In my bsconfig, I have set module to es6 and suffix to .mjs.

I don’t need any special settings in the package.json.

Thanks your suggestion works and now I can do both. but it changes the extension for everything to MJS. Is there a way I can get the client side files as .bj.js and only the server becomes mjs?

or should I just split the directory into two separate projects altogether?

You could also split it and use two different bsconfig files. Actually I’m using a monorepo for this but had trouble with shared libraries while using different settings.

You’re using webpack to bundle the frontend part? So the file extension shouldn’t matter?!

How does one have multiple bsconfig files? the documentation doesn’t talk about it Build System Configuration | ReScript Language Manual

Also, when I convert the suffix to mjs webpack generates the final “index.js” in a weird way. It just “links” to mjs file whereas when the suffix was “.bs.js” it was taking the entire content and then generating the final “index.js”.

So you have to configure your webpack process or use different modules and extensions.
Maybe "module": "commonjs" and "suffix": "cjs"?

I’m using esbuild to bundle my frontend (no problems with es modules). The backend will run in nodejs - no bundling etc. is necessary.

If you want to use different configs, you need different subfolders. If you still want to share code between fe and be, you could use a monorepo. Check this page: Pinned Dependencies | ReScript Language Manual