aleclarson / vite-tsconfig-paths

Support for TypeScript's path mapping in Vite
MIT License
1.28k stars 45 forks source link

ESModules: tsconfigPaths is not a function; no default export #23

Closed josh-hemphill closed 3 years ago

josh-hemphill commented 3 years ago

In an ESModule project, the default export is { default: [Function (anonymous)] } which also breaks type information in ESM Typescript projects.

I've had to do this to work around it:

import _tsconfigPaths from 'vite-tsconfig-paths';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
const tsconfigPaths: typeof _tsconfigPaths = _tsconfigPaths.default;

Perhaps the easiest solution would be to create two dist bundles, one classic Node and one ESM. In trying to make my own vite plugins and looking at the others out there, creating two bundles seems to be pretty ubiquitous.

Reproduction: https://github.com/josh-hemphill/vite-tsconfig-paths/tree/esm-errored

aleclarson commented 3 years ago

Please reproduce the issue in the ./demo folder of this repo.

josh-hemphill commented 3 years ago

@aleclarson Here's the requested reproduction: https://github.com/josh-hemphill/vite-tsconfig-paths/tree/esm-errored

aleclarson commented 3 years ago

What's the use case for "type": "module" with a Vite project? Are you using lib mode?

josh-hemphill commented 3 years ago

Currently, no, I just prefer running with "type": "module" across everything, though I'm sure at some point I will. I've been migrating from Webpack and my project is already "type": "module" so I'd like avoid having to also migrate backwards to "type": "commonjs"

aleclarson commented 3 years ago

creating two bundles seems to be pretty ubiquitous

It doesn't appear that Vite's official plugins do this.

But @vitejs/plugin-vue does the following:

// Taken from: https://unpkg.com/browse/@vitejs/plugin-vue@1.2.2/dist/index.js
module.exports = vuePlugin;
vuePlugin["default"] = vuePlugin;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  parseVueRequest
});

Though I'm not sure how that last statement gets there, as it's missing from the source code: https://github.com/vitejs/vite/blob/ad5d28d1fcd027e9c92c1447698b27f3da6655a4/packages/plugin-vue/src/index.ts#L167-L169

josh-hemphill commented 3 years ago

Well they're using esbuild for the bundle generation and tsc just for the declartaions, so presumably it's an artifact of esbuild. A couple of the vite plugins I've seen have been using tsup to build which automatically generates an es and commonjs bundles. I've been working on a favicon plugin and tsup has been pretty nice (though purposefully lacking in configuration, which did cause me to need to copy over any external declarations during build that I wanted to re-export if I was building from ESM)

aleclarson commented 3 years ago

I'd be open to a PR that adds tsup