Babel: Are you open to allowing .babelrc.js?

Created on 1 Oct 2016  路  33Comments  路  Source: babel/babel

The only place I saw "I'd like to use JavaScript inside .babelrc is here: #4449, so I am opening a proper issue about .babelrc.js.

Expected Behavior

I would like to be able to provide:

.babelrc.js

module.exports = {
  plugins: [
    ["babel-plugin-transform-cool", {
      isCool: maybe => maybe ? 'yes' : 'no';
    }]
  ]
};

And use the isCool option in the plugin like so: state.opts.isCool(true);

Current Behavior

.babelrc only allows for JSON.

Possible Solution

Use babel-core programmatically, this allows for any type of option (which may be seen as non-consistent with .babelrc).

Context

ESLint allows this, I find it easier to reason about configuration files when they are written with JavaScript: comments, easy customization with ENV variables, no context switch (This is JavaScript).

PR outdated

Most helpful comment

I have a bit OCD. >_<

JSON doesn't support trailing comma.
So I always use js format config files. e.g. .eslintrc.js

module.exports = {
  plugins: [],
  extends: [
    'airbnb'
  ],
  rules: {
    'func-names': 1,
    'prefer-spread': 1,
    'strict': 0,
  },
  env: {
    node: true,
  }
};

+1 for .babelrc.js
please at least support .babelrc.js like that.

All 33 comments

Side note, this is doable for now by providing a string configuration linking to a JavaScript configuration file to be used: https://github.com/FormidableLabs/babel-plugin-transform-define#quick-start

But then you are subject to relative => absolute issue (how to resolve the file, from where?).

Yeah workaround for now is you can like just require a string that is the js file you want or you can make a preset that is a js file

The fact that you can't tell .babelrc where to resolve from first is always popping up in our projects. We are trying to move all (most) js related configs/transforms/plugins to babel from webpack but this is the one thing stopping us every time. Having a babelrc.js file would be more than great! :)

@vvo I'm actually here because I wanted to use that plugin. I'm refactoring some things to test babel-register but yes. +1 for babelrc.js

I have a bit OCD. >_<

JSON doesn't support trailing comma.
So I always use js format config files. e.g. .eslintrc.js

module.exports = {
  plugins: [],
  extends: [
    'airbnb'
  ],
  rules: {
    'func-names': 1,
    'prefer-spread': 1,
    'strict': 0,
  },
  env: {
    node: true,
  }
};

+1 for .babelrc.js
please at least support .babelrc.js like that.

@tommytroylin I believe we already use JSON5 to parse, which allows trailing commas. On mobile so can't verify atm, though.

That's correct, .babelrc uses JSON5 so you can use trailing commas, comments, single quotes, an unquoted keys.

+1 for .babelrc.js, which would remove the need for hacky presets like babel-preset-es2015-maybe-webpack.

My use case for .babelrc.js:

