Skip to content
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

Add initial monorepo template #778

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions templates/monorepo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
*.log
.DS_Store
node_modules
dist

node_modules
package-lock.json
yarn.lock
!/yarn.lock
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no lockfiles? is this a Lerna thing?

Copy link
Owner Author

@jaredpalmer jaredpalmer Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lerna thing. You don’t want lockfiles in packages/did because modules are hoisted to the yarn workspace

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But surely we still want the root yarn.lock on line 13?


.yalc
yalc.lock
21 changes: 21 additions & 0 deletions templates/monorepo/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) <year> <author>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
85 changes: 85 additions & 0 deletions templates/monorepo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# TSDX Monorepo User Guide

## Usage

This monorepo is setup for a dummy `@mono/` NPM organization. There are 2 packages by default:

- `@mono/react` - A placholder React component
- `@mono/utils` - A utils packages

Unlike other TSDX templates, the developer experience for this template is currently a bit more manual.

Your first order of business will be to search and replace `@mono` for the npm organization of your own.
Copy link
Collaborator

@agilgur5 agilgur5 Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also need to change author/username and LICENSE file. And description of packages, though that one's a given since the other templates don't do that either.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lerna syncs the license from root prior to publishing for each package. lerna/lerna@5863564


After that you can install all the dependencies in the root directory. Since the monorepo uses Lerna and Yarn Workspaces, npm CLI is not supported (only yarn).

```sh
yarn install
```

This will install all dependencies in each project, build them, and symlink them via Lerna

## Development workflow

In one terminal, run tsdx watch in parallel:

```sh
yarn start
```

This builds each package to `<packages>/<package>/dist` and runs the project in watch mode so any edits you save inside `<packages>/<package>/src` cause a rebuild to `<packages>/<package>/dist`. The results will stream to to the terminal.

### Using the example/playground

You can play with local packages in the Parcel-powered example/playground.

```sh
cd example
yarn install # or yarn install
yarn start
```

This will start the example/playground on `localhost:1234`. If you have lerna running watch in parallel mode in one terminal, and then you run parcel, your playground will hot reload when you make changes to any imported module whose source is inside of `packages/*/src/*`. Note that to accomplish this, each package's `start` command passes TDSX the `--noClean` flag. This prevents Parcel from exploding between rebuilds because of File Not Found errors.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This will start the example/playground on `localhost:1234`. If you have lerna running watch in parallel mode in one terminal, and then you run parcel, your playground will hot reload when you make changes to any imported module whose source is inside of `packages/*/src/*`. Note that to accomplish this, each package's `start` command passes TDSX the `--noClean` flag. This prevents Parcel from exploding between rebuilds because of File Not Found errors.
This will start the example/playground on `localhost:1234`. If you have Lerna running watch in parallel mode in one terminal, and then you run Parcel, your playground will hot reload when you make changes to any imported module whose source is inside of `packages/*/src/*`. Note that to accomplish this, each package's `start` command passes TSDX the `--noClean` flag. This prevents Parcel from exploding between rebuilds because of "File Not Found" errors.
  • TDSX -> TSDX
  • parcel -> Parcel
  • lerna -> Lerna

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helps readability, please approve.


Important Safety Tip: When adding/altering packages in the playground, use `alias` object in package.json. This will tell Parcel to resolve them to the filesystem instead of trying to install the package from NPM. It also fixes duplicate React errors you may run into.

#### Yalc

