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

How to add babel-polyfill #3314

Closed
baseten opened this issue Dec 22, 2017 · 10 comments
Closed

How to add babel-polyfill #3314

baseten opened this issue Dec 22, 2017 · 10 comments

Comments

@baseten
Copy link

baseten commented Dec 22, 2017

I'm using redux-saga in my gatsby app and therefore generator functions. These are causing errors in IE11 and it seems like babel isn't polyfilling them. I've been trying different techniques for including babel-polyfill but none seem to work, both of these seem relevant but don't solve my issue:

#341
#2177

I'm trying to do the following, but still having the same error in IE. Is there a preferred approach for solving this?

if ( stage === 'build-javascript' || stage === 'develop' ) {
    config._config.entry.commons.unshift( 'babel-polyfill' );
}
@KyleAMathews
Copy link
Contributor

Are you trying to require babel-polyfill? Or add it to the babel config?

For the 1st, require it in your layouts/index.js file or gatsby-browser.js.

For the later, add it to a .babelrc in the root of your site.

@baseten
Copy link
Author

baseten commented Dec 27, 2017

I had already imported babel-polyfill in gatsby-browser.js. The problem, it turns out, was a bit more complex and exposed a couple of other issues. These are happening with gatsby 1.9.149:

  • In order to use generators we need babel's transform-regenerator plugin, which is explicitly excluded in gatsby's babel-config.js. It's possible to get around this using the modifyBabelrc api. I found the easiest thing to do here was just to replicate all the config created by babel-config.js in my .babelrc.
  • This showed up another issue which I think other people have noticed. As babel-config.js loads in the project's .babelrc, we end up with duplicate presets and plugins. I also normalized this in modifyBabelrc.
  • I specifically left out targets.browsers from my .babelrc as I was reading them from package.json and adding them in during modifyBabelrc. However when running babel-preset-env with debug mode, it became apparent these values were being ignored during build. It turns out there was another clash with the project .babelrc in webpack's babel-loader, which was defaulting to the .babelrc values over the values provided to query. There is a specific option to turn this off, which I did in the modifyWebpackConfig api. I don't think this is done internally with gatsby, so this is potentially causing issues with anyone using a .babelrc file. It's not obvious unless you run debug mode for babel-preset-env. I suspect it only means there are potentially more polyfills included than necessary, depending on the browserslist.

The relevant parts of my final gatsby-node.js looked like this. Obviously this isn't a totally general solution:

const packageJson = require( './package.json' );
const rawBabelRc = JSON.parse( fs.readFileSync( './.babelrc' ) );

exports.modifyBabelrc = ( { babelrc } ) => {
    // remove duplicates
    babelrc.plugins = _.uniq( babelrc.plugins );
    babelrc.presets = babelrc.presets.slice( 0, rawBabelRc.presets.length );

    const envIndex = babelrc.presets.findIndex( preset => {
        return _.isArray( preset ) && preset[ 0 ].indexOf( 'babel-preset-env' ) > -1;
    } );

    const rcEnvOptions = babelrc.presets[ envIndex ][ 1 ];

    rcEnvOptions.targets = {
        browsers: packageJson.browserslist
    };

    return babelrc;
};

exports.modifyWebpackConfig = ( { config } ) => {

    const query = Object.assign( {}, config._loaders.js.config.query, {
        babelrc: false
    } );

    config
        .removeLoader( 'js' )
        .loader( 'js', {
            test: /\.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel',
            query
        } );

    return config;
};

.babelrc:

{
  "plugins": [
    "babel-plugin-add-module-exports",
    "babel-plugin-transform-object-assign"
  ],
  "presets": [
    [
      "env",
      {
        "debug": true,
        "loose": true,
        "uglify": true,
        "modules": "commonjs",
        "useBuiltIns": true,
        "exclude": [
          "transform-es2015-typeof-symbol"
        ]
      }
    ],
    "babel-preset-stage-0",
    "babel-preset-react"
  ]
}

@Kalcode
Copy link

Kalcode commented Jan 3, 2018

In the very top of my gatsby-browser.js file i have

import 'babel-polyfill'

is the very first line in that file.

Then in gatsby-node.js I added 'transform-regenerator'

exports.modifyBabelrc = ({ babelrc }) => ({
  ...babelrc,
  plugins: babelrc.plugins.concat(['transform-decorators-legacy', 'transform-regenerator']),
})

The 'transform-decorators-legacy' is not needed. Just showing you the exact working copy I use.

IE 11 and Edge work fine with Redux-Saga now, Saga uses generators for their side-effects.

Hope this helps.

@baseten
Copy link
Author

baseten commented Jan 3, 2018

@Kalcode thanks for this. I think the additional complexity for me comes from using a .babelrc file. I need this for unit testing with jest, otherwise I can see how providing the whole config with code would be much simpler.

Incidentally, I ended up adding the babel-polyfill to the entry array for webpack config and removing from gatsby-browser.js because otherwise I was coming up against this bug when testing in develop mode in IE11. I found that babel-polyfill had to come before react-hot-loader.

@youfoundron
Copy link
Contributor

@Kalcode your setup seems to be working for me, however I get a redux hot-reloading error message in the console

<Provider> does not support changing 'store' on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically.

Is this happening for you as well?

@Kalcode
Copy link

Kalcode commented Jan 16, 2018

@rongierlach That shouldn't have anything to do with the polyfills.

But yah redux needs a way to reload it's reducers. Gatsby is firing off a re-render higher up and redux is saying it doesn't do it auto-magically anymore.

Typically we'd use hot module replacement somewhere and have the reducers passed in again via dynamic import. I don't think Gatsby is using hot module replacement so I don't think module.hot is available.

But when you are making changes that you need to reinitiate the state of your stores you just need to refresh or you can watch for componentWillUpdate on the ones your are testing and reset stuff yourself.

https://github.com/reactjs/react-redux/releases/tag/v2.0.0

Edit: Actually it does use HMRin theory you can use module.hot to reload your reducers. I thought I tried it and it didn't seem to work. YMMV

@youfoundron
Copy link
Contributor

@Kalcode so is the error a symptom of using redux with gatsby and changing certain files -- or something being messed up in my redux integration?

@Kalcode
Copy link

Kalcode commented Jan 16, 2018

It's a symptom of using the Redux 2.0. Not gatsby.

The link above describe the change redux did.

You need to manually handle the hot reloading of redux now. How you do that is up to you.

The error is only relevant during development. It's not breaking it just doesn't understand hot reloading during development.

I've developed different redux connected components with no issues. If your store reducers changes just refresh the browser and continue developing.

You only need to refresh when you.change your actual reducers code or you need to reset to an initial state inside the reducers.

This isn't a gatsbyjs issue.

@m-allanson
Copy link
Contributor

m-allanson commented Mar 20, 2018

Closing this as there's no further action to be taken here. Please re-open or create a new issue if I'm wrong!

@fabe
Copy link
Contributor

fabe commented Jun 25, 2018

I had a hard time getting the intersection-observer polyfill working, ended up using this in the component where it's needed:

// Intersection Observer polyfill
if (typeof window !== `undefined` && !window.IntersectionObserver) {
  require('intersection-observer');
}

Didn't seem to work inside gatsby-browser.js or gatsby-node.js with Gatsby v2 🤷‍♂️

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

No branches or pull requests

6 participants