I'm trying to configure babel/babel-preset-env with just browserslist file. So far preset does not fall back to default browserslist package behavior (which is: if no browsers query is provided try reading browserslist file from the root of the project) but there's a PR for that (https://github.com/babel/babel-preset-env/pull/51).

I thought it would be possible just to import contents of the browserslist file and pass it in .babelrc.js (at least until https://github.com/babel/babel-preset-env/pull/51 is meged) but right now it's not supported. Best I can do is to extend babel config inside webpack.conf.js and leave myself a comment in .babelrc to remember there's a second place where babel configuration is done OR duplicate entries across my browserslist file and .babelrc file. Either way there's duplication.

I suggest designing it like post-css's postcss.config.js file.

More use cases: Only running things when certain contexts are set. Changing config options based on environment, or context of the compile.

For example, I have one folder I don't want to enable react-css-modules on. So right now im having to do in webpack

const babelConfig = (useModules) => {
        const conf = {
            cacheDirectory: isProduction ? null : '.cache/babel',
            "presets": [
                ["es2015", {"loose": true}],
                "react",
                "stage-2"
            ],
            plugins: ['transform-runtime'],
            babelrc: false,
        };

        if (useModules) {
            conf.plugins.push([
                "react-css-modules",
                {
                    filetypes: {
                        ".less": "postcss-less",
                    },
                    allowMultiple: true,
                    generateScopedName: cssPattern
                }
            ]);
        }
        return JSON.stringify(conf);
    };
....
            {
                test: [/\.(js|jsx)$/],
                exclude: /(node_modules|other-folder)/,
                loader: 'babel?' + babelConfig(true),
            },
            {
                test: [/\.(js|jsx)$/],
                include: /other-folder/,
                exclude: /(node_modules)/,
                loader: 'babel?' + babelConfig(false),
            },

Since I'm on webpack1, i wanted to try passing a function to the react-css-modules generatedScopeName, and figured doing it in babelrc could of helped get around the webpack1 options limitation (has to be stringified), but I needed the conditional configurations still so it wasn't possible.

Are there any good reasons a JavaScript library, created to work with JavaScript doesn't want to accept JavaScript as configuration? 馃樃

Because it can make the config more complicated then it needs to be and maybe the interaction of different presets/inherited ones have conflicts. Every new feature has tradeoffs. I think we still to do this but its not just as simple as adding it and hoping nothing else breaks or has issue?

Doesn't babel have a node API that allows you to run babel with a "javascript" object?

Yeah you can already reference another js file in your .babelrc, or just use babel-core/babel-loader to use javascript atm.

Yup, we all know. We just don't understand how come making .babelrc a javascript file that exports the configuration object would be complicated. It seems to me that I can just encapsulate babel-core and provide that feature already.

@anilanar Providing this features is not a big technical problem. "Complexity" means not hard to implement, but hard to understand for others. Most of the features provided in examples ahead already could be implemented with bundler (like webpack). Moreover, you can already specify environment and use different plugins/presets for dev, prod, test, etc.
Imagine your project with 50+ lines babelrc.js + 80+ lines webpack.config.js with contradictory declarations.
After preset-env release, we could think about config minimization, but not ground for demonstration javascript power.

@hzoo The problem with that in my case was where the file is being resolved from...

@yavorsky not everybody is bundling code with babel...

Sacrificing babel power because you don't trust people who use it is not a good enough reason to not support js as config file. But that is just my opinion... I do think babel should have an easy way to be used but also advanced enough for those who want... The nature of babel is advanced. It's touching your code and transforming it to something totally else in most cases... I just want more control over that.

Most people would just use the json form of config. Babel could tell people to use js at their own risk...

Most of the time when I've run to the need to use js as config problem. It has just made me do something else and most often it's a shitty "hack" that is fragile and tiering to maintain for all teams

But this is not as big of a deal for us right now because this has made us minimizing babel usage to as little as possible and going other ways

EDIT: It's not because we don't like babel. It is one of the reason my job got fun again... But we are just needing it less and less

Considering most other systems comparative to babel support js based configs, i think more would expect it to support it than be confused by it.

It's also not babels place to dictate how "complex" ones config is/should be.

it should support exporting a function too (and even supporting a Promise as webpack2 added also) would be ideal.

promise api allows async retrieval of information in order to populate the configuration, and not

But ultimately, babel should use babel.config.js for js support (to be consistent with many other projects who use config files in this style), and leave .babelrc as-is.
This would be "Familiar"

JS vs JSON vs JSON5 vs YAML vs ...

This is something that always comes up as a frustration for config files with any javascript related OSS. Everyone always ends up wanting an option to use JS. Considering babel currently does not have an ability to dynamically specify config's beyond "env" - I think this is a widely desired feature.

This issue is vividly shown when you're using babel for an isomorphic app that needs far more conditional configs because "env" does not cover the need to configure your "node" and "browser" build targets separately. Neither does babel-preset-env, sadly.

I don't see what JSON offers over JS here; there is no hard requirement
for .babelrc to be wire-serializable - so why not?

5276 Has some discussion of dynamic configuration per-environment for 7.x too.

You can write your .babelrc.js and load it in your normal .babelrc file (tested on Linux):

{
  "presets": ["./.babelrc.js"]
}

Edit: Ok, you'd better not call it .babelrc.js, but babel-preset.js, for example.
https://babeljs.io/docs/plugins/#creating-a-preset

@doasync That is not correct. Creating a preset and calling it a .babelrc is just misleading. You can certainly make a preset that set configuration, like you would in a .babelrc, but .babelrc.js files can do things that presets can't, and they have different caching behavior in some cases.

If you want to make a preset in Babel 6 for this, by all means, but just call it a preset. It is not a .babelrc at that point.

@loganfsmyth I just meant that it's kinda possible to use JS for the config file. Thank you for your clarification.

I don't really get why anyone designs a JS tool to use a static configuration file nowadays. It's so easy to load configuration from a JS module. Is it just because people with a lot of experience working in non-interpreted langs are so used to using static files for configuration?

@jedwards1211 I'm not sure to understand your point. The Babel JavaScript configuration is now available in Babel 7.

@xtuc ah good. I was mainly commenting that I'm surprised the authors didn't make that the primary form of configuration file from the start.

But really, I wish I could configure babel with XML 馃槅

@xtuc so any doc for using babel with javascript configuration?

I just realized that we are lacking a bit of documentation about that sorry. You can refer to the JSON format http://babeljs.io/docs/usage/babelrc/ it's the same configuration. You just need to export it module.exports = {...};

Just to confirm, JS config files are only supported in beta, not in version 6, right?

@jedwards1211 yes that's right

Just a note for anyone trying to use this with babel 7 -- you need to name your file babel.config.js to get this to work, apparently. I tried .babelrc.js which was my intuition, but that didn't work. FWIW.

@jaredh159 That is a separate feature, but may well address your issue in cases where .babelrc.js would not.

Was this page helpful?
0 / 5 - 0 ratings