Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing default and named exports with Rollup

I am writing a Bluetooth library for Node.js using TypeScript and Rollup. I want to enable users to import my libraries components in these ways

import Sblendid from "@sblendid/sblendid";
import Sblendid, { Peripheral } from "@sblendid/sblendid";

const Sblendid = require("@sblendid/sblendid");
const { Peripheral } = require("@sblendid/sblendid");

My project structure looks like this:

root
 ∟ rollup.config.ts
 ∟ src
    ∟ index.ts
    ∟ sblendid.ts
    ∟ peripheral.ts

And the according code is this:

index.ts

export {
  default,
} from "./sblendid";

export {
  default as Peripheral,
} from "./peripheral";

sblendid.ts

export default class Sblendid {}

peripheral.ts

export default class Peripheral {}

I am bundling everything with Rollup and my entire config is this:

import typescript from "typescript";
import commonjs from "rollup-plugin-commonjs";
import resolve from "rollup-plugin-node-resolve";
import typescriptPlugin from "rollup-plugin-typescript2";
import autoExternal from "rollup-plugin-auto-external";
import { terser } from "rollup-plugin-terser";
import pkg from "./package.json";

export default {
  input: "src/index.ts",
  output: [
    {
      file: pkg.main,
      format: "cjs",
      sourcemap: true
    },
    {
      file: pkg.module,
      format: "es",
      sourcemap: true
    }
  ],
  plugins: [
    autoExternal(),
    resolve({ preferBuiltins: true }),
    commonjs(),
    typescriptPlugin({ typescript, objectHashIgnoreUnknownHack: true }),
    terser()
  ]
};

You can find the entire code here

https://github.com/LukasBombach/sblendid/tree/master/packages/sblendid

Now, this setup does not work. Rollup tells me

$ rollup -c rollup.config.ts

src/index.ts → dist/index.cjs.js, dist/index.es.js...
(!) Mixing named and default exports
Consumers of your bundle will have to use bundle['default'] to access the default export, which may not be what you want. Use `output.exports: 'named'` to disable this warning

which is true. This

const Sblendid = require("@sblendid/sblendid");

simply does not work. What I have to do is this:

const Sblendid = require("@sblendid/sblendid").default;

I can fix this behavior by not mixing named ad default exports, ok, but then I lose the ability to do this:

import Sblendid, { Peripheral } from "@sblendid/sblendid";

So I am wondering. Is there any way, maybe using multiple bundles, I can achieve having users be able to do both:

// This
import Sblendid from "@sblendid/sblendid";
import Sblendid, { Peripheral } from "@sblendid/sblendid";

// And this
const Sblendid = require("@sblendid/sblendid");
const { Peripheral } = require("@sblendid/sblendid");
like image 820
Lukas Avatar asked Oct 05 '19 09:10

Lukas


People also ask

Can you mix named and default exports in a bundle?

(!) Mixing named and default exports Consumers of your bundle will have to use bundle ['default'] to access the default export, which may not be what you want. Use `output.exports: 'named'` to disable this warning

How can I accomplish this dual default/named export with ES5?

How can I accomplish this dual default/named export with ES5? Exports in ES6 (compiled with babel) export default to a property named default and set a property _esModule. When importing the default module, it will import default iff _esModule exists.

Can I mix named and default exports in a commonjs module?

The best you can do here is to use different entry points and propose named exports later. Though mixing named and default exports is still error prune. If commonjs module uses package with module field which has mixed named and default exports webpack produces broken output.

How many default exports can a module have?

modules can only have one default export. I prefer to use default exports when the exported component is only going to be imported once, or if a file exports one thing. A good example would be a Router component. You can combine default and named exports in a single file.


1 Answers

If you target only nodejs environment you can export like this (index.ts)

import Sblendid from "./sblendid";
import Peripheral from "./peripheral";

Sblendid.Peripheral = Peripheral;
export default Sblendid;
like image 199
uNmAnNeR Avatar answered Oct 19 '22 04:10

uNmAnNeR