React-static项目IE11及以下出现Promise is undefined问题求助
问题描述
我正在开发一个 React Static 应用,发现仅在 IE11 及以下浏览器中出现「Promise is undefined」错误,该错误源于项目依赖代码,而非我自行编写的代码(我已使用 @babel/polyfill 对整个应用做了兼容处理)。我判断需要对依赖也进行 @babel/polyfill 兼容处理,这个思路正确吗?如果正确,具体该如何操作?
现有配置文件
.babelrc
{ "presets": [ "react-static/babel-preset.js", ["@babel/preset-env", { "useBuiltIns": "entry", "debug": true, "targets": { "ie": "11" } }], ], "plugins": [ "@babel/transform-runtime", "@babel/plugin-proposal-class-properties", "babel-plugin-styled-components", ["minify-dead-code-elimination", { "optimizeRawSize": true }], [ "module-resolver", { "cwd": "babelrc", "root": ["./src/"], "extensions": [".jsx", ".js"], "alias": { "images": "./public/assets/images" } } ] ], "env": { "production": { "plugins": ["transform-remove-console"] }, "development": { "plugins": ["@babel/transform-react-jsx-source"] } } }
package.json
{ "name": "react-static-example-blank", "private": true, "license": "MIT", "scripts": { "start": "react-static start --debug --verbose", "stage": "react-static build --staging", "build": "react-static build", "serve": "serve dist -p 3001 -s" }, "dependencies": { "react": "^16.6.3", "react-dom": "^16.6.3", "react-hot-loader": "^4.3.12", "react-static": "^6.0.18", "styled-components": "^4.1.3", "@fortawesome/fontawesome-svg-core": "^1.2.0-14", "@fortawesome/free-brands-svg-icons": "^5.1.0-11", "@fortawesome/free-solid-svg-icons": "^5.1.0-11", "@fortawesome/react-fontawesome": "^0.1.1", "@babel/polyfill": "^7.2.5", "core-js": "2.6.3" }, "devDependencies": { "@babel/cli": "^7.0.0", "@babel/core": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/runtime": "^7.0.0", "babel-eslint": "^9.0.0", "babel-plugin-minify-dead-code-elimination": "^0.4.3", "babel-plugin-module-resolver": "^3.1.1", "babel-plugin-styled-components": "^1.10.0", "babel-plugin-transform-remove-console": "^6.9.4", "eslint": "^5.12.1", "eslint-config-airbnb": "^17.0.0", "eslint-import-resolver-babel-module": "^5.0.1", "eslint-plugin-import": "^2.16.0", "eslint-plugin-jsx-a11y": "^6.2.0", "eslint-plugin-react": "^7.12.4", "eslint-config-react-tools": "1.1.6", "react-devtools": "^3.6.0", "serve": "^10.1.1" } }
问题解答
你的思路完全正确!其实很多人都会踩这个坑——@babel/polyfill 默认只会处理你自己写的源码,那些第三方依赖包里的代码(比如你用的 styled-components、@fortawesome 这类)如果本身没做 IE11 兼容,就会带着 ES6+ 的 API 直接打包,IE11 不认 Promise 这类特性自然就报错了。下面咱们一步步来解决:
1. 先确认 @babel/polyfill 引入位置正确
你已经在依赖里装了 @babel/polyfill,但一定要确保在应用入口文件的最顶部(比如 src/index.js 或者 src/App.js 的第一行)引入它:
import '@babel/polyfill';
因为你在 @babel/preset-env 里设了 useBuiltIns: "entry",这个配置会根据你指定的目标浏览器自动挑选需要的 polyfill,但前提是你必须手动在入口处引一次,不然它没法生效。
2. 让 Babel 转译第三方依赖
默认情况下,Babel 会跳过 node_modules 目录,所以依赖里的未转译代码根本没被处理。你需要修改 .babelrc,告诉 Babel 哪些依赖包需要被转译。
在你的 .babelrc 里加个 include 字段,把那些可能不兼容的依赖加进去,比如你用到的 styled-components 和 @fortawesome 系列:
{ "presets": [ "react-static/babel-preset.js", ["@babel/preset-env", { "useBuiltIns": "entry", "debug": true, "targets": { "ie": "11" } }] ], "plugins": [ // ... 保留你原来的所有插件 ], "env": { // ... 保留你原来的环境配置 }, "include": [ "./src/**/*", // 你的源码必须包含 "./node_modules/styled-components/**/*", "./node_modules/@fortawesome/**/*" // 如果之后还有其他依赖报错,就把对应的包路径加进来 ] }
要是不确定哪些依赖有问题,直接看 IE11 控制台的报错栈,里面会明确显示是哪个包里的代码出问题,把那个包的路径加到 include 里就行。
3. 升级 core-js 让兼容更彻底(可选但推荐)
你现在用的是 core-js@2.6.3,而现在官方更推荐用 core-js@3,它的 polyfill 覆盖更全面,也更适配现代的 Babel 配置。如果可以的话,建议升级一下:
- 先安装新版
core-js:
npm install core-js@3 --save
- 修改
.babelrc里的@babel/preset-env配置,指定corejs版本:
["@babel/preset-env", { "useBuiltIns": "entry", "debug": true, "targets": { "ie": "11" }, "corejs": 3 }]
- 最后把入口文件的
import '@babel/polyfill'换成下面两行:
import 'core-js/stable'; import 'regenerator-runtime/runtime';
这样能更精准地加载需要的 polyfill,避免打包冗余代码。
4. 验证配置是否生效
运行 npm run build 构建项目,然后用 IE11 打开 dist 目录里的页面测试。另外,因为你开了 debug: true,构建时控制台会输出详细的 polyfill 引入日志,你可以看看有没有 Promise 相关的 polyfill 被加载了,这也能帮你确认配置是否起作用。
如果还是有问题,可以排查这几点:
- 入口文件的 polyfill 是不是在最顶部?必须确保它比其他依赖先加载
- 是不是还有其他没被转译的依赖?根据报错信息补充到
include里 - React Static 的 preset 顺序是不是影响了配置?你现在把它放在第一个是对的,但如果有冲突,可以试试把
@babel/preset-env挪到第一个(不过通常不用这么做)
内容的提问来源于stack exchange,提问作者darksoulsong

