Giter Site home page Giter Site logo

sample-monorepo's Introduction

sample-monorepo

Build Status

Sample monorepo setup with npm workspaces and typescript project references.

Getting started

Clone repository and execute the following commands in the root:

  • npm i
  • npm run build
  • npm start - to see the client running in dev-mode (non-minified; with source-maps)
  • npm run start:server - to see server running (with SSR; client is minified with source-maps)

Setup explained

Tooling

  • Monorepo is installed using npm.

    • Packages are automatically linked together, meaning you can do cross-package work within the repo.
    • devDependencies are common, and only appear in the root package.json. Easier to manage and upgrade.
    • Each package has its own scripts and dependencies. They are being installed in the root node_modules, using the same deduping mechanism npm uses for single packages.
    • Adding new packages is as simple as dropping an existing package in the packages folder, and re-running npm i.
  • Sources and tests are written in strict TypeScript.

    • Common base tsconfig.base.json.

Included sample packages

Basic structure and configurations

.github                  // CI flow configuration (GitHub Actions)
packages/
  some-package/
    src/
      test/              // package-specific test folder
        test.spec.ts
      index.ts
      tsconfig.json      // package-specific config, built to "some-package/dist"
    LICENSE              // license file. included in npm artifact
    package.json         // package-specific deps and scripts
    README.md            // shown in npmjs.com. included in npm artifact

.eslintignore            // eslint (linter) ignored directories/files
.eslintrc                // eslint (linter) configuration
.gitignore               // github's default node gitignore with customizations
.prettierignore          // prettier (formatter) ignored directories/files
.prettierrc              // prettier (formatter) configuration
lerna.json               // lerna configuration (needed for deployment below)
LICENSE                  // root license file. picked up by github
package-lock.json        // the only lock file in the repo. all packages combined
package.json             // common dev deps and workspace-wide scripts
README.md                // workspace-wide information. shown in github
tsconfig.base.json       // common typescript configuration
tsconfig.json            // solution-style root typescript configuration
webpack.config.js        // root webpack configuration. inherited by app's webpack config

Styling solutions

This repository aims to avoid showcasing styling solutions in-depth.

Webpack's experimental CSS handling is turned on for the sanitize.css library being used, but the infrastructure doesn't contain any asset copying (into dist folder) and so doesn't support local css assets.

Each styling solution has its own set of infrastructure requirements.

CSS-in-JS based solutions, for example, probably won't need to worry about it at all, and work without additional setup.

Within Wix, we use Stylable, which has its own CLI (stc) to build and/or copy .st.css files into dist.

Full support for source code importing .css/.scss/.less/.whatever would require additional building. It would have to be addressed for Node as well, if one wants to execute tests importing these source files.

Dependency management

Traditionally, working with projects in separate repositories makes it difficult to keep versions of devDependencies aligned, as each project can specify its own devDependency versions.

Monorepos simplify this, because devDependencies are shared between all packages within the monorepo.

Taking this into account, we use the following dependency structure:

  • devDependencies are placed in the root package.json
  • dependencies and peerDependencies are placed in the package.json of the relevant package requiring them, as each package is published separately

New devDependencies can be added to the root package.json using npm:

npm i <package name> -D

Some packages depend on sibling packages within the monorepo. For example, in this repo, @sample/app depends on @sample/components. This relationship is just a normal dependency, and can be described in the package.json of app like so:

  "dependencies": {
    "@sample/components": "<package version>"
  }

Deployment

npx lerna publish will publish new versions of the packages to npm.

Lerna asks for new version numbers for packages that changed since last release and their dependencies. Every package has a prepack script which automatically runs build prior to packing.

npx lerna publish --force-publish will force a release of all packages, regardless of which ones actually changed.

Deployment of app/server assets to any actual production servers is not shown.

sample-monorepo's People

Contributors

avivahl avatar dependabot-preview[bot] avatar dependabot[bot] avatar eric-hc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sample-monorepo's Issues

