diff --git a/contributors.yml b/contributors.yml index 4c632d504ae..4164fec2abb 100644 --- a/contributors.yml +++ b/contributors.yml @@ -209,6 +209,7 @@ - juwiragiye - jveldridge - jvnm-dev +- jwnx - kalch - kanermichael - karimsan diff --git a/packages/remix-dev/__tests__/readConfig-test.ts b/packages/remix-dev/__tests__/readConfig-test.ts index ddfed1ba54c..1b101f88624 100644 --- a/packages/remix-dev/__tests__/readConfig-test.ts +++ b/packages/remix-dev/__tests__/readConfig-test.ts @@ -21,6 +21,7 @@ describe("readConfig", () => { serverBuildPath: expect.any(String), assetsBuildDirectory: expect.any(String), relativeAssetsBuildDirectory: expect.any(String), + tsconfigPath: expect.any(String) }, ` Object { @@ -50,6 +51,7 @@ describe("readConfig", () => { "serverMode": "production", "serverModuleFormat": "cjs", "serverPlatform": "node", + "tsconfigPath": Any, "watchPaths": Array [], } ` diff --git a/packages/remix-dev/compiler.ts b/packages/remix-dev/compiler.ts index a2425c7ca82..b677af3ca97 100644 --- a/packages/remix-dev/compiler.ts +++ b/packages/remix-dev/compiler.ts @@ -368,6 +368,10 @@ async function createBrowserBuild( sourcemap: options.sourcemap, metafile: true, incremental: options.incremental, + // As pointed out by https://github.com/evanw/esbuild/issues/2440, when tsconfig is set to + // `undefined`, esbuild will keep looking for a tsconfig.json recursively up. This unwanted + // behavior can only be avoided by creating an empty tsconfig file in the root directory. + tsconfig: config.tsconfigPath, mainFields: ["browser", "module", "main"], treeShaking: true, minify: options.mode === BuildMode.Production, @@ -458,6 +462,10 @@ function createServerBuild( loader: loaders, bundle: true, logLevel: "silent", + // As pointed out by https://github.com/evanw/esbuild/issues/2440, when tsconfig is set to + // `undefined`, esbuild will keep looking for a tsconfig.json recursively up. This unwanted + // behavior can only be avoided by creating an empty tsconfig file in the root directory. + tsconfig: config.tsconfigPath, incremental: options.incremental, sourcemap: options.sourcemap, // use linked (true) to fix up .map file // The server build needs to know how to generate asset URLs for imports diff --git a/packages/remix-dev/compiler/plugins/mdx.ts b/packages/remix-dev/compiler/plugins/mdx.ts index 4ff210ec9f4..49e137b8a1a 100644 --- a/packages/remix-dev/compiler/plugins/mdx.ts +++ b/packages/remix-dev/compiler/plugins/mdx.ts @@ -17,7 +17,7 @@ export function mdxPlugin(config: RemixConfig): esbuild.Plugin { ]); build.onResolve({ filter: /\.mdx?$/ }, (args) => { - let matchPath = createMatchPath(); + let matchPath = createMatchPath(config.tsconfigPath); // Resolve paths according to tsconfig paths property function resolvePath(id: string) { if (!matchPath) { diff --git a/packages/remix-dev/compiler/plugins/serverBareModulesPlugin.ts b/packages/remix-dev/compiler/plugins/serverBareModulesPlugin.ts index 4e9fcffe17f..d5124b0a7df 100644 --- a/packages/remix-dev/compiler/plugins/serverBareModulesPlugin.ts +++ b/packages/remix-dev/compiler/plugins/serverBareModulesPlugin.ts @@ -23,7 +23,7 @@ export function serverBareModulesPlugin( let isDenoRuntime = remixConfig.serverBuildTarget === "deno"; // Resolve paths according to tsconfig paths property - let matchPath = isDenoRuntime ? undefined : createMatchPath(); + let matchPath = isDenoRuntime ? undefined : createMatchPath(remixConfig.tsconfigPath); function resolvePath(id: string) { if (!matchPath) { return id; diff --git a/packages/remix-dev/compiler/utils/tsconfig/index.ts b/packages/remix-dev/compiler/utils/tsconfig/index.ts index 8836e7a472f..559a34e8800 100644 --- a/packages/remix-dev/compiler/utils/tsconfig/index.ts +++ b/packages/remix-dev/compiler/utils/tsconfig/index.ts @@ -2,8 +2,17 @@ import tsConfigPaths from "tsconfig-paths"; import { writeConfigDefaults } from "./write-config-defaults"; -export function createMatchPath() { - let configLoaderResult = tsConfigPaths.loadConfig(); +export function createMatchPath(tsconfigPath: string | undefined) { + // There is no tsconfig to match paths against. + if (!tsconfigPath) { + return undefined; + } + + // When passing a absolute path, loadConfig assumes that the path contains + // a tsconfig file. + // Ref.: https://github.com/dividab/tsconfig-paths/blob/v4.0.0/src/__tests__/config-loader.test.ts#L74 + let configLoaderResult = tsConfigPaths.loadConfig(tsconfigPath); + if (configLoaderResult.resultType === "failed") { if (configLoaderResult.message === "Missing baseUrl in compilerOptions") { throw new Error( diff --git a/packages/remix-dev/config.ts b/packages/remix-dev/config.ts index 6c2a110ed7f..39d87a89f29 100644 --- a/packages/remix-dev/config.ts +++ b/packages/remix-dev/config.ts @@ -269,6 +269,11 @@ export interface RemixConfig { * A list of directories to watch. */ watchPaths: string[]; + + /** + * The path for the tsconfig file, if present on the root directory. + */ + tsconfigPath: string | undefined; } /** @@ -450,6 +455,18 @@ export async function readConfig( let serverDependenciesToBundle = appConfig.serverDependenciesToBundle || []; + // When tsconfigPath is undefined, the default "tsconfig.json" is not + // found in the root directory. + let tsconfigPath: string | undefined; + let rootTsconfig = path.resolve(rootDirectory, "tsconfig.json"); + let rootJsConfig = path.resolve(rootDirectory, "jsconfig.json"); + + if (fse.existsSync(rootTsconfig)) { + tsconfigPath = rootTsconfig; + } else if (fse.existsSync(rootJsConfig)) { + tsconfigPath = rootJsConfig; + } + return { appDirectory, cacheDirectory, @@ -472,6 +489,7 @@ export async function readConfig( serverDependenciesToBundle, mdx, watchPaths, + tsconfigPath, }; }