diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index b85a2de2cf281..1f97ed0bfce7c 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -732,7 +732,7 @@ export default async function getBaseWebpackConfig( const emacsLockfilePattern = '**/.#*' - // Allowing importing TS/TSX files from outside of the project dir. + // Allowing importing TS/TSX files from outside of the root dir. let externalDir if (config.experimental.externalDir) { externalDir = path.join(dir, config.experimental.externalDir) diff --git a/test/integration/typescript-external-dir/project/components/world.tsx b/test/integration/typescript-external-dir/project/components/world.tsx new file mode 100644 index 0000000000000..d7d1f66258c77 --- /dev/null +++ b/test/integration/typescript-external-dir/project/components/world.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export function World(): JSX.Element { + return <>World +} diff --git a/test/integration/typescript-external-dir/project/next.config.js b/test/integration/typescript-external-dir/project/next.config.js new file mode 100644 index 0000000000000..a25af57d55d8b --- /dev/null +++ b/test/integration/typescript-external-dir/project/next.config.js @@ -0,0 +1,9 @@ +module.exports = { + onDemandEntries: { + // Make sure entries are not getting disposed. + maxInactiveAge: 1000 * 60 * 60, + }, + experimental: { + externalDir: '../shared', + }, +} diff --git a/test/integration/typescript-external-dir/project/pages/index.tsx b/test/integration/typescript-external-dir/project/pages/index.tsx new file mode 100644 index 0000000000000..c391ff332ff2a --- /dev/null +++ b/test/integration/typescript-external-dir/project/pages/index.tsx @@ -0,0 +1,16 @@ +import React from 'react' + +import { World } from 'components/world' + +// External +import { Counter } from '../../shared/components/counter' + +export default function HelloPage(): JSX.Element { + return ( +
+ Hello ! +
+ +
+ ) +} diff --git a/test/integration/typescript-external-dir/project/test/index.test.js b/test/integration/typescript-external-dir/project/test/index.test.js new file mode 100644 index 0000000000000..b9205057c34df --- /dev/null +++ b/test/integration/typescript-external-dir/project/test/index.test.js @@ -0,0 +1,31 @@ +/* eslint-env jest */ + +import { join } from 'path' +import cheerio from 'cheerio' +import { renderViaHTTP, findPort, launchApp, killApp } from 'next-test-utils' + +jest.setTimeout(1000 * 60 * 2) + +const appDir = join(__dirname, '..') +let appPort +let app + +async function get$(path, query) { + const html = await renderViaHTTP(appPort, path, query) + return cheerio.load(html) +} + +describe('TypeScript Features', () => { + describe('default behavior', () => { + beforeAll(async () => { + appPort = await findPort() + app = await launchApp(appDir, appPort, {}) + }) + afterAll(() => killApp(app)) + + it('should render the page with external TS/TSX dependencies', async () => { + const $ = await get$('/') + expect($('body').text()).toMatch(/Hello World!Counter: 0/) + }) + }) +}) diff --git a/test/integration/typescript-external-dir/project/tsconfig.json b/test/integration/typescript-external-dir/project/tsconfig.json new file mode 100644 index 0000000000000..dce2837cb1bcc --- /dev/null +++ b/test/integration/typescript-external-dir/project/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "esModuleInterop": true, + "module": "esnext", + "jsx": "preserve", + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true + }, + "exclude": ["node_modules"], + "include": ["next-env.d.ts", "components", "pages"] +} diff --git a/test/integration/typescript-external-dir/shared/components/counter.tsx b/test/integration/typescript-external-dir/shared/components/counter.tsx new file mode 100644 index 0000000000000..1740cf121827b --- /dev/null +++ b/test/integration/typescript-external-dir/shared/components/counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react' + +import inc from '../libs/inc' + +export function Counter(): JSX.Element { + const [x, setX] = useState(0) + return ( + + ) +} diff --git a/test/integration/typescript-external-dir/shared/libs/inc.ts b/test/integration/typescript-external-dir/shared/libs/inc.ts new file mode 100644 index 0000000000000..384bbfd6b7eb5 --- /dev/null +++ b/test/integration/typescript-external-dir/shared/libs/inc.ts @@ -0,0 +1,3 @@ +export default function inc(x: number) { + return x + 1 +} diff --git a/test/integration/typescript-external-dir/shared/tsconfig.json b/test/integration/typescript-external-dir/shared/tsconfig.json new file mode 100644 index 0000000000000..de0655b2346cb --- /dev/null +++ b/test/integration/typescript-external-dir/shared/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "module": "esnext", + "jsx": "preserve", + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true + }, + "include": ["components", "libs"] +}