IE11环境下如何添加String.repeat与AbortController的Polyfill?
我之前在用Create React App开发项目时,也碰到过完全一样的情况——自己代码里根本没用到String.repeat和AbortController,但IE11控制台却一直报这两个错误,排查后才发现是引入的第三方库在偷偷使用这些ES6+特性。下面是我试过的几个有效解决方案,你可以逐一尝试:
1. 调整Polyfill的加载顺序(关键!)
react-app-polyfill的导入顺序非常重要,必须放在所有其他代码(包括React、第三方库)的最前面。我之前就是因为把polyfill放在了React导入之后,导致第三方库加载时polyfill还没生效。
修改你的index.js,确保开头是这样:
// 最顶部先导入polyfill import 'react-app-polyfill/ie11'; import 'react-app-polyfill/stable'; // 然后再导入其他依赖 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; // 你的第三方库导入放在这里
另外,react-app-polyfill/ie11已经包含了ie9的兼容,所以可以去掉单独的ie9导入,简化代码。
2. 单独添加AbortController的Polyfill
react-app-polyfill并没有包含AbortController的兼容,这个API需要单独处理:
- 首先安装polyfill包:
npm install abortcontroller-polyfill --save - 然后在react-app-polyfill之后导入它:
import 'react-app-polyfill/ie11'; import 'react-app-polyfill/stable'; // 新增这行 import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
这个polyfill会同时补全AbortController和它在fetch中的使用逻辑。
3. 把String.repeat的Polyfill提前到HTML中加载
如果上面的方法还没解决String.repeat的问题,很可能是某个第三方库在你的JS代码执行前就调用了这个方法(比如库的顶层作用域就有调用)。这时候把polyfill放在public/index.html的最前面,确保页面加载时第一个执行:
在public/index.html的<body>标签最顶部添加:
<script> if (!String.prototype.repeat) { String.prototype.repeat = function(count) { 'use strict'; if (this == null) { throw new TypeError('can\'t convert ' + this + ' to object'); } var str = '' + this; count = +count; if (count != count) { count = 0; } if (count < 0) { throw new RangeError('repeat count must be non-negative'); } if (count == Infinity) { throw new RangeError('repeat count must be less than infinity'); } count = Math.floor(count); if (str.length == 0 || count == 0) { return ''; } if (str.length * count >= 1 << 28) { throw new RangeError('repeat count must not overflow maximum string size'); } var rpt = ''; for (;;) { if ((count & 1) == 1) { rpt += str; } count >>>= 1; if (count == 0) { break; } str += str; } return rpt; }; } </script>
这样在所有JS文件加载前,String.repeat就已经被补全了。
4. 确认Browserslist配置包含IE11
检查你的package.json,确保browserslist配置里明确包含了IE11,这样Create React App的Babel会自动针对IE11进行转译和polyfill处理:
"browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all", "ie 11" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version", "ie 11" ] }
5. 强制转译未兼容的第三方库
如果以上方法都没用,那可能是你用的第三方库本身是用ES6+写的,没有做向下兼容,而且没有被CRA的Babel转译。这时候可以用react-app-rewired来修改Webpack配置,强制转译这个库:
- 先安装依赖:
npm install react-app-rewired customize-cra --save-dev - 在项目根目录创建
config-overrides.js:const { override, babelInclude } = require('customize-cra'); const path = require('path'); module.exports = override( // 替换成你要转译的第三方库名称 babelInclude([ path.resolve('src'), path.resolve('node_modules/[your-third-party-lib]') ]) ); - 修改
package.json中的启动脚本:"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }
按照这个流程走下来,应该就能解决IE11的这两个错误了。我当时是调整了polyfill顺序+添加AbortController的polyfill就搞定了,你可以先试前两步~
内容的提问来源于stack exchange,提问作者icelic

