Skip to content

Instantly share code, notes, and snippets.

@Couto
Last active November 11, 2020 17:53
Show Gist options
  • Save Couto/b29676dd1ab8714a818f to your computer and use it in GitHub Desktop.
Save Couto/b29676dd1ab8714a818f to your computer and use it in GitHub Desktop.
Fetch polyfill with webpack
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
var folders = {
APP: path.resolve(__dirname, '../app'),
BUILD: path.resolve(__dirname, '../build'),
BOWER: path.resolve(__dirname, '../bower_components'),
NPM: path.resolve(__dirname, '../node_modules')
};
var config = {
entry: {
app: [
'webpack/hot/dev-server',
"./js/app.js"
]
},
debug: true,
resolve: {
extensions: ['', '.js', '.jsx', '.scss'],
alias: {
//'es6-promise': path.join(folders.NPM, 'es6-promise', 'es6-promise.js'),
//'fetch': path.join(folders.NPM, 'whatwg-fetch', 'fetch.js'),
}
},
stats: {
colors: true,
reasons: true,
},
output: {
path: __dirname + '/build',
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].js'
},
module: {
loaders: [
{
test: /\.s?css$/,
exclude: /node_modules/,
loaders: [
'style',
'css',
'autoprefixer?browsers=last 2 version',
'sass?' + ['outputStyle=nested'].join('&')
]
},
{ test: /\.jsx?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /\.json$/, loader: 'json' },
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.ProvidePlugin({
'Promise': 'es6-promise', // Thanks Aaron (https://gist.github.com/Couto/b29676dd1ab8714a818f#gistcomment-1584602)
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
}),
//new webpack.optimize.CommonsChunkPlugin('app', null, false),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: path.resolve('./', 'index.html'),
webpackDevServer: '/webpack-dev-server.js'
})
]
};
module.exports = config;
@OliverJAsh
Copy link

Unfortunately this means even new browsers will use the Promise polyfill 😢

@OliverJAsh
Copy link

My mistake, that's intended: stefanpenner/es6-promise#148

@silvenon
Copy link

@finbarmaginn I was wondering the same thing, but I think you have the benefit of deciding when to polyfill based on the environment. E.g. you probably don't want to polyfill promises when testing in Node.js because newer versions support them.

@gbrassey
Copy link

gbrassey commented Jan 7, 2016

Is this still the preferred method to polyfill Promise and does it cause any errors? re: https://github.com/babel/babel-loader#custom-polyfills-eg-promise-library

@Nosherwan
Copy link

I am curious just today I have learned that at least in babel 6 there is a 'babel-polyfill' (provides es6 env) that can be imported via the entry option in webpack.config.js like so:

var path = require('path');
var webpack = require('webpack');

module.exports = {
  entry: [
    'babel-polyfill',
    './src/main'
  ],
  output: {
      publicPath: '/',
      filename: 'main.js'
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        test: /\.js$/,
        include: path.join(__dirname, 'src'),
        loader: 'babel-loader',
        query: {
          presets: ["es2015","react"],  
        }
      }
    ]
  },
  debug: true
};

Would this not make es6-promise polyfill redundant, and maybe it is smart enough to use browser implementation if provided?

@silvenon
Copy link

Was wondering the same thing…

@nickjanssen
Copy link

babel-polyfill does not appear to include a fetch polyfill, so you'd still need to use this.

@tarikjn
Copy link

tarikjn commented May 18, 2016

Wouldn't simply including it in entry be a better approach? There is actually a use case where the demonstrated method will fail, for example if you use Webpack server side with externals: [nodeExternals()], you would be forced to use entry anyways because external modules would not see fetch as being defined. So it seems it would be more consistent to use entry here as well.

@tarikjn
Copy link

tarikjn commented May 19, 2016

After double checking, this approach is actually incorrect and will not polyfill fetch properly, the correct approach is to configure whatwg-fetch on your Webpack entry configuration, like such:

module.exports = {
   entry: ['whatwg-fetch', './app/js']
};

This will fix issues where using a 3rd party that expect fetch will not find it with the approach of this gist. This is also consistent with the way babel documents using a polyfill with Webpack and does not require the extra loaders.

