diff --git a/CHANGELOG.md b/CHANGELOG.md index 42ac39fb09a..5a0ce71b59d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,12 @@ This approach should ensure maximum compatibility with all JavaScript environments that support ES5 and above. Note that this means minified files containing Unicode properties may be slightly larger than before. +* Ignore `tsconfig.json` files inside `node_modules` ([#1355](https://github.com/evanw/esbuild/issues/1355)) + + Package authors often publish their `tsconfig.json` files to npm because of npm's default-include publishing model and because these authors probably don't know about `.npmignore` files. People trying to use these packages with esbuild have historically complained that esbuild is respecting `tsconfig.json` in these cases. The assumption is that the package author published these files by accident. + + With this release, esbuild will no longer respect `tsconfig.json` files when the source file is inside a `node_modules` folder. Note that `tsconfig.json` files inside `node_modules` are still parsed, and extending `tsconfig.json` files from inside a package is still supported. + ## 0.12.6 * Improve template literal lowering transformation conformance ([#1327](https://github.com/evanw/esbuild/issues/1327)) diff --git a/internal/bundler/bundler_tsconfig_test.go b/internal/bundler/bundler_tsconfig_test.go index 2074911fd19..4638fe5aaaf 100644 --- a/internal/bundler/bundler_tsconfig_test.go +++ b/internal/bundler/bundler_tsconfig_test.go @@ -994,6 +994,31 @@ func TestTsconfigJsonNodeModulesImplicitFile(t *testing.T) { }) } +func TestTsconfigJsonInsideNodeModules(t *testing.T) { + tsconfig_suite.expectBundled(t, bundled{ + files: map[string]string{ + "/Users/user/project/src/app/entry.tsx": ` + import 'foo' + `, + "/Users/user/project/src/node_modules/foo/index.tsx": ` + console.log(
) + `, + "/Users/user/project/src/node_modules/foo/tsconfig.json": ` + { + "compilerOptions": { + "jsxFactory": "TEST_FAILED" + } + } + `, + }, + entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, + options: config.Options{ + Mode: config.ModeBundle, + AbsOutputFile: "/Users/user/project/out.js", + }, + }) +} + func TestTsconfigWarningsInsideNodeModules(t *testing.T) { tsconfig_suite.expectBundled(t, bundled{ files: map[string]string{ diff --git a/internal/bundler/snapshots/snapshots_tsconfig.txt b/internal/bundler/snapshots/snapshots_tsconfig.txt index 82d3466b450..5794947c22b 100644 --- a/internal/bundler/snapshots/snapshots_tsconfig.txt +++ b/internal/bundler/snapshots/snapshots_tsconfig.txt @@ -279,6 +279,12 @@ console.log("works"); // Users/user/project/src/entry.jsx console.log(/* @__PURE__ */ baseFactory("div", null), /* @__PURE__ */ baseFactory(derivedFragment, null)); +================================================================================ +TestTsconfigJsonInsideNodeModules +---------- /Users/user/project/out.js ---------- +// Users/user/project/src/node_modules/foo/index.tsx +console.log(/* @__PURE__ */ React.createElement("div", null)); + ================================================================================ TestTsconfigJsonNodeModulesImplicitFile ---------- /Users/user/project/out.js ---------- diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index 7ef94d69a21..b69b807a9fb 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -499,24 +499,46 @@ func (r resolverQuery) finalizeResolve(result *ResolveResult) { // Copy various fields from the nearest enclosing "tsconfig.json" file if present if path == &result.PathPair.Primary && dirInfo.enclosingTSConfigJSON != nil { - result.JSXFactory = dirInfo.enclosingTSConfigJSON.JSXFactory - result.JSXFragment = dirInfo.enclosingTSConfigJSON.JSXFragmentFactory - result.UseDefineForClassFieldsTS = dirInfo.enclosingTSConfigJSON.UseDefineForClassFields - result.PreserveUnusedImportsTS = dirInfo.enclosingTSConfigJSON.PreserveImportsNotUsedAsValues - result.TSTarget = dirInfo.enclosingTSConfigJSON.TSTarget - - if r.debugLogs != nil { - r.debugLogs.addNote(fmt.Sprintf("This import is under the effect of %q", - dirInfo.enclosingTSConfigJSON.AbsPath)) - if result.JSXFactory != nil { - r.debugLogs.addNote(fmt.Sprintf("\"jsxFactory\" is %q due to %q", - strings.Join(result.JSXFactory, "."), - dirInfo.enclosingTSConfigJSON.AbsPath)) + // Except don't do this if we're inside a "node_modules" directory. Package + // authors often publish their "tsconfig.json" files to npm because of + // npm's default-include publishing model and because these authors + // probably don't know about ".npmignore" files. + // + // People trying to use these packages with esbuild have historically + // complained that esbuild is respecting "tsconfig.json" in these cases. + // The assumption is that the package author published these files by + // accident. + // + // Ignoring "tsconfig.json" files inside "node_modules" directories breaks + // the use case of publishing TypeScript code and having it be transpiled + // for you, but that's the uncommon case and likely doesn't work with + // many other tools anyway. So now these files are ignored. + if helpers.IsInsideNodeModules(result.PathPair.Primary.Text) { + if r.debugLogs != nil { + r.debugLogs.addNote(fmt.Sprintf("Ignoring %q because %q is inside \"node_modules\"", + dirInfo.enclosingTSConfigJSON.AbsPath, + result.PathPair.Primary.Text)) } - if result.JSXFragment != nil { - r.debugLogs.addNote(fmt.Sprintf("\"jsxFragment\" is %q due to %q", - strings.Join(result.JSXFragment, "."), + } else { + result.JSXFactory = dirInfo.enclosingTSConfigJSON.JSXFactory + result.JSXFragment = dirInfo.enclosingTSConfigJSON.JSXFragmentFactory + result.UseDefineForClassFieldsTS = dirInfo.enclosingTSConfigJSON.UseDefineForClassFields + result.PreserveUnusedImportsTS = dirInfo.enclosingTSConfigJSON.PreserveImportsNotUsedAsValues + result.TSTarget = dirInfo.enclosingTSConfigJSON.TSTarget + + if r.debugLogs != nil { + r.debugLogs.addNote(fmt.Sprintf("This import is under the effect of %q", dirInfo.enclosingTSConfigJSON.AbsPath)) + if result.JSXFactory != nil { + r.debugLogs.addNote(fmt.Sprintf("\"jsxFactory\" is %q due to %q", + strings.Join(result.JSXFactory, "."), + dirInfo.enclosingTSConfigJSON.AbsPath)) + } + if result.JSXFragment != nil { + r.debugLogs.addNote(fmt.Sprintf("\"jsxFragment\" is %q due to %q", + strings.Join(result.JSXFragment, "."), + dirInfo.enclosingTSConfigJSON.AbsPath)) + } } } }