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

Allow babelrc: false and/or babel.config.js #2110

Closed
adrienharnay opened this issue Oct 5, 2018 · 26 comments
Closed

Allow babelrc: false and/or babel.config.js #2110

adrienharnay opened this issue Oct 5, 2018 · 26 comments

Comments

@adrienharnay
Copy link

🙋 feature request

Hey,

Since Babel 7, it is common to use a babel.config.js file, or the babelrc: false option.

Why? It allows for modules outside the root dir (e.g. Yarn workspace, symlinked package in node_modules with "source": true in package.json) to be transpiled using the same options as the rest of the code.

🤔 Expected Behavior

Being able to transpile a module with source: true using the .babelrc.js config at the Parcel root.

😯 Current Behavior

The external module is transpiled using Parcel's default babelrc (e.g. no support for experimental syntax classProperties).

Support for the experimental syntax 'classProperties' isn't currently enabled

💁 Possible Solution

Supporting either babelrc: false or babel.config.js. Or maybe both?

🔦 Context

I have a monorepo like so:

repo
- packages
-- service-a
-- util-shared

service-a is compiled with Parcel. util-shared is symlinked in service-a node_modules using Yarn workspaces. Both use the same type of code, and it would be nice to use the same babel config for both.

💻 Examples

I think Context pretty much covers it all, but I would be happy to give more context if needed.

Also, I would be up to implement this but would need some pointers if possible. Thanks in advance!

@kosmotaur
Copy link

Need… this… badly… I'm happy to help out with the code, but would also need some tips where to start. Thank you!

@serv
Copy link

serv commented Oct 19, 2018

We should also mention in the doc that babel.config.js is not supported until it becomes useable for Parcel. I was mistakenly thinking that babel.config.js is supported and realized that babel config changes were not being applied.

@Hotell
Copy link

Hotell commented Oct 19, 2018

Maybe a slight off topic, but same applies for tsconfig.json I guess, should be also added to docs.

@adrienharnay
Copy link
Author

Hey, any news on this? Seems like a few people would like to see it implemented/would be eager to file a PR

@aliai
Copy link

aliai commented Nov 20, 2018

Part of this issue is addressed here #2269 (needs attention 😄). With this PR you can have a single .babelrc or .babelrc.js file in the root directory and your packages (service-a, util-shared) will pick up on that, unless they also have the file themselves in case those packages want to override the project-wide configuration. The same for tsconfig.json.

I think adding support for babel.config.js is a bit more trickier, as you could be able to control different directories settings with one file.

@adrienharnay
Copy link
Author

Hey, thanks for following on this!

As projects grow, a monorepo can have a lot of different projects. Where I work, we have several parcel projects, several React Native projects, and also several web projects that do not use Parcel but Webpack. Sharing a babel config for all of these projects is not doable, but what we have is a configs folder at the root, where we store all of our different configuration files and we specify the one we want to use for each project. This way, we avoid the automatic resolution of babel config by not having a config in the workspace root.

I think resolving the configuration files at the root is a step in the right direction, but I'm not sure it entirely covers this issue. Since we can't specify a babel config to Parcel, we should be able to enforce the one at the project root for all projects, even ones that are symlinked (as the original post describes).

TL;DR: won't fix the case where you don't use a babel config at the workspace root, but you have local babel configs that you want to apply to symlinked dependencies.

@aliai
Copy link

aliai commented Nov 20, 2018

Hey @adrienharnay! Not sure if you are referring to the PR or this issue, sorry if I got it wrong :) Now I see that my PR does not address the exact issue you brought up here (which is support for babel.config.js). I just jumped into conclusion when I saw yarn workspaces.

The problem with yarn workspace (monorepo linked packages) with parcel is that parcel doesn't traverse the folders to get to the root folder, to begin with. It stops at the sub-project level. In your case having a .babelrc.js or .babelrc in your projects' folder should suffice. As you pointed out.

In our monorepo, we made a project to preset all of our babel configurations in one package (without publishing) and use that preset everywhere. Basically, in all of our js project where we need babel compiler, we just drop a .babelrc file in the root of that project and point the preset to the predefined preset project.

@adrienharnay
Copy link
Author

Hey, in any case thanks a lot for the PR, I will try again when it is released and tell you if it satisfied our use case 🙂

@adrienharnay
Copy link
Author

Hey, it feels like this is going stale. Anything anyone interested by this feature could do to help shipping this?

@sanohin
Copy link

sanohin commented Jan 21, 2019

seems like babel.config.js is officially supported https://babeljs.io/docs/en/configuration#babelconfigjs

@newtriks
Copy link

I'm in the position where I wanted to integrate Parcel into a Lerna based project and with Babel 7 in a monorepos setup babel.config.js is recommended https://babeljs.io/docs/en/config-files#monorepos. I'd also love to see this supported by Parcel as dotfiles in every package is not an approach we desire.

@sidroopdaska
Copy link

Any updates on this?

@devongovett
Copy link
Member

Unfortunately, babelrc.config.js makes things very difficult for Parcel's cache. Since it is a JS file rather than static JSON, it can have dependencies, side effects, read files from the filesystem, return different value every time, etc. This basically makes applications that use it completely non-cacheable. In my opinion, allowing JS in configs was a major design mistake.

