NX Workspace #3673
Replies: 1 comment
-
Example contents// tsconfig.base.json // tsconfig.build.base.json // libs/core/tsconfig.json (solution file) // libs/core/tsconfig.lib.json // libs/core/tsconfig.dev.json // libs/core/tsconfig.spec.json Tips if save-time re-checking still feels slow
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Bundling
Started with path alias, but this is still treated as 1 giant bundle
Project references is the way to go, for incremental bundle, treated as individual bundle. This was added later on
https://nx.dev/blog/managing-ts-packages-in-monorepos
https://nx.dev/blog/new-nx-experience-for-typescript-monorepos
Module Resolution
app
need to havepackage.json
withdevDependencies
that reference local package perpnpm
For extending package imports, we use use
package.json
only it seems without modifyingtsconfig.json
We migrated over the project reference, but found
ESLint
apps/web/tsconfig.json contains a references array, so TypeScript treats it as a “solution‑style” file whose main job is to point at sub‑projects (tsconfig.lib.json, tsconfig.spec.json, …).
• At the same time it still has an include list with **/*.tsx, so TypeScript also sees it as a real source project.
• When a file (e.g. app/(dashboard)/(authenticated)/admin/default.tsx) is seen in both the root project and one of the referenced projects, the compiler deduplicates it and keeps it only in the referenced project.
Result: the Program built from tsconfig.json no longer contains that file, so TypeScript‑ESLint throws
“TSConfig does not include this file”.
This behaviour is documented in the TypeScript repo; the common fix is to empty out include/files in the solution config so it’s only an aggregator
ESM
After a few days of research I was able to understand a little more about the difference between module and moduleResolution in tsconfig settings. It seems that even putting moduleResolution: "node" the typescript understands it as if it were CommonJS. To be interpreted as ESM moduleResolution has to be set to "NodeNext" in typescript versions 4.5 onwards. So to convert my whole project to ESM I defined "type": "module" in the package.json file as well. A better explanation:
client server schema
I just ran into the same error and think I know what's going on. If you have a server action or a server component that imports a zod schema from a file that is a marked as a client component or client entry point, it will throw an error. If you move the schema declaration to a seperate file that only runs on the server, or make the file containing the schema a server component it should fix it. You should then be able to import the schema and use it from a client or server component.
I'm running into lots of problem like this when working with server components and passing data to client components. Particularly with tanstack table and their create column helper.
typecheck
buildLibsFromSource
For nextjs dev it's better to have turbopack compile everything, it's quite fast. The issue we're having now is production build on CI, it's quite slow.
If we turn
buildLibsFromSource
off, then have vite build the libs, it will be much fasterIf we want to use buildable libs, the entire import chain need to be buildable as well.
Old way
Preferred way to use exports, more encapsulation
allowJs
offdeclarationMap
on will trigger more errors, but needed for buildable libsNo —declaration maps ("declaration": true + "declarationMap": true) and type-inference can live together.
What breaks is not “inference in general,” but exporting a value whose inferred public type leaks private, non-exported stuff.
When do we typecheck, it builds the tsbuildinfo which is placed according to rootDir. We cannot specify both rootDir and rootDirs in base.
when you don't set rootDir, the compiler infers it, rootDir = the longest common directory that is a prefix of every source file the compiler will emit for this program. So the shortest path in files. Since we added vite.config.ts, it removed src as the rootDir.
customConditions
is a tsc compile concept, while package.json exports is a bundleruse server
anduse client
, even theimport preserveDirectives from 'rollup-preserve-directives'
fails when an import chain has both directives, they are both addedoutDir
in lib specified, the next bundler will lok there to load filesThe TypeScript compiler never consults that field when the library is referenced through a project-reference.
pnpm workspace linking
Be careful of workspace linking, the
pnpm-workspace.yaml
had incorrect syntax for exclusion, usedexcludes
key instead of!
This looked under dist as a workspace and
pnpm install
used the dist files to link as pnpm workspaceIf we want to remove project.json, the output will go to dist folder
which means the exports field will need to change (may be able to change with inferred config path)
inferred js not working if
isValidPackageJsonBuildConfig
not true, meaning package.json can't reference any dist pathTo use inferred,
@nx/js/typescript
creates build, but we want@nx/js:tsc
if we want to copy assets, so we add to targets build in package.json. Then we set some defaults for targetDefaultsEven though the package.json exports map has a development condition pointing to src, the TypeScript project reference mechanism, especially with composite: true, often relies on the outDir specified in the referenced project's tsconfig. It uses the tsBuildInfoFile to track the relationship between source and output files. The error arises because the build info likely indicates that dist/index.d.ts should correspond to src/index.ts, but it's either missing or older than the source.
What’s going on internally
1. composite: true implicitly turns on declaration: true and makes the compiler treat the declarations as the public contract of the project. 
2. When the resolver sees moduleResolution: nodenext/bundler, it does load the exports map but it first checks whether it is looking for “the emitted declarations of a composite project”. If so, it jumps straight to and ignores the rest of the conditions.
3. customConditions is therefore skipped; the development branch is never evaluated.
composite: true tells TypeScript that this project’s declarations (.d.ts in outDir) are the public API
Solution style tsconfig.json should not include lib, since lib is used for build only. only reference dev should we use for ide
Beta Was this translation helpful? Give feedback.
All reactions