I'm playing around with Yarn 2, and I want to do something like this.
I have a monorepo of the structure:
/
packages/
shared-ts/
package.json
src/
lib*/
app-ts/
package.json
src/
lib*/
app-js/
package.json
src/
lib*/
where lib*
denotes that the folder is gitignored, but is where the compiled code will live.
In this example, I have a dependency library shared-ts
that is used by two apps, app-ts
and app-js
.
The conventional approach
The conventional approach to configuring a monorepo like this, is that in shared-ts
I would have a package.json like:
"main": "lib/index.js"
"scripts" : {
"build": "tsc"
}
Where the build
script will build index.js
and index.d.ts
into the lib folder.
When both app-ts
and app-js
then resolve the package, they look in the lib folder and find the index.js
and in app-ts
's case - the index.d.ts
.
This works fine, except that the developers need to remember to run the build
script if they have made changes to shared-ts
in order for the changes to propagate across.
Where this could potentially become problematic is where there are many layers of dependencies.
Attempted work around 1 - point main
to src/index.ts
.
I can change shared-ts
package.json to
"main": "src/index.ts"
"scripts" : {
"build": "tsc"
}
This generally won't work, a plain node process won't be able to parse the syntax in the .ts
file (eg. the import
keyword).
Potential workaround - publishConfig
So something I'm considering, but haven't tried yet is, using the publishConfig
fields in the package.json
This field contains various settings that are only taken into consideration when a package is generated from your local sources (either through yarn pack or one of the publish commands like yarn npm publish).
"main": "src/index.ts",
"publishConfig": {
"main": "lib/index.js"
}
The idea being that:
- When you publish a package to npm,
lib/index.js
will be used as main. π code is ready for consumption, no compilation required. - If being used directly in the monorepo
src/index.ts
will be used as main. π This kind of works as if you were runningapp-ts
withts-node
for example.
However, where this starts breaking down is:
- Running
app-js
in a development environment (where you don't have any additional syntax parsing set up).
Practical current best solution
My current best solution is to 'just give up on this 'no compile' aspiration' - if a developer makes changes to some code, they need to re-run build for the changes to propagate across.