Skip to content
This repository has been archived by the owner on Aug 4, 2021. It is now read-only.

Run babel per output #333

Merged
merged 20 commits into from Nov 28, 2019
Merged

Run babel per output #333

merged 20 commits into from Nov 28, 2019

Conversation

lukastaegert
Copy link
Member

@lukastaegert lukastaegert commented Nov 15, 2019

Resolves #303.

This PR will add the ability to run Babel on generated chunks instead of input files. Also, this updates all dependencies to their latest versions if possible. I also updated documentation which I will copy below and which should explain most of the details.

One possible improvement that I did not get to yet and that may be part of a future PR is that in order to deduplicate helpers in a code-splitting setup, this plugin could move all used helpers to a separate chunk that is then emitted in the generateBundle hook. This should probably not be the default behaviour but might be made configurable via an option. Unfortunately I do not see how it could be possible to only move shared helpers to a shared chunk as we would only know which helpers are shared AFTER all chunks are processed.

I also updated quite a few of the tests as I found them to be either quite unspecific or of the "always green" kind.

Anyway, this is the main part of the documentation update:

Running Babel on the generated code

By setting options.transformGenerated: true, you can configure rollup-plugin-babel to run Babel on the output files instead of the input files. This can be used to perform code transformations on the resulting chunks and is the only way to transform Rollup's auto-generated code. By default, the plugin will be applied to all outputs:

// rollup.config.js
import babel from 'rollup-plugin-babel';
export default {
	input: 'main.js',
	plugins: [babel({ transformGenerated: true })],
	output: [
		{ file: 'bundle.cjs.js', format: 'cjs' },
		{ file: 'bundle.esm.js', format: 'esm' },
	],
};

If you only want to apply it to specific outputs, you can use it as an output plugin:

// rollup.config.js
import babel from 'rollup-plugin-babel';
export default {
	input: 'main.js',
	output: [
		{ file: 'bundle.js', format: 'esm' },
		{
			file: 'bundle.min.js',
			format: 'esm',
			plugins: [babel({ transformGenerated: true })],
		},
	],
};

The include, exclude and extensions options are ignored when the transformGenerated option is used and will produce warnings, and there are a few more points to note that users should be aware of.

Finding .babelrc files

Depending on what options are used, this plugin will start looking for .babelrc files starting in the directory of the file indicated by output.file or in the directory indicated by output.dir. If neither of these options is used, e.g. when rendering to stdout or when using the JavaScript API, then .babelrc files are ignored and options need to be passed in manually.

Injected helpers

By default, helpers e.g. when transpiling classes will be inserted at the top of each chunk. In contrast to when applying this plugin on the input files, helpers will not be deduplicated across chunks.

You can however use external helpers by adding the @babel/external-helpers plugin, which will look for helpers on a global variable named babelHelpers:

rollup.rollup({...})
.then(bundle => bundle.generate({
  format: 'esm',
  plugins: [babel({
    transformGenerated: true,
    presets: ['@babel/env'],
    plugins: ['@babel/external-helpers']
  })]
}))
// input
export default class Foo {}

// output
var Foo = function Foo() {
	babelHelpers.classCallCheck(this, Foo);
};

export default Foo;

Alternatively, you can use imported runtime helpers by adding the @babel/transform-runtime plugin. Note that to produce valid code e.g. with @babel/env, it is very recommended to configure the format of modules for that plugin to match the output format used by Rollup:

rollup.rollup({...})
.then(bundle => bundle.generate({
  format: 'cjs',
  plugins: [babel({
    transformGenerated: true,
    presets: [['@babel/env', { modules: 'cjs' }]],
    plugins: ['@babel/transform-runtime']
  })]
}))
// input
export default class Foo {}

// output
('use strict');

var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault');

var _classCallCheck2 = _interopRequireDefault(require('@babel/runtime/helpers/classCallCheck'));

var Foo = function Foo() {
	(0, _classCallCheck2['default'])(this, Foo);
};

module.exports = Foo;

