minimal working example: rollup + babel + async/await
htho opened this issue ยท 19 comments
I saw some issues (#209, #306) and questions on stackoverflow about how to configure rollup and babel so I can use async and await. There are many (often outdated) answers and it is a tedious, difficult (but hopefully not impossible) task to create a working rollup.config.js. I was not able to do that.
My repository
should become a minimal working example.
Right now it is a vanilla rollup.config.js based on the official rollup.js guide. https://rollupjs.org/guide/en/#babel
I understand that rollup is currently es6 only, and therefore does not support async/await natively. But I thought that this would be babel's job anyway. For the Developer Experience, setting up rollup+babel with async/await support, should be a no-brainer.
Please help me. Or integrate it into this repository. A set of minimally working examples would make developers lifes so much easier.
It all depends on what are your requirements and target format, you can make your example work by using such a setting:
{
"presets": [
["@babel/env", { "modules": false, "useBuiltIns": "usage" }]
]
}
I am required to set the corejs version.
$ ./node_modules/.bin/rollup -c
src/BuildTest.js โ dist/BuildTest.js...
WARNING: We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in
future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option.
You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following
commands:
npm install --save core-js@2 npm install --save core-js@3
yarn add core-js@2 yarn add core-js@3
(!) Unresolved dependencies
https://rollupjs.org/guide/en#warning-treating-module-as-external-dependency
regenerator-runtime/runtime (imported by src\BuildTest.js)
created dist/BuildTest.js in 2.3s
OK, which core-js should I use, and where do I "explicitely" set the corejs version via the corejs
option?
I can not find the answer: https://duckduckgo.com/?q=babel+rollup+declare+the+core-js+version&t=ffab&ia=web
Use latest one:
{
"presets": [
["@babel/env", { "modules": false, "useBuiltIns": "usage", "corejs": 3 }]
]
}
Still not sufficient:
./node_modules/.bin/rollup -c
src/BuildTest.js โ dist/BuildTest.js...
(!) Unresolved dependencies
https://rollupjs.org/guide/en#warning-treating-module-as-external-dependency
regenerator-runtime/runtime (imported by src\BuildTest.js)
created dist/BuildTest.js in 2s
U have to install regenerator-runtime module and u should be ready to go
Thank you so far.
I have updated my repository in order to reflect the changes we discussed.
The regenerator is available now.
But IE still needs a Polyfill for Promise. I'd expect babel to include it aswell, but it isnt. Is it a problem with babel? To my understanding, the babel documentation suggests that the Promise polyfill is included aswell: https://babeljs.io/docs/usage/polyfill/
Well, there is the message, that says with useBuiltIns I should not import polyfills anymoren
In your example rhe reference to a Promise is only in so called babel helpers (asyncGeneratorStep & asyncToGenerator here). Those are insertes "as is" - without compilation, so preset-env doesn't visit it to see a Promise which would cause it to insert a ponyfill import. To work around this you can insert Promise.resolve()
into your code, or you can just polyfill Promise globally.
Hi. Once someone (you) explained the internals to me, this seems totally logical. But in my opinion consumers of a tool should not need learn these internals. They should not be required to solve this problem on their own. The solution should not be a dummy call to Promise.resolve()
. But that is another topic.
I really feel stupid for asking all these questions. On the other hand, I am really frustrated a task that is so basic, is so complicated. The documentation of all the releated tools and all the error messages are so useless. I really am someone who says and does RTFM ans STFI all the time, but I cant help myself here.
Manually including the polyfill circumvents the useful useBuiltIns. So I make the dummy call.
Guess what! It still does not work. The polyfill that is included uses calls to require() and of course they can not be resolved at runtime. Thats what rollup or babel should do.
I updated the repository again.
Please I really start doubting myself.
I agree with all of your points, this is a surprisingly hard thing to do for something supposedly that simple. Even I had to look through docs and babel source code to try find a good combo of options for various outputs which I have wanted to achieve here.
Problem is that requirements are different for people though, one is fine with polluting global namespace with polyfills, one is not and want to use ponyfill imports, other one doesn't want to polyfill at all or just want to handle on their own. That's why there is no one golden example for doing this. I've brought this up to a Babel team though and hopefully we should be able to figure out a better way of doing this like this.
I'll look at your repo at later time, unfortunately I don't have much time right now.
Have a look at egoist/bili it removes a lot of the complexity. And uses rollup under the hood.
I've pulled my hair about this today, and I could have recent Babel 7, along with tests to work. Lots of things changed since Babel 6.
I pushed something that works with testing with recent config. Tests works woth modern async/await, uses modules and does transpilation in different targets (e.g. Node, Browser) and mimicks one module member of a monorepo. Try it out, maybe it'll help. https://github.com/renoirb/experiments-201907-bili-babel-preset-env-multiple-target-builds
Hi @renoirb,
bili sounds nice. But I am always sceptical when I need to put more and more parts of my build-process into someone elses hands. New systems introduce new problems. This speaks from my heart: https://bravenewgeek.com/tag/taco-bell-programming/
As long as I can, I want to use the cat
, sed
and grep
of the bundle/transpile world.
Anyway, it is good to know that there is bili out there. Should I or the awsome devs at rollup and/or babel not find a solution in the next time, I need to reeavaluate it.
Thank you very much!
/dist/BuildTest.js
...
var $ = require('../internals/export');
var IS_PURE = require('../internals/is-pure');
var global = require('../internals/global');
var path = require('../internals/path');
var redefineAll = require('../internals/redefine-all');
...
Hi,
I didn't find an "internals" directory, so where did it require internals?
Hi @FuJuntao as far as I understood the problem. This code is copied&pasted somwhere from within babels directory structure. Somewhere in there, there might be an internals directory. But the problem is, that the code is not transpiled/included before it is moved here.
I'm having the same kind of issues. I've tried just about every combination I can think of between rollup and babel, but still can't get it working properly.
rollup.config.js
:
import pkg from './package.json';
import babel from 'rollup-plugin-babel';
export default [
{
input: 'src/index.js',
output: [
{ file: pkg.browser, format: 'umd', name: 'MyLib' },
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' },
],
plugins: [
babel({
babelrc: false,
exclude: 'node_modules/**',
presets: [
[
'@babel/preset-env',
{
corejs: 3,
modules: false,
useBuiltIns: 'usage',
forceAllTransforms: true,
targets: {
node: 'current',
ie: '11',
},
},
],
],
}),
],
},
];
The first few lines of my output file, however, contain references directly to core-js
and regenerator-runtime
. I have both of those installed as devDependencies
.
require('core-js/modules/es.array.from');
require('core-js/modules/es.array.iterator');
require('core-js/modules/es.map');
require('core-js/modules/es.object.to-string');
require('core-js/modules/es.string.iterator');
require('core-js/modules/web.dom-collections.for-each');
require('core-js/modules/web.dom-collections.iterator');
require('regenerator-runtime/runtime');
Update: Finally got it working with the following rollup.config.js
(no babel config as it is inlined in the rollup config):
import pkg from './package.json';
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
export default [
{
input: 'src/index.js',
output: [
{ file: pkg.browser, format: 'umd', name: 'MyLib' },
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' },
],
plugins: [
babel({
babelrc: false,
exclude: 'node_modules/**',
presets: [
[
'@babel/preset-env',
{
corejs: 3,
modules: false,
useBuiltIns: 'usage',
targets: {
ie: '11',
},
},
],
],
}),
resolve(),
commonjs(),
],
},
];
The fix was adding rollup-plugin-node-resolve
and rollup-plugin-commonjs
. I didn't need any additional babel plugins like transform-runtime
or transform-async-to-generator
.
CC @FuJuntao - I had the same internals
references as you after I added rollup-plugin-node-resolve
. That was fixed and properly inlined once I added rollup-plugin-commonjs
. Hope that fixes your problem as well.
Thank you @green-arrow now it works!
https://github.com/htho/mweRollupBabelAsyncAwait
@Andarist It still is necessary to include the dummy call to `Promise.resolve()``. Will there be a solution for this inconvenience?
I am currently looking into that example: https://github.com/htho/mweRollupBabelAsyncAwait.
It kinda works but the Promise.resolve()
hacks seems weird and confusing (Is it just Promise
or are other things broken too?). Has there been any progress in finding the cause of that problem?
My current work around is basically @babel/plugin-transform-runtime
. And honestly, I don't really understand the difference between babel's plugin-transform-runtime
and preset-env
's useBuiltIns
set to usage
. The former one seems to produce slightly smaller output than the latter one.
I have a running example of async/await written in TypeScript, and multiple build outputs. It's also using @babel/plugin-transform-runtime.
Regarding the confusion about preset-env and transform-runtime plugin. Look at my notes in @renoirb/conventions-use-bili (they're what's hidden behind my bili.conf.js).
Thanks for putting this together guys! Awesome stuff. This was a confusing process indeed.