• Stars
    star
    153
  • Rank 235,565 (Top 5 %)
  • Language
    HTML
  • License
    MIT License
  • Created almost 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Typescript monorepo for React project

What I want to achieve?

  • Monorepo project, to be able to comfortably to develop several packages, which can be used separately but as well together
  • Typescript
  • React
  • Testing library. I want to start with Jest, but as well we can choose something else
  • Storybook (or similar tool) for React components development and showcasing
  • (nice to have, but optional) ESlint with eslint-config-react-app
  • (nice to have, but optional) Rollup to bundle and minify
  • (nice to have, but optional) pre-commit hooks with prettier

Packages structure

  • d - utility library
  • b - React components library, which depends on d
  • c - another React components library, which depends on d
  • stories - showcase of b and c package's compnents as well used for development (initial plan, can change later)

Tools

⚠️⚠️⚠️ Info in this section is stale ⚠️⚠️⚠️:

  • Problem 1 is resolved in PR #2
  • Problem 2 is resolved in PR #5
  • Problem 4 is resolved in PR #4

yarn

yarn instead of npm, because it supports workspaces to link cross-dependencies.

Create package.json in the root without version because we not going to publish it and with workspaces:

"workspaces": [
  "packages/*"
]

lerna

We will use lerna to run commands across all packages and "elevate" common dependencies.

Create lerna.json:

{
  "packages": ["packages/*"],
  "npmClient": "yarn",
  "useWorkspaces": true,
  "version": "0.0.1"
}

TypeScript

We will use typescript to check types and compile TS down to desired JS files (ES5 or ES2015, CommonJS or ES modules).

Create tsconfig.base.json. This is what you need to add to enable monorepo:

{
  "include": ["packages/*/src"],
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "baseUrl": ".",
    "paths": {
      "@stereobooster/*": ["packages/*/src"]
    }
  }
}

Create packages/d/, packages/b/, packages/c/, packages/stories/. Add tsconfig.json to each one:

{
  "include": ["src"],
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    // to override config from tsconfig.base.json
    "outDir": "lib",
    "rootDir": "src",
    // for references
    "baseUrl": "src"
  },
  // references required for monorepo to work
  "references": [{ "path": "../d" }]
}

In package.json for packages b and c add:

"peerDependencies": {
  "@stereobooster/d": "0.0.1"
},
"devDependencies": {
  "@stereobooster/d": "*"
}

We need peerDependencies to make sure that when packages (d, b, c) installed by the end user they will use the same instance of package d, otherwise, TypeScript can complain about incompatible types (especially if use inheritance and private fields). In peerDependencies we specify a version, but in devDependencies we don't need to, because we need simply to instruct yarn to use whatever version of package we have locally.

Now we can build projects. Add to root package.json:

"scripts": {
  "build": "lerna run build --stream --scope=@stereobooster/{d,b,c}"
}

and to package.json for d, b, c

"scripts": {
  "build": "tsc"
}

Problem 1: because of sub-dependencies (packages b and c depend on d, stories depends on d, b, c) we need to build packages accordingly, e.g. first d, second b and c, third stories. That is why we can't use --parallel flag for lerna for build command.

React

Install @types/react, @types/react-dom, react, react-dom.

Add to tsconfig.base.json:

"compilerOptions": {
  "lib": ["dom", "esnext"],
  "jsx": "react",
}

Add to subpackage's package.json:

"peerDependencies": {
  "react": "^16.8.0",
  "react-dom": "^16.8.0"
}

Jest

We will use jest to run tests. Install @types/jest, @types/react-test-renderer, jest, react-test-renderer. Add jest.json. To eanbale TypeScript:

{
  "moduleFileExtensions": ["ts", "tsx", "js"],
  "transform": {
    "\\.tsx?$": "ts-jest"
  },
  "testMatch": ["**/__tests__/**/*.test.*"],
  "globals": {
    "ts-jest": {
      "tsConfig": "tsconfig.base.json"
    }
  }
}

