bsb-js: BuckleScript Build Wrapper
bsb-js is a foundational JavaScript library designed to programmatically interface with the BuckleScript build system (`bsb`), which is crucial for compiling ReasonML and OCaml source code into JavaScript. As of version 1.1.7, it provides an API to trigger compilation tasks, allowing developers to integrate BuckleScript builds into various JavaScript tooling environments like Webpack (via `bs-loader`) or Rollup (via `rollup-plugin-bucklescript`). The library is currently active, receiving updates primarily for compatibility with new `bs-platform` versions and improving error resilience. Its release cadence is driven by maintenance and necessary adaptations to the BuckleScript ecosystem. A key differentiator is its role in decoupling the core compilation logic from specific bundler integrations, enabling a more modular and reusable approach to integrating ReasonML/OCaml builds within JavaScript projects.
Common errors
-
Error: spawn bsb ENOENT
cause The `bsb` executable (part of `bs-platform`) is not found in the system's PATH. `bsb-js` relies on this external command.fixInstall `bs-platform` globally (`npm install -g bs-platform`) or locally in your project (`npm install --save-dev bs-platform`) and ensure your build environment's PATH includes the local `node_modules/.bin` directory. -
Compilation failed: [...] "errors": [{ "type": "error", "message": "Syntax error: [...]" }]cause The ReasonML or OCaml source file being compiled contains syntax errors or other compilation issues that `bsb` reports.fixReview the error message details provided by `bsb` (which `bsb-js` forwards) and correct the syntax or logic in your source `.re` or `.ml` file. -
Cannot find module 'bsb-js'
cause The `bsb-js` package has not been installed, or the import path is incorrect.fixRun `npm install bsb-js` or `yarn add bsb-js`. Verify that your `import` or `require` statement correctly references the package name.
Warnings
- breaking The `compileFileSync` function's parameters were updated in `bsb-js@1.1.0` to match those of `compileFile` for consistency. Code relying on the older `compileFileSync` signature will break.
- breaking Starting with `bs-loader@2.0.0`, the core compilation logic was extracted into separate packages, including `bsb-js` and `read-bsconfig`. Projects previously using `bs-loader` as a monolithic solution will need to explicitly integrate `bsb-js` or use other bundler plugins built on top of it.
- gotcha `bsb-js` wraps the `bsb` executable. Compatibility issues can arise if the `bs-platform` version installed in your environment (globally or locally) is not aligned with the expectations of your `bsb-js` version. For instance, `bsb-js@1.1.7` includes a fix for `bs-platform` 4.0.5.
Install
-
npm install bsb-js -
yarn add bsb-js -
pnpm add bsb-js
Imports
- compileFile
const { compileFile } = require('bsb-js');import { compileFile } from 'bsb-js'; - compileFileSync
import compileFileSync from 'bsb-js';
import { compileFileSync } from 'bsb-js'; - ReadBsConfig
import type { ReadBsConfig } from 'bsb-js';
Quickstart
import { writeFileSync, mkdirSync, readFileSync, rmSync } from 'fs';
import { join } from 'path';
import { compileFile } from 'bsb-js';
// 1. Setup a dummy ReasonML project structure
const projectRoot = join(process.cwd(), 'temp_bsb_project');
const srcDir = join(projectRoot, 'src');
const bsConfigPath = join(projectRoot, 'bsconfig.json');
const reasonFilePath = join(srcDir, 'MyModule.re');
// Ensure clean slate
try { rmSync(projectRoot, { recursive: true, force: true }); } catch (e) {}
mkdirSync(srcDir, { recursive: true });
// 2. Write a minimal bsconfig.json
writeFileSync(bsConfigPath, JSON.stringify({
"name": "temp_project",
"sources": ["src"],
"package-specs": {
"module": "commonjs",
"in-source": true
},
"suffix": ".bs.js"
}, null, 2));
// 3. Write a simple ReasonML file
writeFileSync(reasonFilePath, `
let message = "Hello from ReasonML!";
let greet = () => print_endline(message);
`);
console.log('Dummy ReasonML project set up.');
// 4. Use bsb-js to compile the file
async function compileMyModule() {
try {
console.log(`Compiling ${reasonFilePath} using bsb-js...`);
// The first argument is the root where bsconfig.json resides.
// The second argument is the path to the source file relative to the project root.
const result = await compileFile(projectRoot, 'src/MyModule.re', {
log: true // Output bsb logs to console
});
if (result.isSuccess) {
console.log('\nCompilation successful!');
const jsFilePath = join(srcDir, 'MyModule.bs.js'); // Assuming in-source build
if (readFileSync(jsFilePath, 'utf8')) {
console.log(`Compiled JS content found at ${jsFilePath}`);
console.log('--- Compiled JS (first 100 chars) ---');
console.log(readFileSync(jsFilePath, 'utf8').substring(0, 100));
console.log('------------------------------------');
}
} else {
console.error('\nCompilation failed:', result.errors);
}
} catch (error) {
console.error('\nAn unexpected error occurred during compilation:', error);
} finally {
// Clean up temporary directory
console.log('\nCleaning up temporary project...');
rmSync(projectRoot, { recursive: true, force: true });
}
}
compileMyModule();