I am aware that babel has an API to control cacheability of configs, but it isn't really designed for use in a cache that is serialized to disk. It is designed to avoid re-calling the config function, not to avoid re-compiling files. In addition, it is not enabled by default. The API relies on callback functions to determine if the cache should be invalidated, but that only works when the callback can be stored in memory - we cannot serialize it to disk. So when you restart Parcel, we still need to invalidate the cache for every file and recompute the babelrc.config.js. This will make rebuilds much much slower than you are used to with Parcel.

If we support this, we will need to add custom logic to Parcel to disable caching if babelrc.config.js is seen, and probably warn users about why their builds get much slower. I would recommend just using a .babelrc in the root of your monorepo instead of babelrc.config.js. If you can avoid writing JS configs, do.

@akatechis
Copy link

Unfortunately, babelrc.config.js makes things very difficult for Parcel's cache. Since it is a JS file rather than static JSON, it can have dependencies, side effects, read files from the filesystem, return different value every time, etc. This basically makes applications that use it completely non-cacheable. In my opinion, allowing JS in configs was a major design mistake.

While you're probably right that using JS in configs is an anti-pattern (see plugins, tools and design patterns around webpack.config.js merging/extending for evidence), there's a couple use cases that are only possible with dynamic configuration files.

First, the case of extending a base config, using JS syntax to require it, and extend it. Secondly, is to target multiple environments: My own babel config looks something like this:


module.exports = function (api) {
  api.cache(true)

  // tests run in mocha, so we compile those to commonjs
  const modules = process.env.NODE_ENV === 'test'
    ? 'commonjs'
    : false

  // target node when we're running tests, otherwise, browsers
  const targets = process.env.NODE_ENV === 'test'
    ? { node: 'current' }
    : { browsers: 'last 2 versions' }

  const presets = [
    ['@babel/env', {
      targets,
      modules,
      useBuiltIns: 'usage',
    }],
  ]

  return { presets }
}

In our case, we set the NODE_ENV variable to test when we run our tests, as a signal that we're running on node, to change how module syntax is handled. Similarly, our target is adjusted based on whether we're running tests (node) or just building the app (last 2 versions of each browser).

I'd be interested to know if there's some cleaner/better way of handling multiple execution targets.

@alexkrolick
Copy link

alexkrolick commented Mar 5, 2019

FYI - Jest 24 dropped support for Babel 6 and seems to only pick up babel.config.js, not .babelrc. https://jestjs.io/docs/en/getting-started#using-babel

Projects using both Jest and Parcel now have incompatible configurations.

@ctsstc
Copy link

ctsstc commented Mar 7, 2019

I haven't been able to find a way around conditions for configs without having a JS file. This is mainly due to the cli lacking the extensibility, but giving most flexibility through JS which is nice.

@devongovett Just spitballing an idea here, but assuming most people are commonly setting an environment variable that doesn't change after the CLI has been called/ran once. Given that the main babelrc config is JSON I believe that the export should still boil down to JSON; people are just using booleans or strings in their js configs it seems to check against an environment variable. Could we just read the export/evaluate it and JSON'ify it with the assumption that it's then frozen and reused from then on out?

@sanohin
Copy link

sanohin commented Apr 9, 2019

@alexkrolick jest still supports .babelrc as well.

@hellobrian
Copy link

it would be good to update the parcel babel docs to make it really clear that babel.config.js isn't supported.

I was getting errors in my chrome browser console with my production build that said:

Syntax Error Unexpected token <

It wasn't until I found this issue that I finally figured out that I needed to use a .babelrc file.

@adamshaylor
Copy link

@alexkrolick jest still supports .babelrc as well.

Jest does not support .babelrc when testing ES modules with ES module dependencies. See jestjs/jest#6229.

@posidron
Copy link

I solved it in Jest with:

  globals: {
    'babel-jest': {
      useBabelrc: true
    }
  }

@jamesguan
Copy link

I am running into this issue as well, trying to migrate an old project from webpack but this would cause a whole reconfiguration and would be difficult to set configurations depending on environment. Is this going to be a supported feature in the future to support js files for configuration?

@devongovett
Copy link
Member

This will be supported in Parcel 2, though it will warn in some sub-optimal scenarios that are possible with JS-based configs. See #3261 for the in progress PR.

@joeyhub
Copy link

joeyhub commented Sep 3, 2019

babel.config.js is just another build asset.

Using static files is not an alternative to using dynamic scripts for configuration. What you have to do with static files is unroll everything.

Even with a static file hack, I'd still have something like npm -e 'JSON.stringify(require("./babel.config.js")());' > .babelrc.

The NPM config interface can be a bit annoying in combination with the documentation but what a lot of people really want is just to deduplicate. In those cases it's unlikely the config has or needs to rely on embedding data types incompatible with JSON in the configuration.

A very common case is that people use the JS format for different environments. Babel's JSON format has support for with with the env key where per env overrides can be applied. It's not always DRY but will be more DRY than having to have multiple files.

@tofishes
Copy link

Babel 7 only use babel.config.js to compile node_modules , but parcel support .babelrc , how to resolve this case ?

@DeMoorJasper
Copy link
Member

@tofishes parcel 2 supports babel.config.js.

Also if the package’s browserlist doesn’t match the one of your application it transpiles that module to your projects target

Sent with GitHawk

@devongovett
Copy link
Member

Closing this. Parcel 2 supports all standard babel config options. However, when you use babel.config.js we do bail out on caching and you will need to restart parcel each time you make a change to the config and rebuilds may be slower. We contributed support for babel.config.json to babel and recommend using that instead if possible for better perf.

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