Skip to content

Support custom babel presets & plugins via environment variables #900

Closed

Description

@philiptzou

Hello, I found an easy way to enable additional presets & plugins in my fork of react-scripts. I want to share it with others and the maintainer of this original repository may find this feature useful and add it to the main react-scripts.

Basically, what I did was just introducing two environment variables BABEL_PRESETS and BABEL_PLUGINS, which accept JSON encoded list of path strings. Users can enable any kind of presets/plugins by specify those two variables before they run npm start.

For example, I need to enable react-relay support. What I did is just execute this command before I start the development server:

export BABEL_PLUGINS="[\"`pwd`/plugins/relay-plugin.js\"]"

With my forked react-scripts (@philiptzou/react-scripts) and other related relay packages installed, the webpack server is able to handle Relay.QL syntax now.

I just noticed that we can use .env file to specify REACT_APP_ initial variables. It maybe a more elegant way to do this in the future.

Activity

  1. changed the title [-]Support custom babel presets & plugins via environment variables?[/-] [+]Support custom babel presets & plugins via environment variables[/+] on Oct 13, 2016
  2. gaearon commented on Oct 13, 2016

    @gaearon
    Contributor

    Hi, thanks for the issue!

    We have decided to punt on custom Babel plugins in the close future. This is more of an advanced use case, and it will be hard for us to guarantee compatibility with this while shipping new features.

    We will likely reevaluate this position some time next year, but now is not the time yet.
    See also discussion in #462.

  3. nylen commented on Nov 17, 2016

    @nylen

    This is possible to achieve today, though definitely unsupported. Automattic/wp-api-console#45 (comment) is an example for a production build, and it looks like something similar would work for the dev server too.

  4. gaearon commented on Nov 20, 2016

    @gaearon
    Contributor

    It's frustrating people don't reach out to us first with their use cases. I'd be happy to get Automattic/wp-api-console#45 (comment) in.

  5. spudly commented on Dec 2, 2016

    @spudly
    Contributor

    My 2¢:

    I would love to have the ability to add custom presets. At the moment, my only option is to fork the repo. I also understand why you would want to wait to implement something like this.

    When you are ready to support something like this, I'd like it to just let me configure babel the way I do in all my other projects (using the babel key in package.json, or a .babelrc file).

    Would you (eventually) accept a pull request that would make the webpack config file autodetect a .babelrc or package.json/babel key and (if detected), use that config instead of babel-preset-react-app?

  6. gaearon commented on Dec 5, 2016

    @gaearon
    Contributor

    What is the reason you don't want to use Webpack directly in this case?

  7. spudly commented on Dec 5, 2016

    @spudly
    Contributor

    Because I don't want to override the webpack config completely, just the Babel config.

    That's why I suggest that we could just allow Babel to use the .babelrc if it exists. If it doesn't exist, it'll continue to use the default preset.

  8. philiptzou commented on Dec 5, 2016

    @philiptzou
    Author

    Using .babelrc is more gentle and friendly than my above solution. And we can still have the default settings for everyone who doesn't want or need customizations.

  9. added a commit that references this issue on Mar 13, 2017
  10. danielkcz commented on Sep 18, 2017

    @danielkcz

    Hey, @gaearon. Sorry for reviving the old issue. Strangely enough, I wasn't able to find anything new and relevant. Based on your #900 (comment) above is it already time to reevaluate this? :)

    I am used to using babel plugin transform-export-extensions in almost every of my project. I am well aware it's in stage 1 for a very long time now, but I still want to use it.

    Feels odd I would need to eject just to add one small plugin. So what is your stance on this after one year? :)

    Btw Create-React-Native-App supports using .babelrc :) I know it's whole different story there, but I just felt that comparison is in place :)

  11. anon-r-7 commented on Sep 19, 2017

    @anon-r-7

    @gaearon +1 For babelrc support; this seems like it might be standard functionality. I'd like to be able to use the following babel plugins:

    "transform-class-properties",
    "syntax-decorators",
    "transform-decorators-legacy"
    

    And a use case for transform-decorators-legacy: let's say you are using three wrappers on a given component, as such:

    import React from 'react'
    ...
    
    class Component {...}
    export default connect((state) => {
      someProp: state.someProp,
      otherProp: state.otherProp,
    }, ReactForm(Radium(Component)))
    

    This starts to get really difficult to read -- and also forces us to include these statements near the bottom. It's much cleaner to use the new babel decorator, like so:

    import React from 'react'
    ...
    @connect((state) => {
      someProp: state.someProp,
      otherProp: state.otherProp,
    })
    @ReactForm()
    @Radium()
    
    class Component {...}
    export default class Component
    

    A much cleaner solution, and it includes our wrappers near the top where we know what's going on from the get go. So now we can call a given action like so:

    someFunction() {
      const { dispatch } = this.props.dispatch
      dispatch(someReduxAction())
        .then(() => { this.someFunctionAfterDispatch() })
    }
    

    Using dispatch to call our actions is a much cleaner approach in general, and we get the added benefit of getting to call then() on the dispatch. It also makes our code easier to read. Rather than having this.props everywhere for all our actions, we can look for our actions with the dispatch action. But this is only possible, to my knowledge, with something like a decorator -- which to my knowledge, is only available with transform-decorators-legacy, which to my knowledge is only available through .babelrc plugins object.

    Feel free to shoot some holes in this. My example isn't intended to be exhaustive -- just wanted to give one very clear example of how having access to this functionality helps improve a project dramatically with a very lightweight implementation of babelrc config.

  12. anon-r-7 commented on Sep 19, 2017

    @anon-r-7

    @FredyC An alternate solution until .babelrc configuration is available is to install the babel package manually and specify it in your package.json babel object. Like so:

    npm install --save babel-plugin-name-of-plugin

    And in package.json under babel add the following:

    "plugin"": [ "name-of-plugin" ], @

  13. danielkcz commented on Sep 20, 2017

    @danielkcz

    @ryanostrom Regarding a need for decorators, consider approach I've described in my short article. Decorators are not really needed not even mentioning they tightly couple your component to some other stuff and make it harder to test. But this issue is hardly placed to talk about that. Feel free to comment on my article instead.

    I don't understand why are you calling for support of .babelrc when you are convinced that adding it to package.json works the same way. I tried it and doesn't work for me. If it would work this issue would not be necessary.

  14. anon-r-7 commented on Sep 20, 2017

    @anon-r-7

    @FredyC thanks for the additional info, I'll take a look at your article.

    I just tested this functionality yesterday and did find that adding it in package.json does work if you install the corresponding babel package via npm as well. I find it a cumbersome solution because it requires that you install an individual npm package for each and every babel plugin that you want -- whereas with babelrc it's a little more automatic. And I'm not convinced that every configuration that you get in babelrc would also work in package.json (although I haven't thoroughly tested). Here's a snippet from my package.json file:

      "babel": {
        "plugins": [
          "transform-class-properties",
          "syntax-decorators",
          "transform-decorators-legacy"
        ],
        "presets": [
          "react-app"
        ]
      },
      "devDependencies": {
        "babel-plugin-syntax-decorators": "^6.13.0",
        "babel-plugin-transform-class-properties": "^6.24.1",
        "babel-plugin-transform-decorators-legacy": "^1.3.4",
      }
    
  15. danielkcz commented on Sep 20, 2017

    @danielkcz

    I find it a cumbersome solution because it requires that you install an individual npm package for each and every babel plugin that you want -- whereas with babelrc it's a little more automatic.

    I don't understand. Automatic how? How would specifying something in .babelrc know what version of a plugin you want to install and use? :) I think you have been misled somewhere along the path ;) Or you just got lucky because some other dependency has installed plugins you have specified there. Either way, every babel plugin needs to be installed with NPM (or Yarn).

  16. locked and limited conversation to collaborators on Jan 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions