nighttrax / ts-monorepo Goto Github PK
View Code? Open in Web Editor NEWTemplate for setting up a TypeScript monorepo
License: MIT License
Template for setting up a TypeScript monorepo
License: MIT License
Is there any correct way to handle definition files of type d.ts? let's use for example the styled-components of this context here
If the examples / cra
project is to use it would it get bored automatically, if q is this in fact a definition of packages / components
?
Hey,
Thanks for this insightful example. I've a question though: I checked out the project reference branch, and running npm run build on foo yields this error:
src/index.ts:1:27 - error TS2307: Cannot find module '@nighttrax/foo'.
Any idea ?
GitHub has recently introduced the templates feature:
This repository and its accompanying article are so good that I think they deserve to be a template. I spent long hours debugging my TypeScript configs and reading other two tutorials before stumbling upon yours!
Oh, and if I may, a further idea: rebrand this to "ts-monorepo" or something alike - one doesn't have to use lerna to follow through the setup.
I tried installing ts-node-dev to run the index file to see if it would throw this error, and indeed it did. For some reason, I just can not get monorepos to work for me. Even if VSCode detects symbols correctly, node can not resolve the modules at runtime.
[sparta@sparta-pc lerna-ts-master]$ yarn tsnd packages/bar/src/index.ts
yarn run v1.19.0
$ /data/downloads/lerna-ts-master/node_modules/.bin/tsnd packages/bar/src/index.ts
Using ts-node version 8.6.2, typescript version 3.4.5
Error: Cannot find module '@nighttrax/foo'
Require stack:
- /data/downloads/lerna-ts-master/packages/bar/src/index.ts
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
at Function.Module._load (internal/modules/cjs/loader.js:862:27)
at Module.require (internal/modules/cjs/loader.js:1040:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/data/downloads/lerna-ts-master/packages/bar/src/index.ts:1:1)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
at Module._compile (/data/downloads/lerna-ts-master/node_modules/source-map-support/source-map-support.js:541:25)
at Module.m._compile (/tmp/ts-node-dev-hook-048440305208922174.js:57:25)
at Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
at require.extensions.<computed> (/tmp/ts-node-dev-hook-048440305208922174.js:59:14)
[ERROR] 19:28:04 Error: Cannot find module '@nighttrax/foo'
Require stack:
- /data/downloads/lerna-ts-master/packages/bar/src/index.ts
When I use this in my cra repo
// Remove the ModuleScopePlugin which throws when we try to import something
// outside of src/.
config.resolve.plugins.pop();
// Resolve the path aliases.
config.resolve.plugins.push(new TsconfigPathsPlugin());
// Let Babel compile outside of src/.
config.module.rules[2].oneOf[1].include = undefined
config.module.rules[2].oneOf[1].exclude = /node_modules/;
I got
Cannot read property 'options' of undefined
error Command failed with exit code 1.
And when I delete this line
config.module.rules[2].oneOf[1].include = undefined
It wont throw error
Thank you in advance! your repository is helping me to learn a lot!
I want to bring a problem related to path alias between packages. I don't know if it's okay to do it the way I'm trying but come on, let me explain. I'm managing to call the packages between projects, so far so good. However, when I call one another and this other in his imports uses some alias (from the project itself) he gets lost.
In the common scenario, I would do a simple import {Container, Input as InputBase, Error} from '. / Styles'
, but I want to try to reach that sense of different projects having their alias declared for them and in this external relationship with internal, worked. You see?
I brought an example of a POC that I'm doing where I had this problem that I reported ... I tried to apply the same problem in your project and I had the same error
First of all I think this can be very helpful for someone how just want to start working with Lerna and TS, thank you for this project.
I kind of missing some full instruction to make it work... maybe I missed it...
anyway - whenever I run Lerna run build - I get this error "'rm' is not recognized as an internal or external command,"
What can i do?
Hey mate,
I've been using this repo as a starter for my monorepo since a few months and it's working pretty well for the most part. I'm glad the tooling (TS, Lerna, VSCode, e.g.) is working as expected in most important ways.
But am I correct in saying that there's not clear best practice or even implementation in serving and watching the packages?
Harm
I am testing some changes to the examples and I noticed that to run the tests on the CRA project it seems to me to be incorrect.
Was that so?
ts-monorepo/examples/cra/package.json
Line 24 in 54681cf
Hi,
The tsconfig-paths works in development but not when running react-app-rewired test.
I am using typescript.
Cannot find module '@client/package' from 'src/Context.ts'
What should be added to get test to recognize the import module outside of src?
Thanks.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates await pending status checks. To force their creation now, click the checkbox below.
@nestjs/common
, @nestjs/core
, @nestjs/platform-express
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@storybook/core-common
, @storybook/react
, @storybook/react-webpack5
, storybook
).github/workflows/tests.yml
actions/checkout v4
pnpm/action-setup v4.0.0
actions/setup-node v4
apps/cra/package.json
react ~18.3.0
react-dom ~18.3.0
@types/node ~20.14.0
@babel/core ~7.25.0
@babel/plugin-syntax-flow ~7.24.0
@babel/plugin-transform-react-jsx ~7.25.0
@craco/craco ~7.1.0
@types/express ~4.17.13
@types/jest ~29.5.0
@types/react ~18.3.0
@types/react-dom ~18.3.0
autoprefixer ~10.4.0
cross-env ~7.0.2
jest ~29.7.0
postcss ~8.4.31
react-scripts ~5.0.0
rimraf ~6.0.0
ts-jest ~29.2.0
tsconfig-paths-webpack-plugin ~4.1.0
typescript ~4.9.0
ts-node ~10.9.1
apps/jest-babel/package.json
@babel/core ~7.25.0
@babel/preset-env ~7.25.0
@babel/preset-typescript ~7.24.0
@types/jest ~29.5.0
babel-plugin-module-resolver ~5.0.0
jest ~29.7.0
apps/jest-tsjest/package.json
@types/jest ~29.5.0
@jest/types ~29.6.0
@types/node ~20.14.0
jest ~29.7.0
ts-jest ~29.2.0
ts-node ~10.9.0
typescript ~4.9.0
apps/nestjs/package.json
@nestjs/common ~10.3.8
@nestjs/core ~10.3.8
@nestjs/platform-express ~10.3.8
reflect-metadata ~0.2.2
rimraf ~6.0.0
rxjs ~7.8.0
@nestjs/cli ~10.4.0
@types/express ~4.17.11
@types/node ~20.14.0
ts-node ~10.9.0
tsconfig-paths ~4.2.0
typescript ~4.9.0
apps/nextjs/package.json
next ~14.0.0
react ~18.3.0
react-dom ~18.3.0
@types/node ~20.14.0
@types/react ~18.3.0
@types/react-dom ~18.3.0
rimraf ~6.0.0
typescript ~4.9.0
apps/rollup/package.json
@rollup/plugin-typescript ~11.1.5
@types/node ~20.14.0
rimraf ~6.0.0
rollup ~4.20.0
tslib ~2.6.0
typescript ~4.9.0
apps/storybook/package.json
react ~18.3.0
react-dom ~18.3.0
@babel/core ~7.25.0
@babel/preset-env ~7.25.0
@babel/preset-react ~7.24.0
@babel/preset-typescript ~7.24.0
@storybook/core-common ~7.6.0
@storybook/react ~7.6.0
@storybook/react-webpack5 ~7.6.0
@types/react ~18.3.0
@types/react-dom ~18.3.0
babel-loader ~9.1.0
require-from-string ~2.0.2
rimraf ~6.0.0
storybook ~7.6.0
tsconfig-paths-webpack-plugin ~4.1.0
typescript ~4.9.0
webpack ~5.93.0
apps/ts-node/package.json
@types/node ~20.14.0
ts-node ~10.9.0
tsconfig-paths ~4.2.0
typescript ~4.9.0
apps/vite/package.json
react ~18.3.0
react-dom ~18.3.0
@types/react ~18.3.0
@types/react-dom ~18.3.0
@vitejs/plugin-react ~4.3.0
rimraf ~6.0.0
typescript ~4.9.3
vite-tsconfig-paths ~4.2.0
vite ~5.3.0
apps/webpack/package.json
rimraf ~6.0.0
webpack ~5.93.0
webpack-cli ~5.1.0
ts-loader ~9.5.0
tsconfig-paths-webpack-plugin ~4.1.0
typescript ~4.9.0
package.json
@nighttrax/eslint-config-tsx ~12.0.0-alpha.2
doctoc ~2.2.0
eslint ~8.57.0
eslint-plugin-import ~2.29.0
typescript ~4.9.0
packages/bar/package.json
rimraf ~6.0.0
typescript ~4.9.0
packages/components/package.json
@types/react ~18.3.0
react ~18.3.0
react-dom ~18.3.0
rimraf ~6.0.0
react ~18.3.0
packages/foo/package.json
rimraf ~6.0.0
typescript ~4.9.0
Hello @NiGhTTraX
In the root package.json, there exists a devDependency named eslint. eslint-plugin-import is another dependency.
Also there is a "yarn lint" command in the same package.json.
In the examples/nestjs/package.json, eslint devDependency is again there.
In the examples/cra/package.json, there are no eslint-related dependencies. Also, the eslintConfig property is not there.
Earlier the eslint was working for nestjs as soon as I used to start the VSCode. Then I replaced 'react-app-rewired' with 'craco' in the CRA.. to provide support for tailwindcss.
Now the ESLint is neither working for nestjs nor cra. Why is there a mismatch between the esling configurations for the cra and nestjs examples?
Kindly help. Thanks
It would be great to see how NestJs could be used with the setup you made for these plugins.
Hello i just noticed that declaration files are not generated when building the rollup example.
You can fix that with an update to the rollup config rollup/plugins#61 (comment)
I'm not sure what the appropriate solution is at the moment.
I tried adding "outDir": "/dev/null"
but that didn't fly. It also wouldn't work on a windows box, I dont think. noEmit
won't work at the base level because it conflicts with composite
. Setting the outDir
risks overriding the proper build unknowingly.
Hello,
Thanks for your nice work. It would be very interesting to have an example with react-native too.
Thanks for your blog post and maintaining this repo 👍
Currently this template has a nextjs 9 example project, using next-transpile-modules
3.3.0 to handle shared packages. For reference, as of writing this next-transpile-modules
is at version 6.4.0, and next is version 10.
As I described in the nextjs issue here vercel/next.js#5666 (comment), the next-transpile-modules
changed their module resolution to use enhanced-resolve between the versions 3 and 4, which seemingly broke the usecase found in this repo.
As also suggested in that thread, I managed to work around this issue in my own project with the following next.config.js:
module.exports = {
webpack: (config) => {
config.module.rules.forEach((rule) => {
if (rule.test && rule.test.toString().includes("tsx|ts")) {
rule.include = [
...rule.include,
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("path").join(__dirname, "../../packages"),
];
}
});
return config;
},
};
So far I'm unsure if there are any caveats to this approach as compared to next-transpile-modules
. Either way, it might make sense to update the template to use something that does not break with latest versions of the packages involved.
Hi @NiGhTTraX
In the cra app, I want to use the path aliases which, if I am right, could be specified in the cra's tsconfig.json as follows:
"extends": "../../tsconfig.json",
...
baseUrl: "src",
"paths": {
"@contexts/*": ["contexts/*"],
"@hooks/*": ["hooks/*"],
"@shared/*": ["shared/*"],
},
But this is not working. What do I need to do to make it work, any hints.
Kindly note that the ts-monorepo has its own ts-config file where the "paths" property is already there.
Thank you.
If you create a .env
file in a package and that .env
has let's say EXAMPLE=foo
and a main package has EXAMPLE=example
and that main package includes foo
, if you export the EXAMPLE
from foo
and try to print on the main repository it will print the EXAMPLE
from the main and not the foo
.
For example:
packages/foo/.env
:
EXAMPLE=foo
packages/foo/src/index.ts
:
import dotenv from "dotenv";
dotenv.config();
const { EXAMPLE } = process.env;
export const example = EXAMPLE;
This is going to export the EXAMPLE
variable from the .env
.
packages/api/.env
:
EXAMPLE=api
packages/api/src/index.ts
:
import { example } from "@monorepo/foo";
console.log(example);
The output from console.log
should be foo
but it outputs api
Hey, thanks for that repo.
I was trying to copy the concept for my project. Sadly I couldnt bring it to build successfully, always got the failure "module not found" when I tried to run the build steps in a package with dependecies to other packages. (eg. @nighttrax/foo' not found in package/bar)
So I just tried to simply download and run this repo. Sadly I am running into few errors. May you understand what I am doing wrong?
I am using vscode on windows, so I changed nothing but the "clean" task. I changed "rm" command to a "rimraf" command which is globally installed, so I dont think thats a issue.
Thanks.
This has to be the best Typescript/Next/Lerna monorepo I've seen yet. I've been searching for weeks for an optimal configuration. My requirements were:
This checks all of the boxes except for the last one, but it's a simple fix.
I'm primarily concerned with the NextJS package and importing from other libs in the monorepo. To reproduce my issue, do the following:
yarn build
and observe the first load JS bundle size for the NextJS build (should be around 59KB)packages/components
, add react-select
as a dependency.packages/components/src/select.tsx
with the following code:import React from "react";
import Select from "react-select";
export function MySelect(): JSX.Element {
return <Select />;
}
packages/components/src/index.tsx
:export * from "./button";
export * from "./select";
yarn build
at the root and observe the first load JS bundle size for the NextJS build (should now be somewhere around 86KB). This isn't ideal, as we've simply added a component that we're not using to another package in the repo.Ideally, only the components that are imported should be included in the bundle.
To fix:
module: "esnext"
moduleResolution: "node"
Code splitting is only supported in the more recent versions of es. Also, I had to make some modifications to support proper interface/type detection. Lmk if you want the details!
Cheers, thanks for the code!
EDIT2:
amended steps.
Hi there, what a cool repo!
I ran in to a build failure after doing the following on a fresh clone:
# npm version >=7 supports workspaces like yarn
npm install
npm run build
The error message:
ERROR in ../../node_modules/@nestjs/core/nest-application.js 16:102-145
Module not found: Error: Can't resolve '@nestjs/websockets/socket-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
resolve '@nestjs/websockets/socket-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
Parsed request is a module
using description file: C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\package.json (relative path: .)
resolve as module
looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules\@nestjs\websockets doesn't exist
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\node_modules doesn't exist or is not a directory
C:\dev\efokschaner\ts-monorepo\node_modules\node_modules doesn't exist or is not a directory
looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\websockets doesn't exist
C:\dev\efokschaner\node_modules doesn't exist or is not a directory
C:\dev\node_modules doesn't exist or is not a directory
C:\node_modules doesn't exist or is not a directory
@ ../../node_modules/@nestjs/core/index.js 25:21-50
@ ./src/main.ts 3:15-38
ERROR in ../../node_modules/@nestjs/core/nest-application.js 17:120-173
Module not found: Error: Can't resolve '@nestjs/microservices/microservices-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
resolve '@nestjs/microservices/microservices-module' in 'C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core'
Parsed request is a module
using description file: C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\package.json (relative path: .)
resolve as module
looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\core\node_modules\@nestjs\microservices doesn't exist
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\node_modules doesn't exist or is not a directory
C:\dev\efokschaner\ts-monorepo\node_modules\node_modules doesn't exist or is not a directory
looking for modules in C:\dev\efokschaner\ts-monorepo\node_modules
C:\dev\efokschaner\ts-monorepo\node_modules\@nestjs\microservices doesn't exist
C:\dev\efokschaner\node_modules doesn't exist or is not a directory
C:\dev\node_modules doesn't exist or is not a directory
C:\node_modules doesn't exist or is not a directory
@ ../../node_modules/@nestjs/core/index.js 25:21-50
@ ./src/main.ts 3:15-38
webpack 5.28.0 compiled with 2 errors in 3305 ms
It appears webpack is not smart about these optionalRequire
s in nest-application.js
.
After some learning about what nestjs is and how it works, I found that in their example boilerplate, they are not using webpack: https://github.com/nestjs/typescript-starter/blob/master/nest-cli.json
I'll post a PR with webpack removed so you can see if that's a fix that makes sense to you. That solved the issue for me locally.
Thanks!
Thank you for your work.
I cloned the project for trying it and I found out that dependencies are installed correctly only running lerna bootstrap
from the root; I get an error when I try to run npm i
in 'packages/bar' directory.
It tries to download 'foo' dependency from the public npm registry, instead of using the one in the monorepo.
Is there a way to fix this issue and have npm i
working as well as lerna bootstrap
?
Hi there,
Regarding nextJS, Instead of doing this:
webpack: (config) => {
const tsRule = config.module.rules.find(
(rule) => rule.test && rule.test.toString().includes("tsx|ts")
);
console.log(tsRule)
tsRule.include = undefined;
tsRule.exclude = /node_modules/;
return config;
},
You can do this:
experimental: {
externalDir: true,
},
Hi @NiGhTTraX,
Thanks for the article and sharing your work 👌
I tried to add an extra foo/src/demo.ts
module and importing it from bar/src/index.ts
after adding files: ["dist"]
on foo/package.json
.
import demo from "@nighttrax/foo/src/demo";
import demo from "@nighttrax/foo/demo";
Both syntaxes ends with Error: Cannot find module '@nighttrax/foo/[src/]demo
Is it possible to import non "main" modules (without having to import and export them from the main one)?
All typescript mono repo examples that I found so far showcase the same kind of example of package a
import module b
's single exported main module.
Thanks for the tutorial! I had to make a change to the project-references
branch and instead of rootDir
use rootDirs
. However, this completely breaks it. Any idea how to use include multiple roots in foo
?
I wanted to execute the script in "@nighttrax/bar", so I added "ts-node" to the game and a little start script:
lerna-ts\packages\bar\package.json
{
...
"scripts": {
...
"start": "ts-node ./src/index.ts",
...
},
...
}
When executing npm start
I am getting the following error:
Error: Cannot find module 'C:\dev\projects\bennyn\lerna-ts\packages\bar\node_modules@nighttrax\foo\dist
index'. Please verify that the package.json has a valid "main" entry
The problem exists because the "main" entry in "foo" package points to "dist/index". This file does not exist by default so I have to run "npm run build" in the "foo" package directory first before I can start my script in "bar" package.
Do you have an idea how the monorepo can be linked so that I don't have to compile monorepo dependencies first?
I could change the "main" entry in "foo" package to "src/index" so it uses the existing TypeScript source code but then I will get intro trouble when publishing this package on npmjs since it will point to TypeScript sources and not to compiled JavaScript code.
Thank you for your documentation.
I'm a week and a half stuck with this problem, all my Google links are purple, and my StackOverflow questions hasn't received any answers. Maybe you will know how to solve this issue.
Using techniques from this repo everything compiles without errors, even when common/* (shared) code contains missing types.
Our project structure:
|-- apps
|-- native
|-- web
|-- package.json
|-- tsconfig.json
|-- tsconfig..paths.json
|-- common
|-- models
|-- package.json
|-- tsconfig.json
|-- connectors
|-- package.json
|-- tsconfig.json
|-- store
|-- package.json
|-- tsconfig.json
|-- types
|-- package.json
|-- tsconfig.json
|-- utils
|-- package.json
|-- tsconfig.json
-- package.json
-- tsconfig.json
-- tsconfig.paths.json
Root package.json
{
"name": "@flowbase/client",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"workspaces": [
"./common/*",
"./apps/*"
],
"devDependencies": {
"@typescript-eslint/parser": "^4.26.0"
}
}
Root tsconfig.json
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@flowbase/*": ["common/*"],
}
}
}
Root tsconfig.paths.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"es2015",
"dom",
"dom.iterable",
"esnext",
"webworker"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"types": [
"jest"
]
}
}
common/storepackage.json - example, they are all the same, only dependencies changing
{
"name": "@flowbase/store",
"version": "1.0.0",
"private": true,
"description": "",
"main": "index.js",
"dependencies": {
"@flowbase/types": "1.0.0",
"@flowbase/utils": "1.0.0",
"@flowbase/connectors": "1.0.0",
"@flowbase/apimodels": "1.0.0",
"@microsoft/signalr": "5.0.1",
"@types/lodash": "^4.14.165",
"@types/react": "^17.0.3",
"@types/redux-logger": "^3.0.8",
"axios": "^0.21.1",
"lodash": "^4.17.20",
"msw": "^0.21.3",
"react": "^17.0.2",
"react-app-polyfill": "^1.0.6",
"react-redux": "^7.2.3",
"typescript": "^4.2.3"
},
"devDependencies": {
"@types/jest": "^26.0.21",
"eslint-plugin-react": "^7.23.1",
"jest": "^26.6.3",
"jest-json-schema": "^2.1.0",
"jest-localstorage-mock": "^2.4.9",
"tslint": "^5.20.1",
"tslint-react": "^4.1.0"
}
}
apps/web package.json
{
"name": "@flowbase/web-client",
"version": "0.1.0",
"private": true,
"dependencies": {
"@flowbase/types": "1.0.0",
"@flowbase/store": "1.0.0",
"@flowbase/connectors": "1.0.0",
"@flowbase/apimodels": "1.0.0",
"@flowbase/utils": "1.0.0",
"@monaco-editor/react": "^3.7.4",
"@types/lodash": "^4.14.165",
"@types/node": "^12.20.6",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"axios": "^0.21.1",
"cronstrue": "^1.110.0",
"lodash": "^4.17.20",
"monaco-editor": "^0.17.1",
"normalize.css": "^8.0.1",
"pdfjs-dist": "2.8.335",
"react": "^17.0.2",
"react-app-polyfill": "^1.0.6",
"react-datepicker": "^3.1.3",
"react-dom": "^17.0.2",
"react-redux": "^7.2.3",
"react-scripts": "^4.0.3",
"streamsaver": "^2.0.5",
"style-scoped": "^0.2.1",
"typescript": "^4.2.3",
"yargs": "^15.4.1"
},
"scripts": {
"start": "set NODE_ENV=development && node generate-config.js && rescripts start",
"mock": "set MOCK_BACKEND='1' && rescripts start",
"build": "set NODE_ENV=production && node generate-config.js && npm run generate-icons && rescripts build",
"unit": "set NODE_ENV=development && set NODE_OPTIONS=--unhandled-rejections=warn && rescripts test --env=jsdom --watchAll=false --coverage",
"unit-interactive": "set NODE_ENV=development && set NODE_OPTIONS=--unhandled-rejections=warn && rescripts test --env=jsdom",
"e2e": "jest -c jest.config.js --runInBand",
"e2e-debug": "set PWDEBUG=1 && jest -c jest.config.js --runInBand",
"test": "npm run unit && npm run e2e",
"generate-icons": "node generate-icons.js",
"eject": "rescripts eject",
"lint": "eslint ./src/**/*.ts ./src/**/*.tsx",
"electron": "electron ."
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
},
"devDependencies": {
"@rescripts/cli": "0.0.16",
"@types/jest": "^26.0.21",
"@types/jest-image-snapshot": "^4.1.3",
"@types/react-datepicker": "^3.1.8",
"@types/react-jsonschema-form": "^1.7.3",
"@types/react-redux": "^7.1.12",
"@types/react-router-dom": "^4.3.5",
"@types/streamsaver": "^2.0.0",
"babel-plugin-module-resolver": "^4.1.0",
"electron": "^12.0.2",
"eslint-plugin-react": "^7.23.1",
"fs-extra": "^8.1.0",
"jest": "^26.6.3",
"jest-image-snapshot": "^4.3.0",
"jest-json-schema": "^2.1.0",
"jest-localstorage-mock": "^2.4.9",
"jest-playwright-preset": "^1.5.1",
"mathsass": "^0.11.0",
"msw": "^0.21.3",
"node-sass": "^5.0.0",
"playwright": "^1.11.1",
"svg-sprite": "^1.5.0",
"ts-jest": "^26.5.4",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"tslint": "^5.20.1",
"tslint-react": "^4.1.0",
"vinyl": "^2.2.0"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"main": "./electron-start.js"
}
apps/web tsconfig.json
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"target": "es5",
"lib": [
"es2015",
"dom",
"dom.iterable",
"esnext",
"webworker"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"types": [
"jest",
"jest-playwright-preset",
"expect-playwright"
]
},
"include": [
"src"
]
}
apps/web tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
}
}
}
We used rescripts instead of react-app-rewired, but the result is the same.
module.exports = [{
const applyRuleFunctionRecursive = (fn, rule, parent) => {
if (typeof rule !== "object") {
return;
}
if (Array.isArray(rule)) {
rule.forEach(r => applyRuleFunctionRecursive(fn, r, rule));
} else if (rule.hasOwnProperty("use")) {
applyRuleFunctionRecursive(fn, rule.use, rule);
} else if (rule.hasOwnProperty("oneOf")) {
applyRuleFunctionRecursive(fn, rule.oneOf, rule);
} else {
fn(rule, parent);
}
}
const extendBabel = (plugin, parent) => {
if (plugin.loader && plugin.loader.indexOf("babel-loader") !== -1) {
plugin.include = undefined;
plugin.exclude = /node_modules/;
plugin.options.presets.push(
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
);
if (plugin.options.plugins) {
plugin.options.plugins.push(
[
"module-resolver",
{
alias: {
'@flowbase': '../../common/',
},
},
],
);
}
}
}
config.resolve.plugins.pop();
config.resolve.plugins.push(new tsConfigPathsPlugin());
applyRuleFunctionRecursive(extendBabel, config.module.rules, config);
return config;
},
}];
After npm install
in the root folder, navigating into "apps/web" and npm start
everything compiles without errors.
The problem is, that if I intentionally comment out a type import inside any of common/*
workspaces, it still compiles without errors (doesn't type check). However, doing the same inside apps/web/
throws an error for missing types. (does type check)
Sorry for the long post, I really hope you can point us in the right direction.
Hey there,
Thanks for this repository, very helpful.
I'm struggling though to understand how to proceed with create-react-app to manage non-relative imports such as utils/foo
or components/bar
that I use a lot in my code base.
I worked around the fact that CRA does not support "paths" in tsconfig.json - And savagely removes them each time it transpiles the application (See : facebook/create-react-app#5585 (comment)).
The workaround is to use baseUrl
set to src
, so that all directories there (eg. src/foo
) could be resolved non-relatively. (foo
)
My issue is that adding this baseUrl
to src makes me unable anymore to resolve the paths in the root tsconfig.json (such as @nighttrax/components
)
Not sure why, but do you have any clue on that one ?
Cheers mate
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Location: renovate.json
Error type: Invalid JSON (parsing failed)
Message: Syntax error: expecting end of expression or separator near sts"]. "
When I clone the repo (or make a new repo based off the template and clone that, and then run yarn install
followed by lerna run build
I get the following output. I included the versions of both tools in case that's relevant.
The text of the errors is slightly different, but more or less the same thing happens in the npm branch.
What am I doing wrong?
PS E:\homedev\ts-monorepo> yarn install
yarn install v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > [email protected]" has unmet peer dependency "eslint-plugin-import@^2.21.2".
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > [email protected]" has unmet peer dependency "eslint-plugin-react-hooks@^4 || ^3 || ^2.3.0 || ^1.7.0".
warning "@nighttrax/eslint-config-tsx > @nighttrax/eslint-config-react > eslint-config-airbnb > [email protected]" has unmet peer dependency "eslint-plugin-import@^2.21.2".
warning " > @nighttrax/[email protected]" has unmet peer dependency "react@~16.13.1".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-example > [email protected]" has incorrect peer dependency "typescript@>=3.8 <4.0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/rollup-example > @rollup/[email protected]" has unmet peer dependency "tslib@*".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/preset-typescript > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "workspace-aggregator-4373fb95-f48d-4678-a7ec-865d3d1924c5 > @nighttrax/jest-babel-example > @babel/preset-typescript > @babel/plugin-transform-typescript > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
Done in 26.74s.
PS E:\homedev\ts-monorepo> lerna run build
info cli using local version of lerna
lerna notice cli v3.22.1
lerna info versioning independent
lerna info Executing command in 8 packages: "yarn run build"
lerna info run Ran npm script 'build' in '@nighttrax/foo' in 5.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 5.31s.
lerna info run Ran npm script 'build' in '@nighttrax/rollup-example' in 1.9s:
yarn run v1.22.10
$ rollup -c
Done in 1.65s.
lerna info run Ran npm script 'build' in '@nighttrax/bar' in 4.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 4.32s.
lerna info run Ran npm script 'build' in '@nighttrax/components' in 4.5s:
yarn run v1.22.10
$ yarn run clean && yarn run compile
$ rimraf -rf ./dist
$ tsc -p tsconfig.build.json
Done in 4.28s.
lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna ERR! yarn run build stdout:
yarn run v1.22.10
$ SKIP_PREFLIGHT_CHECK=true react-app-rewired build
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
lerna ERR! yarn run build stderr:
'SKIP_PREFLIGHT_CHECK' is not recognized as an internal or external command,
operable program or batch file.
error Command failed with exit code 1.
lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna WARN complete Waiting for 3 child processes to exit. CTRL-C to exit immediately.
PS E:\homedev\ts-monorepo> lerna --version
3.22.1
PS E:\homedev\ts-monorepo> yarn --version
1.22.10
PS E:\homedev\ts-monorepo>
I would like one suggestion when applied monorepo strategy.
We go to use this context as example.
When I change something in package/*
, I need on my CI/CD detect all projects those have that specific dependence installed for trigger a deploy as well.
Existis tip with git commands or others for to help in this case?
warning package.json: No license field
$ react-app-rewired start
Cannot read property 'oneOf' of undefined
error Command failed with exit code 1.
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = function override(config, env) {
//https://medium.com/@NiGhTTraX/making-typescript-monorepos-play-nice-with-other-tools-a8d197fdc680
// Remove the ModuleScopePlugin which throws when we try
// to import something outside of src/.
config.resolve.plugins.pop();
// Resolve the path aliases.
config.resolve.plugins.push(new TsconfigPathsPlugin());
// Let Babel compile outside of src/.
const tsRule = config.module.rules[2].oneOf[1];
tsRule.include = undefined;
tsRule.exclude = /node_modules/;
return config;
}
FULL DISCLOSURE: this is my first time working with npm workspaces
git clone https://github.com/NiGhTTraX/ts-monorepo.git
cd ts-monorepo/
git checkout npm
npm install
then all of these commands:
npm run start --workspace=@nighttrax/ts-node
npm run start --workspace=ts-node
npm run start --workspace=examples/ts-node
fail with the same error:
npm ERR! missing script: start
Would be great to see an example of:
/example
I want to use this template for setting up a monorepo with Azure Functions but I'm struggling to get it working how I want.
package/dist/file
package/src/file
or package/file
style importsI get the error:
'Error: Qualified path resolution failed - none of the candidates can be found on the disk.
According to issue Azure/azure-functions-core-tools#2 it seems that I need to use tsconfig-paths
but I don't know how to do that as the azure functions core tools don't use ts-node.
package/src/file
or package/file
working? Or does tsconfig-paths also work without ts-node?I hope someone can provide me some guidance here on possible ways to proceed! (it could be that this also isn't the right place to ask this)
I have made a minimal as possible repro here on a separate branch: https://github.com/ultimate-ttt/ttt-backends/tree/dev-mono-with-berry
To get it running you need:
yarn start
If you have any problems with getting it running, I can help here.
hello,
i am trying to link a file from one package to other directly, it doesn't work,
here is a fork with my example https://github.com/CosticaPuntaru/ts-monorepo/blob/master/packages/bar/src/index.ts
can you help me make it work ? :)
if i change paths to
"paths": {
"@nighttrax/foo/*": ["packages/foo/src/*"],
"@nighttrax/*": ["packages/*/src"]
},
the webstorm ide does not complain about the file, but compile breaks,
if i change tsconfig.build.json and add
"baseUrl": ".",
"paths": {
"@nighttrax/foo/*": [
"packages/foo/src/*"
]
}
it compiles but the compiled files are all messed up,
i understand why, but i am looking for workaround :)
Is there an example of how the Next.js app in this repository could be deployed to Vercel using the npm branch? I'm able to verify that the Next.js builds correctly locally, but I've been unable to successfully deploy it on Vercel. Thanks!
Is there a way to use the typescript files from component package without run the compile command?
Hi,
I think you did a great work here, you really saved me!
the only thing that I was missing is a testing framework, fortunately it was pretty easy to add Mocha and chai - so easy I was sure it's not going to work, I have already made to many changes to run a pull request but if you want to add it to the project I can help - I am also added nyc to get a code coverage report - (the only issue I have is that it's hard to see failing the tests when running lerna run test- but I think it's an issue with Lerna )
I do not know much about lerna. But I have seen that the packages directory typically consists of sub-directories whose names are something like: frontend (or web), backend (or api), shared.)
Could you pl. answer these:
a. What exactly is the role of foo, bar, and components directories residing in the packages directory.
b. Why do the cra and nest appear in the examples directory.
Thanks
I was using a component from "components package" inside monorepo which is a button component. When I run from its own package, it runs with no problem. But if is is used from another package it shows this error.
../components/dist/components/atoms/Test/index.js
Module not found: Can't resolve './styles.module.css' in ...component path.
Any idea that can solve? thank in advance.
We found example for webpack. But how about example for rollup?
I ran in to a build failure after doing the following on a fresh clone:
# npm version >=7 supports workspaces like yarn
npm install
npm run build
The error message:
lerna ERR! yarn run build exited 1 in '@nighttrax/cra-example'
lerna ERR! yarn run build stdout:
yarn run v1.22.10
$ cross-env SKIP_PREFLIGHT_CHECK=true react-app-rewired build
Creating an optimized production build...
Failed to compile.
src\index.tsx
Line 1:27: Delete `CRLF` prettier/prettier
...
I am on Windows which is definitely relevant to this problem.
The prettier eslint plugin and rules appear to come from https://github.com/NiGhTTraX/eslint-config/blob/master/packages/base/index.js#L24
I'm not sure how you prefer to address this, but here are some ideas:
prettier --write
at some step for either this example or the entire repo to fix up line endings and other stuff."endOfLine":"auto"
for either this example or the whole repo.Thanks!
Hi,
First of all, thanks for this repo and accompanying article. Using TypeScript with Lerna feels way more complex than it should, and the resources you created really help with that complexity.
I'm curious to hear what you recommend for watch/development mode, such that you're listening for changes in any of the packages and automatically build them.
Thanks!
Thanks for the article. It looks like the issue you reference in the article has seen some progress. Does this impact your solution at all?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.