npmjs resolution of relative links in packages/*/README.md

Typical of monorepos, this sample has npm packages in a packages directory, e.g. @sample/app is in packages/app/. From what I've seen in my own monorepo, relative markdown links (backed by github repos) point to:

https://github.com/\<group\>/\<repo\>/blob/HEAD/\<markdown-link\>

instead of

https://github.com/\<group\>/\<repo\>/blob/HEAD/packages/\<package-dir\>/\<markdown-link\>

If you know how to make a relative link in packages/app/ point to

https://github.com/wixplosives/sample-monorepo/blob/HEAD/packages/app/\<markdown-link\>

, could you add an example to app's README?

CI/CD and a Dockerfile

Thanks for the example monorepo! It is hard to find good examples. Would it be possible to provide a Dockerfile, and, if possible, an example CI/CD pipeline (Github actions, Jenkinsfile, etc.).

any solution for the code lint ?

for example eslint, stylelint.
when our monorepo packages had their own lint check.
it is very hard to use one config for every packages.
and something like husky,lint-stage. it is hard to figure out where they should be.

Is it required to run a full monorepo build before test?

Hi there,
I am browsing around looking for monorepo templates and this one looked great

However, I am curious: is it required to run a full monorepo build to perform a test? On a large codebase, this could be a pain point, but I am not sure if there is a workaround because I ran into trying to make our own monorepo....

In non-monorepo setups, it seemed like it was fine to test without building first, but because there are inter-dependencies in the monorepo, it expects those to be built.

Just curious if you had thoughts on this

Components with React as Peer Dependency

This is more of a question, but won't React be bundled twice in this setup since both components and app depend on React? Or as long as the version is identical they will use the same?

Either way, components should have React as peer dep. so you could potentially publish it as a package and use in other projects:
https://yarnpkg.com/blog/2018/04/18/dependencies-done-right/

I'm mainly asking because when I tried doing a monorepo with peer deps. I encountered a problem with React not resolving properly.

git tagging in monorepo

It would be nice if you can show the best practices while doing a monorepo
like tagging and releases

alt discussion

Avi, sorry for the delay on updating the pull request.

Will you have a look at https://github.com/jeremy-coleman/monorepo-starterkit?

it's definitely not production worthy, but i'd like your feedback on the setup . there are also some useful scripts for auto-generating a typescript build config inside the scripts folder, but I just can't come up with a way to make it work practically with aliases. If you think it's all trash thats fine too, lol

Deployment

How do you go about packaging & deployment with this structure?

why can the vscode recognize the source path when the exports field in not include the src

thx for sharing this repo!
I have one question.
The exports described in compoents is the output path and not include src
"exports": { ".": "./dist/index.js", "./package.json": "./package.json" },
But when editing the import of comeponent in the vscode,
import { Main } from '@sample/components';
it will navigate to 'sample-monorepo/packages/component/src/index'.
why is it that? I think the correct path is to the dist/index.d.ts if has build by tsc or failed to find module if hasn't build

Lerna is not actually part of your devDependencies

Hi there,

Great monorepo sample, I noticed that the package.json does not actually reference Lerna anywhere even though you're mentioning it in the readme, I know that it can work with just npx lerna but it's probably better to include it in the package.json

Also another note that I came across your repo mainly because of a comment you recently posted on a recent PR of Lerna v5.2.0 which is now installing Nx even if you don't want it and I'm agreement with you there. I was afraid that the project now being directed by Nrwl would eventually have them push their own products. It's sad to see they're going all in with that direction, especially for users who might prefer or already have other tools configured like TurboRepo. On the good side there are alternatives, you can take a look at Lerna-Lite that I created few months before Nrwl took over stewardship of Lerna, at first I thought it was a bad timing from my side to create it before Lerna came back alive, but now that I see the direction they're going, I'm actually glad that I created Lerna-Lite which I use in my own monorepos. On the other end I did add their useNx option but it's totally and will remain optional and that's the way it should always be.

So long story short, you can read all about it on why I created Lerna-Lite, and there's extra features like the support of yarn/pnpm workspace: protocol and other extras that Lerna doesn't yet have. I also keep in sync with Lerna and recreate most of their PRs, except for the ones that I'm less interested like the one you wrote a comment about, I'm also ๐Ÿ˜ฑ to that Nx change, that will obviously not be pushed into Lerna-Lite.

Anyway, if that is of no interest then disregard the post and close the issue
Cheers and happy coding ๐Ÿ˜‰

scripts do not respect dependency order

In the readme, it says
Automatically ensures order when using lerna run [script], meaning that if package-a depends on package-b, it will run package-b's scripts first.

But this does not actually appear to happen. For example, if I delay the build of components (by changing its build script to something like sleep 10 && ts-build...) it clearly completes well after app's build script runs. In fact, it looks like when I do that, what actually happens is that app searches the directory for index.ts in src and then uses that to get type information. If I change the src directory to another name (and update ts-build to reference that instead of src), then app fails to build unless I take the sleep 10 out, at which point it may build because components builds pretty quickly.

Not a huge issue, but I found this repo because I was trying to pin down if Lerna actually does use its dependency graph to make sure scripts complete where dependencies are involved and hoped that this sample demonstrated that it did.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.