## Transpiling with Babel

Install Babel and core-js:

    npm install --save-dev @babel/core @babel/cli @babel/preset-env
    npm install core-js

Create a `babel.config.json` next to your build:

    {
      "presets": [
        ["@babel/preset-env", {
          "targets": "> 0.5%, last 2 versions, not dead",
          "useBuiltIns": "usage",
          "corejs": 3
        }]
      ]
    }

Set `targets` to the browserslist query matching the engines you need to support.

Compile your program with js_of_ocaml, then run Babel on the output:

    js_of_ocaml program.byte -o program.js
    npx babel program.js -o program.es5.js

The resulting `program.es5.js` imports polyfills from `core-js` with `require("core-js/modules/...")` calls. Before shipping to a browser you need to bundle it so those imports are resolved and inlined.

## Bundling

Any JavaScript bundler will work; esbuild is a small, zero-config option:

    npm install --save-dev esbuild
    npx esbuild program.es5.js --bundle --platform=browser \
      --external:node:* --target=es5 --outfile=program.bundle.js

The runtime contains a few `require("node:*")` calls (filesystem, tty, etc.) guarded by Node-detection branches that never run in a browser. `--external:node:*` tells esbuild to leave those imports in place instead of failing to resolve them at bundle time.

`--target` is needed even when Babel has lowered the input: esbuild's own IIFE wrapper and CommonJS helpers use arrow functions and other post-ES5 syntax, and `--target` is what tells it to lower those too. Set it to the lowest syntax level your browserslist query implies.

Ship `program.bundle.js` as a single script; no additional polyfills are required at load time.

## With dune

Assuming dune builds your program to `program.bc.js` (e.g. from an `(executable (modes js) ...)` stanza), wire the Babel and esbuild steps into the build with two rules:

    (rule
     (targets program.es5.js)
     (deps program.bc.js babel.config.json)
     (action
      (run npx babel %{dep:program.bc.js} -o %{targets})))

    (rule
     (targets program.bundle.js)
     (deps program.es5.js)
     (action
      (run npx esbuild %{dep:program.es5.js}
           --bundle --platform=browser --external:node:*
           --target=es5 --outfile=%{targets})))

## See also

- Command line options — compiler flags
- Installation — supported engines