[Yalc](https://github.com/whitecolor/yalc) is an alternative to `yarn/npm link` (and Parcel aliasing) that many developers find useful because it more closely mimics how NPM works. It works kind of like a local package registry via filesystem and symlinking magic.

To do this, install yalc globally.

Using NPM:

```sh
npm i yalc -g
```

Using Yarn:

```sh
yarn global add yalc
```

Then in each package's `start` command add a [`yalc publish`](https://github.com/whitecolor/yalc#publish) or `yalc push` as an TSDX `--onSuccess` hook.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Then in each package's `start` command add a [`yalc publish`](https://github.com/whitecolor/yalc#publish) or `yalc push` as an TSDX `--onSuccess` hook.
Then in each package's `start` command add a [`yalc publish`](https://github.com/whitecolor/yalc#publish) or `yalc push` as a TSDX `--onSuccess` hook.

an TSDX -> a TSDX


```diff
"scripts": {
- "start": "tsdx watch --verbose --noClean",
+ "start": "tsdx watch --verbose --noClean --onSuccess yalc publish",
Comment on lines +68 to +69
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- "start": "tsdx watch --verbose --noClean",
+ "start": "tsdx watch --verbose --noClean --onSuccess yalc publish",
- "start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean",
+ "start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean --onSuccess yalc publish",

Should be updated to match the updated watch command that uses tsconfig.build.json

This comment was marked as spam.

"build": "tsdx build --tsconfig tsconfig.build.json",
"test": "tsdx test",
"lint": "tsdx lint",
"prepublish": "npm run build"
},
```

In your example directory, now add each package via yalc

```sh
yalc add <package>
# or
yalc link <package>
```

There's definitely room for improvement with this workflow, so please contribute if you come up with something better.
3 changes: 3 additions & 0 deletions templates/monorepo/example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.cache
dist
14 changes: 14 additions & 0 deletions templates/monorepo/example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Playground</title>
</head>

<body>
<div id="root"></div>
<script src="./index.tsx"></script>
</body>
</html>
14 changes: 14 additions & 0 deletions templates/monorepo/example/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'react-app-polyfill/ie11';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Thing } from '@mono/react';

const App = () => {
return (
<div>
<Thing message="hello worldzz" />
</div>
);
};

ReactDOM.render(<App />, document.getElementById('root'));
25 changes: 25 additions & 0 deletions templates/monorepo/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@mono/example",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "parcel index.html",
"build": "parcel build index.html"
},
"dependencies": {
"react-app-polyfill": "^1.0.0"
},
"alias": {
"@mono/react": "../packages/react",
"react": "../node_modules/react",
"react-dom": "../node_modules/react-dom/profiling",
"scheduler/tracing": "../node_modules/scheduler/tracing-profiling"
agilgur5 marked this conversation as resolved.
Show resolved Hide resolved
},
"devDependencies": {
"@types/react": "^16.9.11",
"@types/react-dom": "^16.8.4",
"parcel": "^1.12.3",
"typescript": "^3.4.5"
}
}
18 changes: 18 additions & 0 deletions templates/monorepo/example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": false,
"target": "es5",
"module": "commonjs",
"jsx": "react",
"moduleResolution": "node",
"noImplicitAny": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"removeComments": true,
"strictNullChecks": true,
"preserveConstEnums": true,
"sourceMap": true,
"lib": ["es2015", "es2016", "dom"],
"types": ["node"]
}
}
10 changes: 10 additions & 0 deletions templates/monorepo/lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": "0.0.0",
"registry": "https://registry.npmjs.org/",
"publishConfig": {
"access": "public"
agilgur5 marked this conversation as resolved.
Show resolved Hide resolved
},
Comment on lines +3 to +6
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these necessary? I believe these are the defaults

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for scoped packages

"npmClient": "yarn",
"useWorkspaces": true,
"packages": ["packages/*"]
}
28 changes: 28 additions & 0 deletions templates/monorepo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "mono",
"private": true,
"devDependencies": {
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8",
"lerna": "^3.15.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"tsdx": "^0.13.2",
"typescript": "^3.9.7"
},
"workspaces": [
"packages/*"
],
"scripts": {
"lerna": "lerna",
"start": "lerna run start --stream --parallel",
"test": "lerna run test --",
"build": "lerna run build",
"prepublish": "lerna run prepublish"
},
"prettier": {
"trailingComma": "es5",
"singleQuote": true,
"semi": true
}
Comment on lines +23 to +27
Copy link
Collaborator

@agilgur5 agilgur5 Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"prettier": {
"trailingComma": "es5",
"singleQuote": true,
"semi": true
}
"prettier": {
"printWidth": 80,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
}

Let's keep consistent with what all the other templates use

This comment was marked as spam.

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

husky isn't included in here? The other templates have it

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

husky should be included in the root package.json, however its a nice to have feature compared to being able to init a mono repo with mostly the same tsdx configs.

5 changes: 5 additions & 0 deletions templates/monorepo/packages/react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# @mono/react

