Skip to content

Commit

Permalink
Support tsconfig paths without baseurl (#34926)
Browse files Browse the repository at this point in the history
tsconfig behaves differently with `tsc` vs. Next.js. When `baseurl` is omitted, `paths` should be resolved against the tsconfig location. Consequentially, in this case the paths must start with `./`. This PR aligns Next.js behavior with `tsc` around `paths` without `baseurl`. 

Related: microsoft/TypeScript#40101
  • Loading branch information
Janpot committed Aug 15, 2022
1 parent e0d7ee0 commit 683db9a
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 5 deletions.
12 changes: 10 additions & 2 deletions packages/next/build/load-jsconfig.ts
Expand Up @@ -49,6 +49,7 @@ export default async function loadJsConfig(
typeScriptPath && (await fileExists(tsConfigPath))
)

let implicitBaseurl
let jsConfig
// jsconfig is a subset of tsconfig
if (useTypeScript) {
Expand All @@ -65,17 +66,24 @@ export default async function loadJsConfig(
)) as typeof import('typescript')
const tsConfig = await getTypeScriptConfiguration(ts, tsConfigPath, true)
jsConfig = { compilerOptions: tsConfig.options }
implicitBaseurl = path.dirname(tsConfigPath)
}

const jsConfigPath = path.join(dir, 'jsconfig.json')
if (!useTypeScript && (await fileExists(jsConfigPath))) {
jsConfig = parseJsonFile(jsConfigPath)
implicitBaseurl = path.dirname(jsConfigPath)
}

let resolvedBaseUrl
if (jsConfig?.compilerOptions?.baseUrl) {
resolvedBaseUrl = path.resolve(dir, jsConfig.compilerOptions.baseUrl)
if (jsConfig) {
if (jsConfig.compilerOptions?.baseUrl) {
resolvedBaseUrl = path.resolve(dir, jsConfig.compilerOptions.baseUrl)
} else {
resolvedBaseUrl = implicitBaseurl
}
}

return {
useTypeScript,
jsConfig,
Expand Down
31 changes: 30 additions & 1 deletion test/integration/jsconfig-paths/test/index.test.js
Expand Up @@ -3,14 +3,17 @@
import fs from 'fs-extra'
import { join } from 'path'
import cheerio from 'cheerio'
import * as path from 'path'
import {
renderViaHTTP,
findPort,
launchApp,
nextBuild,
killApp,
check,
File,
} from 'next-test-utils'
import * as JSON5 from 'json5'

const appDir = join(__dirname, '..')
let appPort
Expand All @@ -21,7 +24,7 @@ async function get$(path, query) {
return cheerio.load(html)
}

describe('TypeScript Features', () => {
function runTests() {
describe('default behavior', () => {
let output = ''

Expand Down Expand Up @@ -141,4 +144,30 @@ describe('TypeScript Features', () => {
).toBe(false)
})
})
}

describe('jsconfig paths', () => {
runTests()
})

const jsconfig = new File(path.resolve(__dirname, '../jsconfig.json'))

describe('jsconfig paths without baseurl', () => {
beforeAll(() => {
const jsconfigContent = JSON5.parse(jsconfig.originalContent)
delete jsconfigContent.compilerOptions.baseUrl
jsconfigContent.compilerOptions.paths = {
'@c/*': ['./components/*'],
'@lib/*': ['./lib/a/*', './lib/b/*'],
'@mycomponent': ['./components/hello.js'],
'*': ['./node_modules/*'],
}
jsconfig.write(JSON.stringify(jsconfigContent, null, 2))
})

afterAll(() => {
jsconfig.restore()
})

runTests()
})
42 changes: 40 additions & 2 deletions test/integration/typescript-paths/test/index.test.js
Expand Up @@ -2,7 +2,15 @@

import { join } from 'path'
import cheerio from 'cheerio'
import { renderViaHTTP, findPort, launchApp, killApp } from 'next-test-utils'
import * as path from 'path'
import {
renderViaHTTP,
findPort,
launchApp,
killApp,
File,
} from 'next-test-utils'
import * as JSON5 from 'json5'

const appDir = join(__dirname, '..')
let appPort
Expand All @@ -13,7 +21,7 @@ async function get$(path, query) {
return cheerio.load(html)
}

describe('TypeScript Features', () => {
function runTests() {
describe('default behavior', () => {
beforeAll(async () => {
appPort = await findPort()
Expand Down Expand Up @@ -46,4 +54,34 @@ describe('TypeScript Features', () => {
expect($('body').text()).toMatch(/Not aliased to d\.ts file/)
})
})
}

describe('typescript paths', () => {
runTests()
})

const tsconfig = new File(path.resolve(__dirname, '../tsconfig.json'))

describe('typescript paths without baseurl', () => {
beforeAll(async () => {
const tsconfigContent = JSON5.parse(tsconfig.originalContent)
delete tsconfigContent.compilerOptions.baseUrl
tsconfigContent.compilerOptions.paths = {
'isomorphic-unfetch': ['./types/unfetch.d.ts'],
'@c/*': ['./components/*'],
'@lib/*': ['./lib/a/*', './lib/b/*'],
'@mycomponent': ['./components/hello.tsx'],
'd-ts-alias': [
'./components/alias-to-d-ts.d.ts',
'./components/alias-to-d-ts.tsx',
],
}
tsconfig.write(JSON.stringify(tsconfigContent, null, 2))
})

afterAll(() => {
tsconfig.restore()
})

runTests()
})

0 comments on commit 683db9a

Please sign in to comment.