How to add polyfills for external libraries in babel with rollup - babeljs

I'm using rollup to build my (AMD/UMD) project. There's an external dependency to a library that uses ES features such as: Map, Symbol, Array.from, etc. which aren't supported in Internet Explorer. Since the library is external, babel doesn't seem to transpile the library, meaning those features are never polyfilled.
Is there a way to tell babel to include this library for polyfilling via #babel/preset-env?
The rollup config I have looks something like this:
{
// omitted ...
external: [
'vue',
/^#pnp.*/, // uses Map, Symbol, Array.from, ...
],
plugins: [
babel ({
configFile: false,
runtimeHelpers: true,
exclude: /node_modules\/(?!vue-runtime-helpers)/,
extensions: ['.js', '.jsx', '.es6', '.es', '.mjs', '.ts', '.tsx', '.vue'],
presets: [
['#babel/preset-env', {
corejs: 3,
useBuiltIns: 'usage',
ignoreBrowserslistConfig: false,
targets: {
browsers: browserslist, // includes IE11
},
}],
],
}),
]
}
vue seems to work as an external dependency OOTB, because they provide a build that's IE-compatible, while pnpjs does not.

Babel won't be able to detect needed polyfills for external modules but you can include #pnp/polyfill-ie11 in your app. Make sure to not mark it as external.

Related

Not able to use babel "preset-env" plugin with NextJS

I have a requirement where I am trying to use the Babel plugin "preset-env". This plugin compiles my NextJS project from ES6 to ES5. I have created the .babelrlc file as suggested by NextJS documentation and added my plugin like this:
{
"presets": ["next/babel"],
"plugins": ["#babel/preset-env"]
}
When I try to run my project locally I get this error:
error - ./node_modules/next/dist/client/router.js
Error: Cannot find module '#babel/plugin-preset-env' from '/Users/agastya/Local/testcap/Sample-proj'
- If you want to resolve "#babel/preset-env", use "module:#babel/preset-env"
- Did you accidentally pass a preset as a plugin?
NextJS documentation says "Next.js includes the next/babel preset to your app, which includes everything needed to compile React applications and server-side code. ".
It would be great if someone can explain where/what is the right approach to fix this.
You have to do the following:
// .babelrc file, also could be babel.config.js
{
"presets": [
[
"next/babel",
{
"preset-env": {},
"transform-runtime": {},
"styled-jsx": {},
"class-properties": {}
}
]
],
"plugins": []
}
Taken from: https://nextjs.org/docs/advanced-features/customizing-babel-config

Babel 7 not including polyfills

I am trying to transpile a webapplication using Babel v7.8.7 and Webpack v4.42.0.
The solution works in the latest version of Chrome. In Internet Explorer I am getting an error:
SCRIPT5022: Exception thrown and not caught.
If I include polyfills from a CDN the app works correctly in IE11:
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser-polyfill.min.js"></script>
I am now wondering why Babel is not polyfilling correctly.
My index.js includes core-js polyfills:
import "core-js/es";
import "regenerator-runtime/runtime";
I have set .browserslistrc to include Internet Explorer 11.
My babel.config.js:
module.exports = {
presets: [
[
"#babel/preset-env",
{
useBuiltIns: "usage",
corejs: '3.6.4'
}
],
"#babel/preset-react"
],
plugins: [
"#babel/plugin-transform-async-to-generator",
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-proposal-nullish-coalescing-operator"
]
};
Do you know what I am missing to have Babel polyfill correctly?

How can I configure babel/preset-env to include core-js URLSearchParams polyfill?

I'm using URLSearchParams in my app. The code is transpiled with babel, using babel/preset-env and core-js#3 to include polyfills needed for the browsers I target.
This is my babelrc:
{
"presets": [
[
"#babel/preset-env",
{
"modules": false,
"corejs": "3",
"useBuiltIns": "entry",
"forceAllTransforms": true
}
]
]
}
Here is my .browserslistrc:
IE 11
Edge >= 14
last 2 Chrome versions
last 2 Firefox versions
The problem is that even though I've specified IE11 in .browserslistrc, the polyfill for URLSearchParams is still not included in the final bundle. So far I've solved this by manually importing core-js/web/url-search-params.js but I would rather that was done automatically by babel/preset-env.
Can I configure babel/preset-env somehow to include the URLSearchParams polyfill from core-js?
Since I'm getting upvotes on the question I should probably add my answer here as well.
The problem for me was that I was adding #babel/polyfill next to my entrypoint in my webpack config:
{
entry: {
"my.js": ["#babel/polyfill", "my.js"]
}
}
To fix my problem I removed #babel/polyfill from the entrypoint, and instead added the following to the top of my.js:
import "core-js/stable";
import "regenerator-runtime/runtime";

babel-preset-env not changing build size

I have an ES6 React app that is being bundled with webpack and using babel. I am configuring babel-preset-env, for node everything is working perfect, but for browser the size of my build is not changing regardless the target percentage. The size is the same when the interval is >1 or when its 90%.
The webpack version is 1.13.1, my babel version 6.26.0 and babel-preset-env version is 1.6.1
I have this in my .babelrc
{
"presets": [
"es2015",
"stage-0",
"react",
[
"env",
{
"targets": {
"node": "9.4.0",
"browsers": [
">1%"
]
}
}
]
],
"plugins": [
[
"transform-class-properties",
"transform-runtime",
"transform-decorators-legacy",
"react-intl",
{
"messagesDir": "./build/messages",
"enforceDescriptions": false
}
]
]
}
When you use babel-preset-env it will decide, based on the list of browsers your target, to include only the necessary babel transforms.
It is an alternative to es2015 and stage-0, and including those presets along with env is counterproductive, as the transforms included in those presets will be applied whether they're needed or not.
It also depends on how you use babel-polyfill. Set it as import 'babel-polyfill' at the beginning of your JavaScript entry file, and babel-preset-env will replace the import with individual imports with only the polyfills needed for the browsers you target.
I am not sure if it works that way if you include babel-polyfill as part of the Webpack entry option, e.g.:
js
entry: {
myentry: ['babel-polyfill', 'js/index.js']
}
Hope this will help you get that bundle size down!
P.S. I'm aware the babel-preset-env documentation is not the clearest when it comes to describing what you need to do.
Make sure you have import "#babel/polyfill"; in your index.js.
Also, make sure you only import it once.
If you have something like this
entry: ["#babel/polyfill", path.join(__dirname, "./src/index.js")],
in your webpack config, move the polyfill, so it should look like
entry: path.join(__dirname, "./src/index.js")

Karma runner: how to load plugin from file (inlined plugins)

I want to add a plugin from a local file to Karma. I found this example in the documentation (version 0.1):
Documentation to karma runner
// inlined plugins
{'framework:xyz', ['factory', factoryFn]},
require('./plugin-required-from-config')
This is not even valid javascript. When I try the require version of registering I get
Plugin is not registered.
The require version the same.
How is this supposed to be?
It's not so hard.
First of all you should add your plugin to 'plugins' property in karma.config.js after that you could us it.
module.exports = (config) => {
config.set({
frameworks: ['xyz'],
plugins: [
'karma-*',
{
'framework:xyz': ['factory', ()=> console.log('Your code')]
}
]
})
}