Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Reason asset type #342

Merged
merged 7 commits into from
Dec 21, 2017
Merged

Add Reason asset type #342

merged 7 commits into from
Dec 21, 2017

Conversation

rrdelaney
Copy link
Contributor

This adds the Reason asset type to .re files.

Right now this is pretty basic and only loads the recommended Reason configuration. I can update it to use other configurations if you want, but overall I think this is a good starting point.

The code for this is pretty simple -- a lot of the work was already done in the Reason commuity's wrapper for the build tool, bsb-js. That should handle requiring the build tool per-project and error handling already, so little logic other than "run the build" and "read the result" are needed.

@davidnagli
Copy link
Contributor

Nice!

src/Parser.js Outdated
@@ -12,6 +12,7 @@ class Parser {
this.registerExtension('es6', './assets/JSAsset');
this.registerExtension('jsm', './assets/JSAsset');
this.registerExtension('mjs', './assets/JSAsset');
this.registerExtension('re', './assets/ReasonAsset');
Copy link
Contributor

Choose a reason for hiding this comment

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

What about .ml files?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added for OCaml files too 😄

const fs = require('fs');
const JSAsset = require('./JSAsset');
const config = require('../utils/config');
const localRequire = require('../utils/localRequire');
Copy link
Contributor

Choose a reason for hiding this comment

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

Appear to be unused:

const config = require('../utils/config');
const localRequire = require('../utils/localRequire');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, they were. Thanks!

// the Reason compilation process.
await bsb.runBuild();

this.contents = await new Promise((resolve, reject) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could use ../utils/promisify on fs.readFile instead of new Promise.

@brandon93s
Copy link
Contributor

See parcel-plugin-bucklescript (npm) for an existing plugin. Similar implementation, but may provide a bit more on the config front.

@davidnagli
Copy link
Contributor

I just tried it out and I’m consistently getting the error:

🚨  script: bsb: No such file or directory

And yes, I do have a file called hello.re:

> ls
    dist     hello.re

Full output:

> parcelfork hello.re
    ⏳  Building...
    Server running at http://localhost:1234
    🚨  script: bsb: No such file or directory

^C

parcelfork is just a little alias I set up to run the version of Parcel that I have forked locally (in this case switched to your PR HEAD). It’s essentially just calling bin/cli.js

If you’re reproducing this, here’s the exact code I use (taken from here):

hello.re

type tree = Leaf | Node(int, tree, tree);

let rec sum =
  fun
  | Leaf => 0
  | Node(value, left, right) => value + sum(left) + sum(right);

let myTree =
  Node(
    1,
    Node(2, Node(4, Leaf, Leaf), Node(6, Leaf, Leaf)),
    Node(3, Node(5, Leaf, Leaf), Node(7, Leaf, Leaf))
  );

sum(myTree) |> Js.log;

@rrdelaney
Copy link
Contributor Author

@brandon93s Thanks for the link! It looks like the implementation they used adapted from bs-loader, a Webpack loader I wrote for BuckleScript. bs-loader has a few problems and complexities, so we're actively trying to move away from it. By only supporting a small set of BuckleScript configurations the code can be simpler, faster, and more predictable.

@davidnagli You'll need to run the following commands in your project to get set up with Reason:

$ npm install --dev bs-platform
$ touch bsconfig.json
$ touch src/index.re

and then copy this into bsconfig.json:

{
  "name": "reason-parcel-example",
  "sources": [
    "src"
  ],
  "refmt": 3,
  "package-specs": {
    "module": "commonjs",
    "in-source": true
  },
  "suffix": ".bs.js"
}

@rrdelaney
Copy link
Contributor Author

Uhh, I don't think that last one should have failed. The HTML test failed for some reason?

// 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.

@@ -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.

// 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.

@@ -0,0 +1,11 @@
// Generated by BUCKLESCRIPT VERSION 1.9.2, PLEASE EDIT WITH CARE
Copy link
Member

Choose a reason for hiding this comment

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

doesn't seem like this should be committed...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I hard coded the result of compiling the Reason file with BuckleScript so that we don’t have to run it when running the tests. BuckleScript is a binary that compiles itself during installation which could take a while. By hard coding the result we can test just the loading logic, because the logic to run BuckleScript is contained in another package, bsb-js.

@brandon93s
Copy link
Contributor

@rrdelaney - That test experiences random failures; a fix for it is now in master.

Sent with GitHawk

@rrdelaney
Copy link
Contributor Author

@brandon93s Thanks 😄 I just pulled from upstream

@devongovett devongovett merged commit 47e9192 into parcel-bundler:master Dec 21, 2017
@devongovett
Copy link
Member

I moved bsb-js to a dev dependency and used localRequire. That should get it autoinstalled when used once #306 lands.

devongovett pushed a commit that referenced this pull request Oct 15, 2018
* Add bsb-js dependency

* Add ReasonAsset type

* Actually add the Reason asset type

* Add OCaml file type, add integration test, remote unused imports

* use promisify for reading files

* Fix integration tests
devongovett pushed a commit that referenced this pull request Oct 15, 2018
* Add bsb-js dependency

* Add ReasonAsset type

* Actually add the Reason asset type

* Add OCaml file type, add integration test, remote unused imports

* use promisify for reading files

* Fix integration tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants