Skip to content

Establish, document and maintain a reference monorepo for building npm packages #51817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 tasks done
cefn opened this issue Dec 8, 2022 · 1 comment
Open
5 tasks done
Labels
Help Wanted You can do this Suggestion An idea for TypeScript
Milestone

Comments

@cefn
Copy link

cefn commented Dec 8, 2022

Suggestion

Establish and document reference npm packages built from Typescript source in a monorepo which achieve the following three fundamentals. This seems no longer possible since node16, nodenext ...

  • A monorepo (with select package names resolving to local folders)
  • Package references resolve to source files, not built assets (e.g. local tooling such as IDE, bundlers, jest, can resolve local packages to .ts files not .js or .d.ts files which may be out of date)
  • Publishable (package has "main", "module", "types", "exports" pointing to CommonJS and ESM build artefacts)

For modern usage, I have also been attempting to achieve the following, which don't seem to be compatible with the above.

  • Uses moduleResolution node16 or nodenext)
  • Source-mapped (the package contains source and sourcemaps)

🔍 Search Terms

exports main module types npm publishable source resolution package.json node16 nodenext

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

As a Typescript user I am in need of a minimal reference example in which a monorepo resolves local packages to Typescript source in a recommended way. It's possible there is currently no correct way to do it. Discovering this for sure could lead to proposals for core features to fix it (like #51750 ).

The purpose of packages (rather than folders) is that they can be published, depended upon and bundled in isolation (else I'd just use folders). In modern terms this means the package.json is annotated with the main, module, types, and exports fields correctly. The purpose of having a monorepo is to handle the coupling between source files in different packages. So local packages should be resolved to their actual source files (not a build artefact from those files which may be out of date depending which tooling steps have been run). I should be able to follow the recommendations to adopt node16 or nodenext without breaking this core feature (of resolving packages to local source).

📃 Motivating Example

My (working) minimal repo of two interdependent npm packages in a monorepo was at https://github.com/cefn/starter/tree/ef3759946046de7c2223ce75959d64d1c86f6610

However, it was broken by a regression arising in the new resolution modes node16 and nodenext.

In particular with the moduleResolution mode of node I get the following resolution of the local package, traced to the local .ts source file as expected...

[packages/multiply]$ npx tsc --traceResolution | grep @starter/sum | more
======== Resolving module '@starter/sum' from '/home/cefn/Documents/github/starter/packages/multiply/src/index.ts'. ========
======== Module name '@starter/sum' was successfully resolved to '/home/cefn/Documents/github/starter/packages/sum/src/index.ts'. ========

However, toggling the top level tsconfig.json to moduleResolution node16 or nodenext the local package resolves as follows, to the .d.ts artefact which is fundamentally problematic to workflow in a monorepo (requires build targets to be permanently synchronised, for no obvious reason, when the actual source is right there).

[packages/multiply]$ npx tsc --traceResolution | grep @starter/sum | more
======== Resolving module '@starter/sum' from '/home/cefn/Documents/github/starter/packages/multiply/src/index.ts'. ========
======== Module name '@starter/sum' was successfully resolved to '/home/cefn/Documents/github/starter/packages/sum/dist/esm/index.d.ts' with Package ID '@starter/sum/dist/esm/ind
[email protected]'. ========

If the Typescript team were to take responsibility for defining a reference approach, it would minimise the complexity of future development of Typescript too. Currently the team has to deal with all manner of attempts people have made to satisfy the requirements of the ecosystem without support, leading to multiple incompatible strategies now needing to be supported in Typescript itself. I cannot speak for all other package authors, but their configuration 'choices' which the team attempts to support are probably not a choice at all, but are just the result of endlessly tracking and experimenting with ill-documented ecosystem features until the errors go away and they can do some REAL work.

With a reference repo in place that populates an npm package having source resolution, source mapping, CommonJS and ESM outputs, people would no doubt just follow that example. From that starting point it's always possible to further bundle and minify with downstream tooling.

💻 Use Cases

Authoring type-safe npm packages in Typescript is a core use case. Monorepos are a mainstream mechanism for projects which have multiple interdependent chunks of functionality. My attempts to achieve a reference repo fulfilling the above for one of my monorepo-based projects was a failure, and the internet is full of blogs having a blend of legacy and inappropriate configurations with no obvious canonical example. A reference monorepo would also be an effective way for the community to collaborate on further Typescript features.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Help Wanted You can do this labels Dec 8, 2022
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Dec 8, 2022
@cefn
Copy link
Author

cefn commented Sep 12, 2024

The article at https://colinhacks.com/essays/live-types-typescript-monorepo and the related repo at https://github.com/colinhacks/live-typescript-monorepo have largely answered my question here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants