Skip to content

Commit a3d1799

Browse files
committed
fix(nextjs): add extension alias support for handling ESM libs
1 parent 1e30f3d commit a3d1799

File tree

3 files changed

+72
-18
lines changed

3 files changed

+72
-18
lines changed

e2e/next/next-ts-solutions.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
cleanupProject,
3+
getPackageManagerCommand,
4+
newProject,
5+
readFile,
6+
runCLI,
7+
runCommand,
8+
uniq,
9+
updateFile,
10+
updateJson,
11+
} from '@nx/e2e/utils';
12+
describe('Next TS Solutions', () => {
13+
let proj: string;
14+
15+
beforeAll(() => {
16+
proj = newProject({
17+
packages: ['@nx/next'],
18+
preset: 'ts',
19+
});
20+
});
21+
afterAll(() => cleanupProject());
22+
23+
it('should support importing a esm library', async () => {
24+
const appName = uniq('app');
25+
const libName = uniq('lib');
26+
27+
runCLI(
28+
`generate @nx/next:app ${appName} --no-interactive --style=css --linter=none --unitTestRunner=none --e2eTestRunner=none`
29+
);
30+
31+
runCLI(
32+
`generate @nx/js:lib packages/${libName} --bundler=vite --no-interactive --unit-test-runner=none --skipFormat --linter=eslint`
33+
);
34+
35+
updateFile(
36+
`${appName}/src/app/page.tsx`,
37+
`
38+
import {${libName}} from '@${proj}/${libName}';
39+
${readFile(`${appName}/src/app/page.tsx`)}
40+
console.log(${libName}());
41+
`
42+
);
43+
runCLI('sync');
44+
45+
// Add library to package.json to make sure it is linked (not needed for npm package manager)
46+
updateJson(`${appName}/package.json`, (json) => {
47+
return {
48+
...json,
49+
devDependencies: {
50+
...(json.devDependencies || {}),
51+
[`@${proj}/${libName}`]: 'workspace:*',
52+
},
53+
};
54+
});
55+
56+
runCommand(`cd ${appName} && ${getPackageManagerCommand().install}`);
57+
58+
const output = runCLI(`build ${appName}`);
59+
expect(output).toContain(
60+
`Successfully ran target build for project @${proj}/${appName}`
61+
);
62+
});
63+
});

e2e/next/src/next.test.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
uniq,
1111
updateFile,
1212
} from '@nx/e2e/utils';
13-
import * as http from 'http';
1413
import { checkApp } from './utils';
1514

1615
describe('Next.js Applications', () => {
@@ -240,20 +239,3 @@ describe('Next.js Applications', () => {
240239
expect(postBuildPagesContent).toMatchSnapshot();
241240
});
242241
});
243-
244-
function getData(port, path = ''): Promise<any> {
245-
return new Promise((resolve, reject) => {
246-
http
247-
.get(`http://localhost:${port}${path}`, (res) => {
248-
expect(res.statusCode).toEqual(200);
249-
let data = '';
250-
res.on('data', (chunk) => {
251-
data += chunk;
252-
});
253-
res.once('end', () => {
254-
resolve(data);
255-
});
256-
})
257-
.on('error', (err) => reject(err));
258-
});
259-
}

packages/next/plugins/with-nx.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,15 @@ export function getNextConfig(
261261
},
262262
...validNextConfig,
263263
webpack: (config, options) => {
264+
/**
265+
* To support ESM library export, we need to ensure the extensionAlias contains both `.js` and `.ts` extensions.
266+
* This is because Webpack uses the `extensionAlias` to resolve the correct file extension when importing modules.
267+
*/
268+
config.resolve.extensionAlias = {
269+
...(config.resolve.extensionAlias || {}),
270+
'.js': ['.ts', '.js'],
271+
'.mjs': ['.mts', '.mjs'],
272+
};
264273
/*
265274
* Update babel to support our monorepo setup.
266275
* The 'upward' mode allows the root babel.config.json and per-project .babelrc files to be picked up.

0 commit comments

Comments
 (0)