Search code examples
javascriptbabeljsflowtypees6-modulesrollup

In Rollup, create ESM module with no babel transpiling except Flow


I'm trying to release a library that contains Flow syntax in several forms, using Rollup and Babel:

  • UMD, ES5 (works)
  • UMD, ES5, minified (works)
  • ES module (problem)

Specifically, I want the ES module version to be as minimally transpiled as possible: it should use the full range of ES6 features just as I wrote them. I can't seem to stop Babel transpiling down to ES5 though - it creates an _objectSpread2() function and replaces every spread operator with it.

The only reason I want to use Babel is for the Flow syntax. Specifically, converting class property syntax:

class Foo { 
  myProp = 1;
}

(The standalone tool flow-remove-types does not transform class syntax, so its output is not valid JS).

This is the Rollup config that currently over-transpiles, to ES5:

import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import flow from 'rollup-plugin-flow';
export default [
    {
        input: 'src/index.js',
        output: [
            {
                file: 'dist/index.esm.js',
                format: 'esm', // ES2015 modules version so consumers can tree-shake
            },
        ],
        plugins: [flow(), commonjs(), nodeResolve()],
    },
];

Even when I remove the presets, it still does exactly the same thing:

import babel from '@rollup/plugin-babel';
export default [
    {
        input: 'src/index.js',
        output: [
            {
                file: 'dist/index.esm.js',
                format: 'esm', // ES2015 modules version so consumers can tree-shake
            },
        ],
        plugins: [
            babel({
                presets: [],
            }),
        ],
    },
];

Do I need to change something in .babelrc? It is currently as follows:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "esmodules": true
                }
            }
        ],
        ["@babel/preset-flow"]
    ]
}

The library is here.


Solution

  • Hmm, I think the problem was that .babelrc was being applied even in the ESM case. So the answer is:

    1. Remove the .babelrc file
    2. Move its configuration to rollup.config.js
    3. Configure rollup-esm.config.js to explicitly handle class syntax.

    Rollup.config.js:

    ...
            plugins: [
                flow(),
                commonjs(),
                nodeResolve(),
                babel({
                    babelHelpers: 'bundled',
                    presets: [
                        [
                            '@babel/preset-env',
                            {
                                targets: {
                                    esmodules: true,
                                },
                            },
                        ],
                        ['@babel/preset-flow'],
                    ],
                }),
            ],
    
    

    rollup-esm.config.js:

    import babel from '@rollup/plugin-babel';
    export default [
        {
            input: 'src/index.js',
            output: [
                {
                    file: 'dist/index.esm.js',
                    format: 'esm', // ES2015 modules version so consumers can tree-shake
                },
            ],
            plugins: [
                babel({
                    plugins: ['@babel/plugin-proposal-class-properties'],
                    presets: ['@babel/preset-flow'],
                }),
            ],
        },
    ];