egoist / tsup

The simplest and fastest way to bundle your TypeScript libraries.
https://tsup.egoist.dev
MIT License
9.25k stars 218 forks source link

Specify JSX Runtime? #390

Closed ericclemmons closed 2 years ago

ericclemmons commented 3 years ago

Thanks for creating this! I had issues with vite and generating .d.ts files, but tsup has been working great!

The only thing I noticed with my React library are these errors:

ReferenceError: React is not defined

Adding import * as React from 'react'; at the top of each file fixes it.

But based on https://github.com/developit/microbundle/issues/763#issuecomment-877388109, I was wondering if it'd be possible to do something similar like:

tsup --jsx 'React.createElement' --jsxImportSource react --globals react/jsx-runtime=jsx
ericclemmons commented 3 years ago

Just learned vite does something similar for esbuild: https://github.com/vitejs/vite/blob/a0d922e7d9790f998c246f8122bc339717b6088f/packages/vite/src/node/plugins/esbuild.ts#L125

ericclemmons commented 3 years ago

Hey, this works with https://esbuild.github.io/content-types/#auto-import-for-jsx's recommendation:

diff --git a/node_modules/tsup/dist/index.js b/node_modules/tsup/dist/index.js
index 1fd3ea9..8f84cf0 100644
--- a/node_modules/tsup/dist/index.js
+++ b/node_modules/tsup/dist/index.js
@@ -13633,6 +13633,7 @@ async function runEsbuild(options, { format, css }) {
       jsxFactory: options.jsxFactory,
       jsxFragment: options.jsxFragment,
       sourcemap: options.sourcemap,
+      inject: ['./src/react-shim.js'],
       target: options.target === "es5" ? "es2016" : options.target,
       plugins: [
         externalPlugin({

Of course, this is better as inject: options.inject, but with https://github.com/ds300/patch-package I'm able to get this working.

What do do you think is the best way around this?

arantespp commented 3 years ago

I'm facing the same issue, and the solution provided by @ericclemmons (thanks!) worked for me. If you need, I can help with a PR to fix this.

csantos1113 commented 3 years ago

here is the diff for v5.1.0 exposing a inject option prop, if someone needs it

diff --git a/dist/cli-default.js b/dist/cli-default.js
index fbe5e43883a865ba9a6f4e255f843ee0178ed200..22efa088e00fad2ef3c9aed980c86662d93cb601 100755
--- a/dist/cli-default.js
+++ b/dist/cli-default.js
@@ -15838,7 +15838,7 @@ async function runEsbuild(options, { format, css }) {
       }, {})),
       inject: [
         format === "cjs" ? (0, import_path4.join)(__dirname, "../assets/cjs_shims.js") : ""
-      ].filter(Boolean),
+      ].concat(options.inject || []).filter(Boolean),
       outdir: options.legacyOutput && format !== "cjs" ? (0, import_path4.join)(outDir, format) : outDir,
       outExtension: options.legacyOutput ? void 0 : outExtension,
       write: false,
diff --git a/dist/cli-main.js b/dist/cli-main.js
index 0313798aa5ea9847166d17f616921e7292dca42a..791597b12ea0b9f073d7df6cc6a2ffaff6cc15f9 100644
--- a/dist/cli-main.js
+++ b/dist/cli-main.js
@@ -15816,6 +15816,7 @@ async function runEsbuild(options, { format, css }) {
       jsxFactory: options.jsxFactory,
       jsxFragment: options.jsxFragment,
       sourcemap: options.sourcemap,
+      inject: options.inject,
       target: options.target === "es5" ? "es2016" : options.target,
       plugins: [
         externalPlugin({
diff --git a/dist/cli-node.js b/dist/cli-node.js
index 193ada3f7aad06737b25ad2e8a68d7df51d26757..8f3292d95c5c41cb353487046c84020584f56798 100755
--- a/dist/cli-node.js
+++ b/dist/cli-node.js
@@ -15838,7 +15838,7 @@ async function runEsbuild(options, { format, css }) {
       }, {})),
       inject: [
         format === "cjs" ? (0, import_path4.join)(__dirname, "../assets/cjs_shims.js") : ""
-      ].filter(Boolean),
+      ].concat(options.inject || []).filter(Boolean),
       outdir: options.legacyOutput && format !== "cjs" ? (0, import_path4.join)(outDir, format) : outDir,
       outExtension: options.legacyOutput ? void 0 : outExtension,
       write: false,
diff --git a/dist/index.d.ts b/dist/index.d.ts
index 88f77275d8f6de223110bf039297719a081121f8..7256612d02750d5c4faf8a3a27699cb3636e001e 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -24,6 +24,7 @@ declare type Options = {
     keepNames?: boolean;
     watch?: boolean | string | (string | boolean)[];
     ignoreWatch?: string[] | string;
+    inject?: string[];
     onSuccess?: string;
     jsxFactory?: string;
     jsxFragment?: string;
diff --git a/dist/index.js b/dist/index.js
index 2d3b1e761709a2333871e805f41f4b18ff7410b1..1c1406306e9b9cbca48e689725650ff3d7bce4ff 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -15828,7 +15828,7 @@ async function runEsbuild(options, { format, css }) {
       }, {})),
       inject: [
         format === "cjs" ? (0, import_path4.join)(__dirname, "../assets/cjs_shims.js") : ""
-      ].filter(Boolean),
+      ].concat(options.inject || []).filter(Boolean),
       outdir: options.legacyOutput && format !== "cjs" ? (0, import_path4.join)(outDir, format) : outDir,
       outExtension: options.legacyOutput ? void 0 : outExtension,
       write: false,
darklight9811 commented 3 years ago

I'm working with vite and preact, I'm currently manually adding the import { h } from "preact" line in every file it generates. But really would like for a better way to do this.

egoist commented 3 years ago

Now in v5.3.0 you can use the --inject flag or the inject option to achieve this:

tsup --inject ./react-import.js
// react-import.js
import React from 'react'

export { React }

or for preact:

import { h, Fragment } from 'preact'

export { h, Fragment }

But ideally, in the future, we should read jsxImportSource from tsconfig.json and automatically do this for you.

darklight9811 commented 3 years ago

@egoist the documentation is missing a lot of important information, things that I discovered reading the source code. It also doesn't say anything about inject

ericclemmons commented 2 years ago

This works! Thanks!