I have opened a PR with fetch so they stop referring to this solution: JakeChampion/fetch#331

@tarikjn
Copy link

tarikjn commented May 19, 2016

@Nosherwan @silvenon you should not include a Promise polyfill if you use babel-polyfill, the correct configuration would then be:

module.exports = {
   entry: ['babel-polyfill', 'whatwg-fetch', './app/js']
};

@simonsmith
Copy link

Has anyone had success adding this when entry is an object?

@xingwang
Copy link

@simonsmith Does this not work for you?

entry: {
    demo: ['whatwg-fetch', './app']
  },

@strobox
Copy link

strobox commented Jul 19, 2016

@tarikjn
Works for me too, thanks!

@pmcalmeida
Copy link

@Couto ganda truta! 👍

@luiscvalmeida
Copy link

🐟

@vikas5914
Copy link

vikas5914 commented Aug 31, 2016

@tarikjn i am getting a Exception thrown and not caught in IE11 when i use babel-polyfill instead of es6 promise .

entry: ['babel-polyfill', 'whatwg-fetch','./src/main.js'],

but this works perfect in IE11

entry: ['es6-promise', 'whatwg-fetch','./src/main.js']

@callmemagnus
Copy link

callmemagnus commented Sep 10, 2016

Is there a way to have the polyfills loaded from a seperated chunk?

I wish that when a browser is lacking a feature it loads the predeclared polyfill (which would be put in a chunk by webpack). So that the final bundle size does not contain all the polyfills.

Is this possible somehow?

@Zjaaspoer
Copy link

@vikas5914, I'm getting the exact same. Did you solve this in the end, as I would rather keep using babel-polyfill

@NicolasSiver
Copy link

Adding polyfills through entry - defines them in global scope. If you own an application (SPA for example), I think It's Ok, but if you are working on the library, I don't recommend this approach.

@karlAlnebratt
Copy link

if you use webpack 2 you need to change import -> import-loader and export -> export-loader

new webpack.ProvidePlugin({
  fetch: 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch'
})

@samarpanda
Copy link

Can we use webpack.ProvidePlugin to conditionally load polyfills? Essentially load polyfills if browser don't support natively.

Copy link

ghost commented Aug 2, 2017

+1

@xgqfrms007
Copy link

xgqfrms007 commented Nov 29, 2017

🥇

good job!

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const folders = {
    APP: path.resolve(__dirname, '../app'),
    BUILD: path.resolve(__dirname, '../build'),
    BOWER: path.resolve(__dirname, '../bower_components'),
    NPM: path.resolve(__dirname, '../node_modules')
};

const config = {
    entry: {
        app: [
            'webpack/hot/dev-server',
            "./js/app.js"
        ]
    },
    debug: true,
    resolve: {
        extensions: ['', '.js', '.jsx', '.scss'],
        alias: {
            //'es6-promise': path.join(folders.NPM, 'es6-promise', 'es6-promise.js'),
            //'fetch': path.join(folders.NPM, 'whatwg-fetch', 'fetch.js'),
        }
    },
    stats: {
        colors: true,
        reasons: true,
    },
    output: {
        path: __dirname + '/build',
        publicPath: '/',
        filename: '[name].[hash].js',
        chunkFilename: '[id].[hash].js'
    },
    module: {
        loaders: [
            {
                test: /\.s?css$/,
                exclude: /node_modules/,
                loaders: [
                    'style',
                    'css',
                    'autoprefixer?browsers=last 2 version',
                    'sass?' + ['outputStyle=nested'].join('&')
                ]
            },
            { test: /\.jsx?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.json$/, loader: 'json' },
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.ProvidePlugin({
            'Promise': 'es6-promise', // Thanks Aaron (https://gist.github.com/Couto/b29676dd1ab8714a818f#gistcomment-1584602)
            'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
        }),
        //new webpack.optimize.CommonsChunkPlugin('app', null, false),
        new webpack.NoErrorsPlugin(),
        new HtmlWebpackPlugin({
            template: path.resolve('./', 'index.html'),
            webpackDevServer: '/webpack-dev-server.js'
        })
    ]
};

module.exports = config;

@r9software
Copy link

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