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");
(!) 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? 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.
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.
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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With