diff --git a/src/loader.ts b/src/loader.ts index c8453b3..fe63d0b 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -81,8 +81,21 @@ async function ESBuildLoader( } else { /* Detect tsconfig file */ - // Webpack shouldn't be loading the same path multiple times so doesn't need to be cached - const tsconfig = getTsconfig(resourcePath, 'tsconfig.json', tsconfigCache); + let tsconfig; + + try { + // Webpack shouldn't be loading the same path multiple times so doesn't need to be cached + tsconfig = getTsconfig(resourcePath, 'tsconfig.json', tsconfigCache); + } catch (error) { + if (resourcePath.split(path.sep).includes('node_modules')) { + this.emitWarning( + new Error(`[esbuild-loader] Error while discovering tsconfig.json in dependency: "${error?.toString()}"`), + ); + } else { + throw error; + } + } + if (tsconfig) { const fileMatcher = createFilesMatcher(tsconfig); transformOptions.tsconfigRaw = fileMatcher(resourcePath) as TransformOptions['tsconfigRaw']; diff --git a/tests/specs/tsconfig.ts b/tests/specs/tsconfig.ts index e517a10..f40ba4d 100644 --- a/tests/specs/tsconfig.ts +++ b/tests/specs/tsconfig.ts @@ -2,7 +2,7 @@ import path from 'path'; import { createRequire } from 'node:module'; import { testSuite, expect } from 'manten'; import { createFixture } from 'fs-fixture'; -import { execa } from 'execa'; +import { execa, type ExecaError } from 'execa'; import { tsconfigJson } from '../utils.js'; const webpackCli = path.resolve('node_modules/webpack-cli/bin/cli.js'); @@ -263,6 +263,80 @@ export default testSuite(({ describe }) => { const code2 = await fixture.readFile('dist/index2.js', 'utf8'); expect(code2).toMatch('__publicField(this, "foo", 100);'); }); + + test('ignores tsconfig.json in third party dependencies', async () => { + await using fixture = await createFixture({ + // Fake external dependency + node_modules: { + 'fake-lib': { + 'index.ts': 'export function testFn(): string { return "Hi!" }', + 'package.json': JSON.stringify({ + name: 'fake-lib', + }), + 'tsconfig.json': tsconfigJson({ + extends: 'something-imaginary', + }), + }, + }, + // Our project + src: { + 'index.ts': ` + import { testFn } from "fake-lib"; + + export default testFn;`, + }, + 'webpack.config.js': ` + module.exports = { + mode: 'production', + + optimization: { + minimize: false, + }, + + resolveLoader: { + alias: { + 'esbuild-loader': ${JSON.stringify(esbuildLoader)}, + }, + }, + + resolve: { + extensions: ['.ts', '.js'], + }, + + module: { + rules: [ + { + test: /.[tj]sx?$/, + loader: 'esbuild-loader', + options: { + target: 'es2015', + } + } + ], + }, + + entry: { + index: './src/index.ts', + }, + }; + `, + }); + + let result; + + try { + result = await execa(webpackCli, { + cwd: fixture.path, + }); + } catch (error) { + result = error as ExecaError; + } + const { exitCode, stdout } = result; + + // We log this as a warning, and continue the transform + expect(stdout).toMatch("Error while discovering tsconfig.json in dependency: \"Error: File 'something-imaginary' not found.\""); + expect(exitCode).toEqual(0); + }); }); describe('plugin', ({ test }) => {