Blueprint: Does core require a new babel loader?

Created on 5 May 2020  路  13Comments  路  Source: palantir/blueprint

Environment

  • __Package version(s)__: 3.26.1

If possible, link to a minimal repro (fork this code sandbox): https://github.com/alephdata/aleph/blob/master/ui/package.json

Steps to reproduce

  1. Install @blueprint/core inside a create-react-app app.
  2. Attempt to compile

Actual behavior

./node_modules/@blueprintjs/core/lib/esnext/components/forms/numericInput.js 60:31
Module parse failed: Unexpected token (60:31)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|       const delta = this.updateDelta(direction, e);
|       const nextValue = this.incrementValue(delta);
>       this.props.onButtonClick?.(+nextValue, nextValue);
|     };
|

Possible solution

Not clear on what further configuration is required.

tooling core in discussion

Most helpful comment

The error is thrown from acorn 6 in webpack 4, it is fixed in webpack 5: https://github.com/webpack/webpack/issues/11186

Unfortunately due to breaking changes from acorn 6.4.0 to 7.0.0, webpack 4 can not ship acorn 8, which supports optional chaining.

Specifying chrome 79 can work around this issue because @babel/preset-env will apply optional chaining for chrome 79. Since chrome 80 supports optional chaining, it will _not_ transpile optional chaining and thus acorn throw parsing error.

Alternatively, you can also wait until CRA updates to webpack 5: https://github.com/facebook/create-react-app/pull/7929, when webpack 5 is used, please remove chrome 79 so @babel/preset-env can skip most transpling.

All 13 comments

It does if your build system picks up the esnext module entry point specified in package.json:

https://github.com/palantir/blueprint/blob/cd55cc18f3f510fb4f400c7a524d43d499c17056/packages/core/package.json#L7

This build target was added in https://github.com/palantir/blueprint/pull/3230... but now I'm looking at the tsconfig options documentation and --target esnext appears to be discouraged since it is a moving target. I wonder if we should stick to a more predictable --target es2019 instead. Or maybe CRA should be favoring the "module" field over "esnext"? The latter is less standardized...

Sorry for the unintentional break @pudo

@maclockard @ericanderson I wonder if you have any insight here?

@pudo this is happening since you are directly importing an esnext file here: https://github.com/alephdata/aleph/blob/7ab658998ae41aa86ee15bf93f3f4f6911235ba6/ui/src/components/Screen/Screen.jsx#L5-L6. While this fixes the es5 vs es6+ class compatibility issue, its now causing a problem since the create-react-app's babel-loader can't handle the optional chain operator (?.) which blueprint makes use of. There's a couple ways to fix this I think.

An easy and quick way would be to upgrade to a new version of babel, since they added support for both optional chaining and nullish coalescing in 7.8.0 (CHANGELOG). I'm not too sure about your setup or create-react-app's setup, but upgrading to a newer version of create-react-app should fix this, looks like newer versions are on babel 7.9.6 (link) which should cover this. If upgrading create-react-app is not an option, you can maybe try to force resolve the transitive dependency in your repo. Not sure how to do this with npm, but yarn offers some tooling here.

An option with slightly longer turn around would be for blueprint to add another target like es2018 or es2019, but I don't see too much of an advantage here since most folks using esnext should be handling babeling their dependencies themselves since its more of an experimental evergreen thing than something explicitly supported. A more sustainable solution to prevent a need for targeting every es version would be to add alternatives to the decorator for both hot keys and context menus.

Just wanted to chime in and say that I have the very same issue and most likely since I am importing the HotkeysTarget similar to OP since it wouldn't work otherwise without specified the exact esnext import path. A quick resolution on this issue would be highly appreciated, in the meantime I have to go back to a pinned older version that still works.

@ChristianIvicevic are you unable to upgrade babel versions? that's the quick resolution outlined above. You will also need to make sure you babel blueprint as a part of your build process.

@maclockard Thank you for your fast reply. I am currently running react-scripts 3.4.1 which uses babel 7.9.0. I assume that upgrading other dependencies caused the lockfile to be partially regenerated since everything worked with blueprint 3.25.0 a few moments ago.

So I am already running the latest published version of react-scripts with the respective babel version. Since I haven't ejected I am not in control of the. underlying babel configuration and versions and would prefer not to mess around with it too much and I don't actually know how to enforce a newer babel version to used right now.

Out of curiousity I tried removing the HotkeysTarget reference entirely and get the same error, so it's "just" a compilation error when attempting to import @blueprint/core.

can you copy and paste your compilation error? I would expect that version of babel to be able to properly handle an optional chain operator.

It's virtually the same that OP had.

Failed to compile.

./node_modules/@blueprintjs/core/lib/esnext/components/forms/numericInput.js 60:31
Module parse failed: Unexpected token (60:31)
File was processed with these loaders:
 * ./node_modules/react-scripts/node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|       const delta = this.updateDelta(direction, e);
|       const nextValue = this.incrementValue(delta);
>       this.props.onButtonClick?.(+nextValue, nextValue);
|     };
|

I found a bizzare fix! It is described in the following PR: https://github.com/facebook/create-react-app/pull/8526

The browserlists in package.json is per default super strict with last 1 chrome version. However it seems that there is a mismatch with the newest Chrome version 80 that supports certain nullish features. When I replaced last 1 chrome version with last 10 chrome version it suddenly worked and compiled correctly. I still have to try setting the value to chrome 79 to see what happens then.

ah interesting, that makes sense

Quick update, adding chrome 79 in addition to last 1 chrome version fixed the problem. I have to be honest, since I never worked with browserlists myself and took this feature for granted, I am not entirely sure why it fixed the problem, at least it is a quick fix for the time being until the underlying acorn issue described in the original PR is resolved.

(Nevertheless I'd appreciate that HotkeysTarget is made usable at some point in the future without importing the esnext module manually since it has come up during this issue, even though it wasn't the culprit.)

Thanks for the comprehensive feedback on this. The work-around of specifying chrome 79 in the browsers list works, so as an immediate issue this is gone for us. We could close the issue or maybe there's a more long-term code change you wanna base off this?

The error is thrown from acorn 6 in webpack 4, it is fixed in webpack 5: https://github.com/webpack/webpack/issues/11186

Unfortunately due to breaking changes from acorn 6.4.0 to 7.0.0, webpack 4 can not ship acorn 8, which supports optional chaining.

Specifying chrome 79 can work around this issue because @babel/preset-env will apply optional chaining for chrome 79. Since chrome 80 supports optional chaining, it will _not_ transpile optional chaining and thus acorn throw parsing error.

Alternatively, you can also wait until CRA updates to webpack 5: https://github.com/facebook/create-react-app/pull/7929, when webpack 5 is used, please remove chrome 79 so @babel/preset-env can skip most transpling.

I don't think there's any more action on Blueprint's part required here. By definition, the esnext target will produce JS in lib/esnext which often requires post-processing to run in a common JS environment. If your build system picks up this entry point, it's your responsibility to do that post-processing.

Also, re: the last comment in this thread, Webpack 5 has been out for some time now and we have now upgraded to it in this repo without any issues.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

henrify picture henrify  路  17Comments

anasbud picture anasbud  路  20Comments

ripitrust picture ripitrust  路  19Comments

zsherman picture zsherman  路  33Comments

basarat picture basarat  路  17Comments