J'ai Webpack qui travaille avec Babel et inclut le @ babel/polyfill, mais IE11 génère toujours une erreur SCRIPT438 lors de la tentative d'utilisation de .forEach
sur un NodeList
.
Voici mon package.json
{
...
"scripts": {
"build:js": "webpack --config ./_build/webpack.config.js"
},
...
"browserslist": [
"IE 11",
"last 3 versions",
"not IE < 11"
],
"babel": {
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
},
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"babel-loader": "^8.0.4",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2"
},
"dependencies": {
"@babel/polyfill": "^7.0.0"
}
}
Ma webpack.config.js
:
const path = require('path');
const webpack = require('webpack');
module.exports = (env, argv) => {
const javascript = {
test: /\.js$/,
use: {
loader: 'babel-loader'
}
};
// config object
const config = {
entry: {
main: './_src/js/main.js',
},
devtool: 'source-map',
output: {
path: path.resolve(__dirname, '../js'),
filename: '[name].js',
},
module: {
rules: [javascript]
}
}
return config;
}
Et enfin /_src/main.js
que j'exécute via webpack et babel:
const testList = document.querySelectorAll('.test-list li');
testList.forEach(item => {
console.log(item.innerHTML);
})
Les documents sur https://babeljs.io/docs/en/babel-polyfill disent que vous n'avez pas besoin de import
ou require
polyfill
lors du chargement via Webpack avec useBuiltIns: "usage"
. Mais même si je supprime cette option et importe manuellement l'intégralité du polyfill en haut de main.js
(ce qui rend mon paquet énorme), il reste des erreurs dans IE11.
Alors ... qu'est-ce que je fais mal?
Mise à jour: Depuis Babel 7.4.0, Babel est passé à l'utilisation de core-js
directement plutôt que de l'envelopper avec @babel/polyfill
. core-js
déjà polyfills forEach
on NodeList
, donc plus de polyfill supplémentaire requis.
babel-polyfill ne remplit pas les méthodes API/prototype Web manquantes comme NodeList.prototype.forEach
.
Veuillez également noter que le titre de votre question est trompeur: NodeList.prototype.forEach
n'est pas une fonctionnalité ES6. forEach
sur les collections itérables n'est actuellement qu'une recommandation du candidat (en août 2018).
Incluez simplement votre propre polyfill au niveau supérieur de votre Javascript:
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
Cela pourrait changer dès que core-js 3 sera stable: https://github.com/zloirock/core-js/issues/329
Vous pouvez également vous passer de polyfill si vous commencez à adopter le modèle commun utilisé dans ES6 fois:
const testList = [...document.querySelectorAll('.test-list li')];
ou
const testList = Array.from(document.querySelectorAll('.test-list li'));
L'autre option que vous avez est d'utiliser for...of
au lieu:
const lis = document.querySelectorAll('.test-list li');
for (const li of lis) {
// li.addEventListener(...) or whatever
}
Enfin, vous pouvez également adopter le modèle ES5 commun:
var testList = document.querySelectorAll('.test-list li');
Array.prototype.forEach.call(testList, function(li) { /*whatever*/ });