Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"babylon": "^6.17.4",
"babylon-walk": "^1.0.2",
"browser-resolve": "^1.11.2",
"bsb-js": "^1.0.1",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not take this on as a dependency - people can install it locally in their projects. can you move it to a dev dep for the tests and use localRequire below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bsb-js is a thin wrapper over finding and running a BuckleScript executable, kind of like the logic in the TS asset. I developed he package for use cases like this, adding Reason support easily to a new bundler.

This doesn’t actually depend on BuckleScript, so users would still have to install that themselves. Requiring users to install it themselves wouldn’t make that much sense because it’s a package meant to be used by tooling.

With this being the case, it is ok to add it as a dependency? If it helps at all, I’m the maintainer of that package.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After #306 lands this won't be such a big deal since deps like this will be automatically installed by parcel as needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even so, bsb-js is still a pretty small dependency to add. It doesn't include the entire compiler toolchain and has no dependencies itself. The package should only add ~2.7k

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a slippery slope I think. We don't do it for other asset types, so I don't want to start now.

"chalk": "^2.1.0",
"chokidar": "^1.7.0",
"commander": "^2.11.0",
Expand Down
2 changes: 2 additions & 0 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class Parser {
this.registerExtension('es6', './assets/JSAsset');
this.registerExtension('jsm', './assets/JSAsset');
this.registerExtension('mjs', './assets/JSAsset');
this.registerExtension('ml', './assets/ReasonAsset');
this.registerExtension('re', './assets/ReasonAsset');
this.registerExtension('ts', './assets/TypeScriptAsset');
this.registerExtension('tsx', './assets/TypeScriptAsset');
this.registerExtension('coffee', './assets/CoffeeScriptAsset');
Expand Down
28 changes: 28 additions & 0 deletions src/assets/ReasonAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const bsb = require('bsb-js');
const fs = require('fs');
const JSAsset = require('./JSAsset');
const promisify = require('../utils/promisify');
const readFile = promisify(fs.readFile);

class ReasonAsset extends JSAsset {
async parse(code) {
// This runs BuckleScript - the Reason to JS compiler.
// Other Asset types use `localRequire` but the `bsb-js` package already
// does that internally. This should also take care of error handling in
// the Reason compilation process.
if (process.env.NODE_ENV !== 'test') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not building in the tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building during test would require adding BuckleScript as a dev dependency. BS is a big native binary that compiles itself on install, which takes about 7 minutes.

The wrapper around BuckleScript, bsb-js, is pretty well tested, so the tests for Reason only test the file-loading logic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see, ok.

await bsb.runBuild();
}

// This is a simplified use-case for Reason - it only loads the recommended
// BuckleScript configuration to simplify the file processing.
const outputFile = this.name.replace(/\.(re|ml)$/, '.bs.js');
const outputContent = await readFile(outputFile);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there no way to do this without writing to a temporary file first?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, what do you mean by writing to a temp file?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, it seems like bsb-js or whatever that uses is writing its output to a temp file, which we then need to read here. Is there a way to avoid that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. the compileFile function as used by parcel-plugin-bucklescript seems to return the output directly to a variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compileFile basically does the same thing here — reading the result of the output. Currently BuckleScript has no way of compiling Reason like that without seriously compromised performance and maintainability.

this.contents = outputContent.toString();

// After loading the compiled JS source, use the normal JS behavior.
return await super.parse(this.contents);
}
}

module.exports = ReasonAsset;
5 changes: 5 additions & 0 deletions test/integration/reason/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var local = require('./local.re');

module.exports = function () {
return local.a + local.b;
};
11 changes: 11 additions & 0 deletions test/integration/reason/local.bs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions test/integration/reason/local.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
let a = 1;

let b = 2;
16 changes: 16 additions & 0 deletions test/reason.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const assert = require('assert');
const fs = require('fs');
const {bundle, run, assertBundleTree} = require('./utils');

describe('reason', function() {
it('should produce a bundle', async function() {
let b = await bundle(__dirname + '/integration/reason/index.js');

assert.equal(b.assets.size, 2);
assert.equal(b.childBundles.size, 0);

let output = run(b);
assert.equal(typeof output, 'function');
assert.equal(output(), 3);
});
});