to enable monorepo:

"moduleNameMapper": {
  "@stereobooster/(.*)$": "<rootDir>/packages/$1"
}

As well we will need to change tsconfig.base.json, because Jest doesn't support ES modules:

"compilerOptions": {
  "target": "es5",
  "module": "commonjs",
}

Add command to package.json

"scripts": {
  "pretest": "yarn build",
  "test": "jest --config=jest.json"
}

Problem 2: we will publish modules as ES5 + CommonJS, which makes no sense for React package, which would require some kind of bundler to consume packages, like Parcel or Webpack.

Problem 3: there are sub-dependencies, so we need to build all packages first and only after we can run tests. That is why we need pretest script.

Storybook

Install storybook according to official instruction.

We will need the following things in package.json:

"scripts": {
  "start": "start-storybook -p 8080",
  "build": "build-storybook -o dist"
},
"dependencies": {
  "@stereobooster/d": "*",
  "@stereobooster/b": "*",
  "@stereobooster/c": "*"
},
"devDependencies": {
  "@babel/core": "7.4.3",
  "@storybook/addon-info": "^5.0.11",
  "@storybook/addons": "5.0.6",
  "@storybook/core": "5.0.6",
  "@storybook/react": "5.0.6",
  "@types/storybook__addon-info": "^4.1.1",
  "@types/storybook__react": "4.0.1",
  "awesome-typescript-loader": "^5.2.1",
  "babel-loader": "8.0.5",
  "react-docgen-typescript-loader": "^3.1.0"
}

Create configurations in .storybook (again, based on official instruction). Now we can create stories in /src/b for b packages, in /src/c for c package.

Storybook will watch for changes in stories/src, but not for changes in d/src, b/src, c/src. We will need to use TypeScript to watch for changes in other packages.

Add to package.json of d, b and c packages:

"scripts": {
  "start": "tsc -w"
}

and to the root package.json:

"scripts": {
  "prestart": "yarn build",
  "start": "lerna run start --stream --parallel"
}

Now a developer can run yarn start (in one terminal) and yarn test --watch (in another terminal) to get development environment - scripts will watch for changes and reload.

Problem 3: there are sub-dependencies, so we need to build all packages first and only after we can run the start script. That is why we need prestart script.

Problem 4: If there is type error in stories it will show up in the browser, but if there is type error in d, b or c packages it will only show up in terminal, which spoils all DX, because instead of switching between editor and browser you will need to switch to terminal as well to check if there is an error or not.

More Repositories

1

react-snap

👻 Zero-configuration framework-agnostic static prerendering for SPAs
JavaScript
5,025
star
2

react-ideal-image

🖼️ An Almost Ideal React Image Component
JavaScript
3,273
star
3

package.json

🗃️ package.json fields explained
951
star
4

css-in-js-101

💈 CSS-in-JS 101: All you need to know
249
star
5

type-o-rama

👾 JS type systems interportability
243
star
6

programming-languages-genealogical-tree

Programming languages genealogical tree
231
star
7

jekyll-press

🚨 [deprecated] Minifier plugin for jekyll. Minifies all html, js, css files. Simple just drop it in solution. No Java required
Ruby
149
star
8

react-modal-experiment

JavaScript
109
star
9

write-you-a-programming-language

List of small programming languages that you can implement in a relatively small amount of time for educational purposes.
99
star
10

guide-to-async-components

📖 Guide To JavaScript Async Components
79
star
11

diamondback-ruby

⛑ Fork of diamondback-ruby
Ruby
70
star
12

awesome-hiring-process

Collection of links and ideas about the hiring process in the IT industry
58
star
13

ruby-json-benchmark

Ruby json benchmark
Ruby
36
star
14

html_press

🚨 [deprecated] Ruby gem for compressing html
Ruby
35
star
15

pragmatic-types