README.md Outdated Show resolved Hide resolved
src/index.js Outdated Show resolved Hide resolved
src/index.js Outdated Show resolved Hide resolved
src/index.js Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
test/test.js Show resolved Hide resolved
test/test.js Outdated Show resolved Hide resolved
test/test.js Outdated Show resolved Hide resolved
test/test.js Outdated Show resolved Hide resolved
test/test.js Show resolved Hide resolved
@lukastaegert
Copy link
Member Author

Thanks for the very detailed review ❤️

@lukastaegert
Copy link
Member Author

I tried to address all comments, open for a second review.

src/index.js Outdated Show resolved Hide resolved
src/index.js Outdated Show resolved Hide resolved
@lukastaegert
Copy link
Member Author

I have updated the code to use babel.generated to transform chunks and also added a warning with a recommended fix for formats other than esm or cjs.

On a side-node, even Babel's UMD wrapper creates unintended globals, in that case _typeof, but I believe this is not a big issue is it will likely be the only one and also should not cause conflicts as the code outside the wrapper is not run in strict mode.

@nicolo-ribaudo
Copy link
Contributor

On a side-node, even Babel's UMD wrapper creates unintended globals, in that case _typeof, but I believe this is not a big issue is it will likely be the only one and also should not cause conflicts as the code outside the wrapper is not run in strict mode.

This should be already fixed in master

@lukastaegert
Copy link
Member Author

I addressed most of the comments, except the question if we should ignore project-wide configuration. Still undecided. In any case, we should probably add a note about the configFile option so that users know how to override whatever the default is.

@Andarist
Copy link
Member

Ok, so the only thing we need to decide is if we should load configs for output plugins, right? I think I would be in favor of not loading them, but I don't feel very strongly about it 🤷‍♂

@lukastaegert
Copy link
Member Author

By now I also agree not loading by default should be preferable. I will change this by tomorrow and make sure I document the configFile option

@lukastaegert
Copy link
Member Author

I have deactivated default config file loading for babel.generated and adjusted the documentation to reflects this and also explain the configFile option, please have another look.

@Andarist
Copy link
Member

Last question - should we bump peerDep on rollup? Can we validate if someone tries to use an output plugin with older version of rollup? Or is note in a doc about supported versions sufficient?

@lukastaegert
Copy link
Member Author

Unless you want to use it as an output plugin, babel.generated is fully backwards compatible, so I guess a note in the docs would be sufficient.

@Andarist
Copy link
Member

Could you add such? Other than that - I have no further objections. So we should be able to merge this in this week.

cc @loganfsmyth could you maybe take a look as well if everything is OK in your eyes?

@lukastaegert
Copy link
Member Author

I added a note

@Andarist Andarist merged commit cc98689 into master Nov 28, 2019
@Andarist Andarist deleted the run-babel-per-output branch November 28, 2019 07:22
@Andarist
Copy link
Member

In the following days I'm going to look through PRs and such, need to migrate this plugin to the plugin monorepo. @lukastaegert would you prefer to have this published ASAP or can it wait after I'm done with migration? Note that migration will most likely end up major bumping this package anyway.

@rolftimmermans
Copy link

Is there a way to try this out yet? Latest release on NPM does not have this feature, and using the repository directly does not seem to work because there are no files in dist...

@Andarist
Copy link
Member

Andarist commented Dec 8, 2019

I hope to release this in a couple of days - maybe today. Stay tuned.

@Andarist
Copy link
Member

I've just published a new rollup-plugin-babel@next (5.0.0-alpha.1) with this feature included - please give it a try.

@rolftimmermans
Copy link

It works pretty well for me!

@dilyanpalauzov
Copy link

When will this be released as @current instead of @next?

@Andarist
Copy link
Member

Andarist commented Apr 9, 2020

Hard to tell - please track rollup/plugins#108. I really hope to review it soon.

@dilyanpalauzov
Copy link

I do not see a connection between releasing a version offering babel() as ouput plugin and moving to a different repository.

@Andarist
Copy link
Member

The difference is in time put into releasing it and possible maintenance, user issues, etc.

It is currently released as next, so if you care about this feature - just use that next version.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Transform on chunk level instead of module level
6 participants