Last Updated on December 25, 2020 by Neil Murray
Babel-polyfill Issue
If there is another source of babel-polyfill enqueued in admin page, we will have error:
Uncaught Error: only one instance of babel-polyfill is allowed.
In version 0.6.8, we added babel-polyfill in webpack.config.js entry as explained from the doc site https://babeljs.io/docs/en/babel-polyfill/
'visual': [ 'babel-polyfill', './src/index.js' ],
Yoast SEO
They follow the same approach as Gutenberg to exclude vendor scripts from built file, and enqueue before the main built file.
Yoast/wordpress-seo/package.json includes babel-polyfill in “dependencies”:
"dependencies": {
"@wordpress/i18n": "^1.1.1",
"@wordpress/is-shallow-equal": "^1.0.2",
"a11y-speak": ..
"babel-polyfill": "^6.26.0",
..
Yoast/wordpress-seo/js/src/wp-seo-babel-polyfill.js explains why we are having a problem.
// The babel polyfill sets the _babelPolyfill to true. So only load it ourselves if the variable is undefined or false.
if ( typeof window._babelPolyfill === "undefined" || ! window._babelPolyfill ) {
// eslint-disable-next-line global-require
require( "babel-polyfill" );
}
So if the Yoast SEO plugin loads before CF7 Skins then it will require babel-polyfill & window._babelPolyfill will be added to the window global.
Then when CF7 Skins is activated we make repeated calls to babel-polyfill from within visual.js & get the error message that webpack adds to visual.js when the file is built.
babel-polyfill
https://babeljs.io/docs/en/babel-polyfill says:
Because this is a polyfill (which will run before your source code), we need it to be a dependency, not a devDependency
Each entry or polyfill we add before visual.js will be called before it.
entry: {
'visual': [ 'polyfill1', 'polyfill2', './src/index.js' ],
},
This means that our built code in visual.js is calling babel-polyfill before it runs the built JS code.
visual.js
Looking at cf7skins-visual\dist\visual.js – which is the built code we are distributing.
There are many instances of the following code:
if (global._babelPolyfill) {
throw new Error("only one instance of babel-polyfill is allowed");
}
webpack adds the calls to babel-polyfill in the dist build and those calls will be made when user runs the plugin on their site.
So if this global exists our code is going to have problems.
babel-plugin-transform-runtime
https://babeljs.io/docs/en/babel-polyfill says:
If you are looking for something that won’t modify globals to be used in a tool/library, checkout the transform-runtime plugin.
https://babeljs.io/docs/en/babel-plugin-transform-runtime says:
If you use babel-polyfill and the built-ins it provides such as Promise, Set and Map, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can’t exactly control the environment in which your code will run.
@wordpress/babel-preset-default uses @babel/plugin-transform-runtime & does not use babel-polyfill.
https://wordpress.slack.com/archives/C5UNMSU4R/p1532610716000113
Try promise-polyfill
Install it, remove babel-polyfill package and test in IE/Edge.
1. for … of is not supported in IE
We are using it in many files.
2. Gutenberg also uses for … of.
3. Gutenberg uses whatwg-fetch and promise-polyfill.
4. File: config/polyfills.js solved issue with fetch, Object.assign and Promise in IE. (Tested). We better revert back and use it.
https://wordpress.slack.com/archives/C5UNMSU4R/p1532573082000145
Gutenberg uses promise-polyfill
gutenberg_register_vendor_script( 'wp-polyfill-promise', 'https://unpkg.com/promise-polyfill@7.0.0/dist/promise' . $suffix . '.js' );
Advantages of babel-plugin-transform-runtime
Advantages of using babel-plugin-transform-runtime:
- Tested and works with create-react-app polyfills.
- Not using global scope.
- visual.js built file is smaller than using babel-polyfill, less than 3 MB.
Some issues reported with Gutenberg’s use of @babel/plugin-transform-runtime at Change how required built-ins are polyfilled
DevTools SourceMap Warning
Using babel-plugin-transform-runtime and builtin react-create-app ./config/polyfills.js we have a SourceMap warning:
DevTools failed to parse SourceMap: ..wp-content/plugins/contact-form-7-skins/js/performance-now.js.map
The warning only occurs in Chrome but not in Internet Explorer 11, Edge or Firefox.
Links:
- https://stackoverflow.com/questions/35002087/how-do-you-disable-source-maps-in-chrome-developer-tools
- https://github.com/facebook/react-devtools/issues/828
- https://github.com/facebook/create-react-app/issues/2212
Webpack Code-Splitted Files
Our code-splitting is part of the problem - because we run `babel-polyfill` in the webpack entry point.
From the https://github.com/webpack/webpack/tree/master/examples/code-splitting, webpack generates bootstrap function for the main file, and chunk files will have
This is the main file bundled by webpack:
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
And chunk file will have this line:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],[
The same as our build file, visual.js:
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window["webpackJsonp"];
and ready.js:
webpackJsonp([2],{
/***/ 805:
/***/ (function(module, exports, __webpack_require__) {
Question #core-js
Our plugin uses Create React App which include “babel-polyfill”. in webpack entry:
‘visual’: [ ‘babel-polyfill’, “./src/index.js” ],
From babel doc: https://babeljs.io/docs/en/babel-polyfill/
But it has issue “Uncaught Error: only one instance of babel-polyfill is allowed.” which we believe another “babel-polyfill” exists in Yoast SEO “plugins/wordpress-seo/js/dist/wp-seo-babel-polyfill-780.min.js”.
Do you have any suggestion to solve the issue?