Small practical guide on Flow and TypeScript for JavaScript developers
33
star
16

jshintrb

🚨 [deprecated] Ruby wrapper for JSHint
Ruby
31
star
17

mobile-safari-fullscreen

Fix for Mobile Safari fullscreen issue
JavaScript
23
star
18

ruby-memory-issues

🐲 Ruby Memory Issues and Where to Find Them
22
star
19

the-button

JavaScript
17
star
20

rb-fchange

🚨 [deprecated] Gem which uses native windows methods for watching changes of file system
Ruby
15
star
21

react-accessible-accordion

Accessible React accordion component
JavaScript
15
star
22

awesome-vscode-dev-containers

A curated list of VS Code Containers
15
star
23

d3-tube

D3 implementation of tube map
JavaScript
14
star
24

main-module-browser-test

Experiment
JavaScript
12
star
25

jekyll_oembed

🚨 [deprecated] Jekyll plugin to embed objects with the help of oEmbed. Simple liquid tag
Ruby
12
star
26

html_minifier

Ruby wrapper for kangax html-minifier
JavaScript
11
star
27

dev.wtf

HTML
10
star
28

headless-cms-comparison

JavaScript
9
star
29

the-history-of-frontend-development

Current state of frontend development is controversial. How we got here?
9
star
30

rb-notifu

🚨 [deprecated] Notification system for windows. Trying to be Growl
Ruby
8
star
31

sqip.macro

Webpack sqip-loader implemented as babel-plugin-macros
JavaScript
8
star
32

social_detector

Detect if visitors are logged into social networks
Ruby
8
star
33

webpack-comment-import.macro

JavaScript
7
star
34

css-modules-components

styled-components for CSS Modules
JavaScript
7
star
35

postgresql-experiment

JavaScript
6
star
36

css_press

🚨 [deprecated] Ruby gem for compressing CSS
Ruby
6
star
37

jBar2

jBar is a simple and lightweight jQuery notification (call to action) banner
JavaScript
4
star
38

useful-react-snippets

TypeScript
4
star
39

tree-sitter-wasm

Shell
4
star
40

react-async-issue

JavaScript
3
star
41

react-lingui-example

JavaScript
3
star
42

unstyled-components

styled-components based on React's style prop
JavaScript
3
star
43

github-issues

Github issues
3
star
44

react-fsm-example

JavaScript
3
star
45

react-simple-country-select

JavaScript
3
star
46

submodule

Small gem to simplify building process of gems with git submodules. Tended to be used for ruby gems which wrap js libraries or another assets
Ruby
2
star
47

zoos

Zoo is an attempt to classify things.
2
star
48

stereobooster.github.io

CSS
2
star
49

wisp

Mirror of https://hg.sr.ht/~arnebab/wisp
Scheme
2
star
50

readme

About me and my open-source work
2
star
51

cs-video

Computer science videos
2
star
52

parsing-with-derivalives

JavaScript
2
star
53

puma-benchmarks

Ruby
2
star
54

small-bits

Small bits of web UX
JavaScript
1
star
55

react-router-redux-example

JavaScript
1
star
56

docker-reasonml

Dockerfile
1
star
57

waypoint-bug-report

waypoint-bug-report
JavaScript
1
star
58

natural_sort-pgxn

Makefile
1
star
59

art_typograf

Ruby wrapper for typograf.artlebedev.ru webservice
Ruby
1
star
60

crystal-lisp

Crystal
1
star
61

main-module-browser

1
star
62

explain-you-mysql

JavaScript
1
star
63

loadable-components.macro

JavaScript
1
star
64

jekyll-seo-lint

Jekyll plugin to validate metadata provided in front matter and in configuration
Ruby
1
star
65

jevix

mirror of http://jevix.googlecode.com/svn/
PHP
1
star
66

jekyll_press

moved to https://github.com/stereobooster/jekyll-press
Ruby
1
star
67

react-ts-experiment

TypeScript
1
star