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

Impossible to adopt new JavaScript features #11339

Closed
mrdoob opened this issue Aug 29, 2021 · 10 comments
Closed

Impossible to adopt new JavaScript features #11339

mrdoob opened this issue Aug 29, 2021 · 10 comments

Comments

@mrdoob
Copy link

mrdoob commented Aug 29, 2021

We recently tried to adopt private class fields in three.js after we realised that even Safari iOS had added support for them.

Turns out we can no longer use caniuse to know if we can adopt new JavaScript features. Bundlers and tools like create react app are behind browsers.

More info: mrdoob/three.js#22437

@gaearon
Copy link
Contributor

gaearon commented Aug 29, 2021

I’m on a vacation but a few quick thoughts:

Does it help to specify the browserslist field in the app’s package.json? Here’s how: https://create-react-app.dev/docs/supported-browsers-features. Set it to ["last 1 chrome version"] and see if it builds after that. We feed that config to babel-preset-env. So if mrdoob/three.js#22437 (comment) is correct then it should already work.

However mrdoob/three.js#22437 (comment) doesn’t quite make sense to me. If you look at the build error, it’s webpack parser choking on the new syntax. Which means Babel has not compiled it. So the env preset actually looks like it “worked” — it did not try to compile anything — but webpack later choked on it because of an older parser or maybe lack of some option.

So maybe it’s worth checking the reverse: does it help to set the browserslist to include older browsers. Thereby forcing Babel to compile private fields to a polyfill. Not quite what you wanted but if this works, at least it should prevent webpack from choking on the syntax it doesn’t know about.

The actual fix on our side is likely to update webpack to a version that uses a parser which supports this syntax. It needs to be investigated which version is the minimal one with that support.

To sum up:

  • we need to confirm what the actual behavior of the env preset is because CRA does use it
  • we need to check which webpack version would just let this syntax through

I’m not actively working on this (and I’m on a vacation) but hopefully this provides pointers.

@marcofugaro
Copy link
Contributor

Issue on the webpack repo: webpack/webpack#10216

@gaearon
Copy link
Contributor

gaearon commented Aug 30, 2021

Is it stage 4 already?

@mrdoob
Copy link
Author

mrdoob commented Aug 30, 2021

That's the troubling question.

Why do bundlers care whether it is stage 4 before adding support and browsers don't?

Screenshot_20210830-143854

@mjurczyk
Copy link

However mrdoob/three.js#22437 (comment) doesn’t quite make sense to me.

@gaearon let me know if I can be of any help - since it's my comment. The project did indeed fail to build on latest CRA, but compiled when I ejected the config and added latest babel-preset-env manually to options: { presets: [ ... ] } in both js/jsx/ts/tsx resolvers in webpack config.

@nrayburn-tech
Copy link

nrayburn-tech commented Sep 9, 2021

I think the issue is related to the CRA webpack config. CRA does a lesser processing through Babel for dependencies than it does for application code.

I can create a new app and use a private field without issue, however in the same app I cannot use import * as THREE from 'three' (Specifically the version with the private field, 0.132.0).

Webpack doesn't appear to add support for class fields until 5.36.0ish. (Didn't check if this includes private fields or not.)
Using last 1 chrome or chrome 72 for browserslist doesn't make a difference.
Using the yarn.lock as it is created by CRA or running yarn upgrade doesn't change much. The error is different, but that's about it.

Failed to compile.

