Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Named exports as default export #26

Open
niksy opened this issue May 19, 2020 · 4 comments
Open

Named exports as default export #26

niksy opened this issue May 19, 2020 · 4 comments

Comments

@niksy
Copy link

niksy commented May 19, 2020

native-url exposes methods thorugh named exports. To get default Node url behavior you would need to import entire module contents

import * as url from 'native-url'; // or 'url' if aliased`

This is fine for your own code, but dependencies will throw error since they can’t find default export by default, and most 3rd party code using Node url depend on that default export to be available.

To fix this, it’s best to make changes to code at compile time to expose every named export as property of object which should be default export.

Here is a Babel plugin code which achieves that:

const babel = require('@babel/core');

const plugin = babel.createConfigItem(({ types: t }) => {
	return {
		visitor: {
			ExportNamedDeclaration(path, parent) {
				const properties = path.node.specifiers.map((node) => ({
					exported: node.exported.name,
					local: node.local.name
				}));
				path.insertAfter(
					t.exportDefaultDeclaration(
						t.objectExpression(
							properties.map((prop) =>
								t.objectProperty(
									t.identifier(prop.exported),
									t.identifier(prop.local)
								)
							)
						)
					)
				);
			}
		}
	};
});

And here is how you apply it with Webpack:

{
	test: /\.m?js$/,
	include: /node_modules\/native-url/,
	use: [
		{
			loader: 'babel-loader',
			options: {
				plugins: [plugin]
			}
		}
	]
};

After that you can use both modules’ named exports as default export.

Is this something which should be documented for both Webpack and Rollup, or should native-url expose default export by default?

@janicklas-ralph
Copy link
Collaborator

The exports are the same as the default node-url library which webpack uses when bundling for client

I'm assuming everyone developed their libraries based on node-url's export interface (which is the same as url) coupled with babel and Webpack/rollup to handle the resolution? If thats the case this won't be an issue.

I'm curious to know cases when people have used the default import, since both url and node-url don't support it?

Please let me know

@niksy
Copy link
Author

niksy commented May 20, 2020

@janicklas-ralph

This doesn’t throw warning:

const url = require('url');

This does throw warning:

import url from `url`;
Hash: 30643d8377069131206c
Version: webpack 4.43.0
Time: 113ms
Built at: 2020-05-20 11:16:05
 Asset      Size  Chunks             Chunk Names
out.js  14.4 KiB       0  [emitted]  main
Entrypoint main = out.js
[./index.js] 125 bytes {0} [built]
    + 5 hidden modules

WARNING in ./index.js 4:0-3
"export 'default' (imported as 'url') was not found in 'url'

WARNING in ./node_modules/dependancy/index.js 3:0-3
"export 'default' (imported as 'url') was not found in 'url'
 @ ./index.js

Documentation is misleading in saying this:

With this in place, import url from 'url' will use native-url and keep your bundle small.

@developit
Copy link
Collaborator

developit commented May 26, 2020

This happens because the module is being imported as ESM. node-url is only published as CJS, so it always triggers emulated exports.default in Webpack.

@janicklas-ralph - It might be worth removing the module entry to make it exactly the same as node-url? This would cause import * as and import to work identically.

@niksy
Copy link
Author

niksy commented May 27, 2020

@developit maybe export object (with all named exports as properties of that object) as default export and rely on tree-shaking from bundlers for any unwanted exports?

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

No branches or pull requests

3 participants