[![Stable release](https://img.shields.io/npm/v/@mono/utils.svg)](https://npm.im/@mono/utils)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[![Stable release](https://img.shields.io/npm/v/@mono/utils.svg)](https://npm.im/@mono/utils)
[![Stable release](https://img.shields.io/npm/v/@mono/react.svg)](https://npm.im/@mono/react)


Official React SDK for @mono
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a component or an SDK? In the README it says component. In package.json it says library (akin to SDK).

If it's a component it might be more intuitive to rename this to component1 or something

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be either, it’s just a placeholder. I copied it from the project I’m working on. My plan was to make this fairly generic, and then build some more templates/plopfiles for different kinds of packages people will want.

36 changes: 36 additions & 0 deletions templates/monorepo/packages/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@mono/react",
"version": "0.0.0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"version": "0.0.0",
"version": "0.0.0",
"license": "MIT",

MIT license missing. We probably want to include a LICENSE file in each package as well. NPM will automatically include any LICENSE file when publishing (similar to README.md)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lerna copies root license into each package before publishing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, does it do that for package.json.license too? Fancy

"description": "Official React library for @mono",
"author": "Jared Palmer",
"repository": {
"type": "git",
"url": "git+https://github.com/mono/mono.git",
"directory": "packages/react"
},
"scripts": {
"start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean",
"build": "tsdx build --tsconfig tsconfig.build.json",
"test": "tsdx test",
"lint": "tsdx lint",
"prepublish": "npm run build"
},
"main": "dist/index.js",
"module": "dist/react.esm.js",
"typings": "dist/index.d.ts",
"files": [
"README.md",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"README.md",
"src",

"dist"
],
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0"
},
Comment on lines +25 to +28
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"peerDependencies": {
"react": "^16.8.0",
"react-dom": "^16.8.0"
},
"peerDependencies": {
"react": ">=16",
},

Let's keep this consistent with the React templates

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof I didn't realize this was still there. Packages that use hooks actually need to specify React as peer dep as "react": "^16.8.0" (when hooks were introduced). We should discuss in another issue tho as we will need to change the other templates too

"dependencies": {
"@mono/utils": "^0.0.0",
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
Comment on lines +33 to +35
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary?

}
10 changes: 10 additions & 0 deletions templates/monorepo/packages/react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from 'react';
import { toSlug } from '@mono/utils';

export interface ThingProps {
message: string;
}

export function Thing(props: ThingProps) {
return <>{toSlug(props.message)}</>;
}
5 changes: 5 additions & 0 deletions templates/monorepo/packages/react/test/react.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('@mono/react', () => {
it('works', () => {
expect(true).toBe(true);
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep consistent with the test in the React template.

Could add message prop in addition to that if wanted

4 changes: 4 additions & 0 deletions templates/monorepo/packages/react/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.build.json",
"include": ["src", "types", "../../types"]
}
7 changes: 7 additions & 0 deletions templates/monorepo/packages/utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# @mono/utils

[![Stable release](https://img.shields.io/npm/v/@mono/utils.svg)](https://npm.im/@mono/utils)

Shared utilities for various `@mono` packages.

**Important:** This package is intended for internal use by the @mono libraries. You should not use it directly in your production projects, as the APIs can and will change often without regard to sem-ver. You have been warned!
26 changes: 26 additions & 0 deletions templates/monorepo/packages/utils/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@mono/utils",
"version": "0.0.0",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"version": "0.0.0",
"version": "0.0.0",
"license": "MIT",

MIT license missing. We probably want to include a LICENSE file in each package as well. NPM will automatically include any LICENSE file when publishing (similar to README.md)

"description": "Internal, shared utilities",
"author": "Jared Palmer <hello@formium.io>",
"scripts": {
"start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean",
"build": "tsdx build --tsconfig tsconfig.build.json",
"test": "tsdx test",
"lint": "tsdx lint",
"prepublish": "npm run build"
},
"main": "dist/index.js",
"module": "dist/utils.esm.js",
"typings": "dist/index.d.ts",
"files": [
"README.md",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"README.md",
"src",

"dist"
],
"dependencies": {
"tslib": "^2.0.0"
},
"publishConfig": {
"access": "public"
}
Comment on lines +23 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it allows you skip passing a flag when you publish a scoped package. However, when we revamp the create command, we should ask explicitly whether the repo is going to be private or public if it is scoped.

}
19 changes: 19 additions & 0 deletions templates/monorepo/packages/utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Return a slugified copy of a string.
*
* @param {string} str The string to be slugified
* @return {string} The slugified string.
*/
export function toSlug(str: string): string {
let s = str;
if (!s) {
return '';
}
s = s.toLowerCase().trim();
s = s.replace(/ & /g, ' and ');
s = s.replace(/[ ]+/g, '-');
s = s.replace(/[-]+/g, '-');
s = s.replace(/[^a-z0-9-]+/g, '');
s = s.length > 32 ? s.substr(0, 32) : s;
return s;
}
5 changes: 5 additions & 0 deletions templates/monorepo/packages/utils/test/utils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('@mono/utils', () => {
it('works', () => {
expect(true).toBe(true);
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep consistent with the test in the basic template or have a simple test for toSlug.

4 changes: 4 additions & 0 deletions templates/monorepo/packages/utils/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.build.json",
"include": ["src", "types", "../../types"]
}
17 changes: 17 additions & 0 deletions templates/monorepo/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "esnext",
"lib": ["dom", "esnext"],
"importHelpers": true,
"declaration": true,
"sourceMap": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"jsx": "react",
"esModuleInterop": true
}
}
Loading