./node_modules/three/build/three.module.js
SyntaxError: /Users/nrayburn/Desktop/private-class-used/node_modules/three/build/three.module.js: Support for the experimental syntax 'classPrivateProperties' isn't currently enabled (7690:2):

  7688 | class Material extends EventDispatcher {
  7689 |
> 7690 |        #alphaTest = 0;
       |        ^
  7691 |
  7692 |        constructor() {
  7693 |

Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
If you want to leave it as-is, add @babel/plugin-syntax-class-properties (https://git.io/vb4yQ) to the 'plugins' section to enable parsing.


error Command failed with exit code 1.

Related links.
CRA process the application code first, then process any dependencies code differently. (Note the comment on line 442.)

// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
presets: [
[
require.resolve('babel-preset-react-app'),
{
runtime: hasJsxRuntime ? 'automatic' : 'classic',
},
],
],
// @remove-on-eject-begin
babelrc: false,
configFile: false,
// Make sure we have a unique cache identifier, erring on the
// side of caution.
// We remove this when the user ejects because the default
// is sane and uses Babel options. Instead of options, we use
// the react-scripts and babel-preset-react-app versions.
cacheIdentifier: getCacheIdentifier(
isEnvProduction
? 'production'
: isEnvDevelopment && 'development',
[
'babel-plugin-named-asset-import',
'babel-preset-react-app',
'react-dev-utils',
'react-scripts',
]
),
// @remove-on-eject-end
plugins: [
isEnvDevelopment &&
shouldUseReactRefresh &&
require.resolve('react-refresh/babel'),
].filter(Boolean),
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
compact: isEnvProduction,
},
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
{
test: /\.(js|mjs)$/,
exclude: /@babel(?:\/|\\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
// @remove-on-eject-begin
cacheIdentifier: getCacheIdentifier(
isEnvProduction
? 'production'
: isEnvDevelopment && 'development',
[
'babel-plugin-named-asset-import',
'babel-preset-react-app',
'react-dev-utils',
'react-scripts',
]
),
// @remove-on-eject-end
// Babel sourcemaps are needed for debugging into node_modules
// code. Without the options below, debuggers like VSCode
// show incorrect code and set breakpoints on the wrong lines.
sourceMaps: shouldUseSourceMap,
inputSourceMap: shouldUseSourceMap,
},
},

CRA plugins for dependencies.

plugins: [
// Disabled as it's handled automatically by preset-env, and `selectiveLoose` isn't
// yet merged into babel: https://github.com/babel/babel/pull/9486
// Related: https://github.com/facebook/create-react-app/pull/8215
// [
// require('@babel/plugin-transform-destructuring').default,
// {
// // Use loose mode for performance:
// // https://github.com/facebook/create-react-app/issues/5602
// loose: false,
// selectiveLoose: [
// 'useState',
// 'useEffect',
// 'useContext',
// 'useReducer',
// 'useCallback',
// 'useMemo',
// 'useRef',
// 'useImperativeHandle',
// 'useLayoutEffect',
// 'useDebugValue',
// ],
// },
// ],
// Polyfills the runtime needed for async/await, generators, and friends
// https://babeljs.io/docs/en/babel-plugin-transform-runtime
[
require('@babel/plugin-transform-runtime').default,
{
corejs: false,
helpers: areHelpersEnabled,
// By default, babel assumes babel/runtime version 7.0.0-beta.0,
// explicitly resolving to match the provided helper functions.
// https://github.com/babel/babel/issues/10261
version: require('@babel/runtime/package.json').version,
regenerator: true,
// https://babeljs.io/docs/en/babel-plugin-transform-runtime#useesmodules
// We should turn this on once the lowest version of Node LTS
// supports ES Modules.
useESModules: isEnvDevelopment || isEnvProduction,
// Undocumented option that lets us encapsulate our runtime, ensuring
// the correct version is used
// https://github.com/babel/babel/blob/090c364a90fe73d36a30707fc612ce037bdbbb24/packages/babel-plugin-transform-runtime/src/index.js#L35-L42
absoluteRuntime: absoluteRuntimePath,
},
],
].filter(Boolean),

CRA plugins for application code.

plugins: [
// Strip flow types before any other transform, emulating the behavior
// order as-if the browser supported all of the succeeding features
// https://github.com/facebook/create-react-app/pull/5182
// We will conditionally enable this plugin below in overrides as it clashes with
// @babel/plugin-proposal-decorators when using TypeScript.
// https://github.com/facebook/create-react-app/issues/5741
isFlowEnabled && [
require('@babel/plugin-transform-flow-strip-types').default,
false,
],
// Experimental macros support. Will be documented after it's had some time
// in the wild.
require('babel-plugin-macros'),
// Disabled as it's handled automatically by preset-env, and `selectiveLoose` isn't
// yet merged into babel: https://github.com/babel/babel/pull/9486
// Related: https://github.com/facebook/create-react-app/pull/8215
// [
// require('@babel/plugin-transform-destructuring').default,
// {
// // Use loose mode for performance:
// // https://github.com/facebook/create-react-app/issues/5602
// loose: false,
// selectiveLoose: [
// 'useState',
// 'useEffect',
// 'useContext',
// 'useReducer',
// 'useCallback',
// 'useMemo',
// 'useRef',
// 'useImperativeHandle',
// 'useLayoutEffect',
// 'useDebugValue',
// ],
// },
// ],
// Turn on legacy decorators for TypeScript files
isTypeScriptEnabled && [
require('@babel/plugin-proposal-decorators').default,
false,
],
// class { handleClick = () => { } }
// Enable loose mode to use assignment instead of defineProperty
// See discussion in https://github.com/facebook/create-react-app/issues/4263
// Note:
// 'loose' mode configuration must be the same for
// * @babel/plugin-proposal-class-properties
// * @babel/plugin-proposal-private-methods
// * @babel/plugin-proposal-private-property-in-object
// (when they are enabled)
[
require('@babel/plugin-proposal-class-properties').default,
{
loose: true,
},
],
[
require('@babel/plugin-proposal-private-methods').default,
{
loose: true,
},
],
[
require('@babel/plugin-proposal-private-property-in-object').default,
{
loose: true,
},
],
// Adds Numeric Separators
require('@babel/plugin-proposal-numeric-separator').default,
// Polyfills the runtime needed for async/await, generators, and friends
// https://babeljs.io/docs/en/babel-plugin-transform-runtime
[
require('@babel/plugin-transform-runtime').default,
{
corejs: false,
helpers: areHelpersEnabled,
// By default, babel assumes babel/runtime version 7.0.0-beta.0,
// explicitly resolving to match the provided helper functions.
// https://github.com/babel/babel/issues/10261
version: require('@babel/runtime/package.json').version,
regenerator: true,
// https://babeljs.io/docs/en/babel-plugin-transform-runtime#useesmodules
// We should turn this on once the lowest version of Node LTS
// supports ES Modules.
useESModules,
// Undocumented option that lets us encapsulate our runtime, ensuring
// the correct version is used
// https://github.com/babel/babel/blob/090c364a90fe73d36a30707fc612ce037bdbbb24/packages/babel-plugin-transform-runtime/src/index.js#L35-L42
absoluteRuntime: absoluteRuntimePath,
},
],
isEnvProduction && [
// Remove PropTypes from production build
require('babel-plugin-transform-react-remove-prop-types').default,
{
removeImport: true,
},
],
// Optional chaining and nullish coalescing are supported in @babel/preset-env,
// but not yet supported in webpack due to support missing from acorn.
// These can be removed once webpack has support.
// See https://github.com/facebook/create-react-app/issues/8445#issuecomment-588512250
require('@babel/plugin-proposal-optional-chaining').default,
require('@babel/plugin-proposal-nullish-coalescing-operator').default,
].filter(Boolean),

Webpack Class Fields PR
webpack/webpack#13235

@nrayburn-tech
Copy link

nrayburn-tech commented Sep 15, 2021

It looks like there are a few other issues open which share this same issue. Is it worth just processing all code through Babel? Maybe an option to configure it?

#11410
#11434
#9908
#11132

@marcofugaro
Copy link
Contributor

I think this belongs to a much larger discussion and is more related to #11180.

Bundlers need to be updated regularly. That's the main thing.

@lecoqlibre
Copy link

Hi, forgive my question but I don't understand if we have a solution to this issue?

I can't make the openid-client lib work as expected using CRA:

npx create-react-app my-app
cd my-app
yarn add openid-client

Add the following code to test the lib in src/App.js:

import { Issuer } from 'openid-client';
const googleIssuer = Issuer.discover('https://accounts.google.com');
console.log('Discovered issuer %s %O', googleIssuer.issuer, googleIssuer.metadata);

When I do yarn start I get a Support for the experimental syntax 'classPrivateProperties' isn't currently enabled error in openid-client lib code, complaining about a private property wrote like #propertyName.

The compiler tells me to Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config but I thought CRA was doing it, right?

How can I fix this issue? Thanks.

@stale
Copy link

stale bot commented Jan 8, 2022

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

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

No branches or pull requests

6 participants