Webpack is the only one that works out of the box, yes. Using it to bundle only the BuckleScript apps is what we do right now and there have been no issues whatsoever. Ideally we’d skip brunch alltogether but messing with something that works in the scope of JS is just inviting needless issues.
Here are some config files (some names changed because this is contract code):
webpack.config.js
:
const path = require('path');
module.exports = {
mode: "production",
entry: {
"app_one": "./bucklescript/app_one.bs.js",
"two": "./bucklescript/two.bs.js",
"three": "./bucklescript/three.bs.js",
"example-app": "./bucklescript/example_app.bs.js"
},
output: {
path: path.resolve(__dirname, "..", "priv", "static", "js"),
filename: "[name]-bs.js"
}
};
This means that our packaged apps will show up alongside our brunch bundles as <app-name>-bs.js
and that’s how we’d refer to them in pages.
bsconfig.json
{
"name": "project-name",
"sources": { "dir": "bucklescript" },
"generate-merlin": true,
"bs-dependencies": [
"bs-webapi",
"bucklescript-phx",
"@glennsl/bs-json",
"bucklescript-tea"
],
"package-specs": {
"module": "commonjs",
"in-source": true
},
"suffix": ".bs.js",
"bsc-flags": [
"-bs-super-errors -no-alias-deps",
"-color",
"always",
"-w",
"-40+6+7+27+32..39+44+45",
"-w @8"
]
}
Watchers:
watchers: [
node: [
"node_modules/.bin/bsb",
"-clean-world",
"-make-world",
"-w",
cd: Path.expand("../assets", __DIR__)
],
sh: [
"../priv/scripts/run-delayed-webpack.sh",
cd: Path.expand("../assets", __DIR__)
],
node: [
"node_modules/brunch/bin/brunch",
"watch",
"--stdin",
cd: Path.expand("../assets", __DIR__)
]
]
Note that if you use an earlier version of bsb
it wasn’t suitable for using as a watcher so you’d have to run a script that took care of closing when STDIO closed, etc. The delayed webpack script is just a script that waits a bit for bsb
to compile everything and then does packaging because it was easier than figuring out if there is a way to have webpack not complain about the entry points not being there.
For docker I’ve made a version of the build that precompiles the bucklescript compiler and never pulls it from npm
and the bs toolchain compilation is cached, so making changes to the code really only means having the rest of the npm
stuff taking time, not the super dumb “Oh, you don’t have an OCaml compiler, ninja and bsb? We’ll build all three” thing that happens. The only way I managed to get the behavior I wanted was by using yarn link
to get the behavior I thought npm link
should’ve been (npm
overwrites links if you do npm install
). This way you can get a set bsb
version that works within the whole JS build flow for a cost you pay only when you change something foundational in your Dockerfile:
RUN apk update && apk --update upgrade && apk add [a bunch of stuff] opam parallel m4 yarn
RUN opam init && opam update && opam switch 4.02.3+buckle-1 && opam install cppo
RUN git clone https://github.com/BuckleScript/bucklescript bs \
&& cd bs && git checkout 3.1.5
RUN cd bs && eval $(opam config env) \
&& yarn install \
&& cd vendor/ocaml \
&& ./configure -prefix `pwd` && make world.opt && make install \
&& cd ../.. && make && make install && yarn link
...
RUN parallel "sh -c" ::: "mix local.rebar --force" "mix local.hex --force" && \
eval $(opam config env) && \
mix deps.get --only prod && \
parallel "sh -c" ::: "MIX_ENV=prod mix compile" \
"cd 'apps/project_name/assets' && npm install --global brunch && yarn link bs-platform && yarn install --production --prefer-offline && bsb -make-world && node_modules/.bin/webpack && brunch build --production"
There are probably hundreds of ways to get this behavior and they might well be simpler than this one. This one is what I found after messing around with it, though.