Giter Club home page Giter Club logo

tsx-monorepo's Introduction

TSX-monorepo

This project is an opinionated collection of tools, apps, and libraries intended for supporting rapid React UI development. It was heavily inspired by GitHub's Primer design system.

Note: This library is no longer under active development. It was a fun project while it lasted, but I've taken it internal for use within Qualcomm.


Live build here: https://tsx-monorepo.com/


Disclaimers

Development for this project is ongoing - not sure how much longer the repo is going to stay public.

Mobile support is coming soon - just need to spruce up the sidebar. The nav menu doesn't have links yet, and you'll be stuck on the homepage unless you navigate to urls directly.


Table of contents

Goals

  • Consistent code formatting in every package via ESLint.
  • First class TypeScript support.
  • Hot reloading adjacent packages for rapid development.
  • First class documentation support via MDX and react-live.
  • Consistent styling by use of styled-components and styled-system with a strongly typed design system.
  • Tree shaking for every React library.
    • This is accomplished using webpack's side effects. Learn more.
  • Working "go to definition" feature in IDEs for every package.
  • Icons by react-icons.
  • Unit Testing support via Jest and React Testing Library.
  • E2E testing with Playwright + Jest.

Setup

  • Ensure that you have Node and Yarn installed.
    • I run Node v14+ and haven't tried any lesser versions. Your mileage may vary if you're not on v14+.
    • Yarn 2.0+ currently has an issue with the & operator in package.json scripts. Use Yarn v1.22.10 until this is resolved.

Go-to definition (jump to the source file)

  • WebStorm/IntelliJ
    • This should work out of the box with either of these. If the Go to Declaration or Usages option is taking you to the dist/ folder of the target component, try using the Go to Implementation(s) option instead.
  • VSCode
    • The Go to Definition option works out of the box for me. I'd highly recommend binding this to Ctrl+Click.

Running projects and libs

  • Unless otherwise noted, run all yarn commands from the root of this repository. This is particularly important for yarn install. For more details on why this is necessary, read up on yarn workspaces and lerna.

Projects

  • Standalone Front End applications are located within packages/apps.
  • Shared libraries and utilities are located within packages/libs.
  • Data fetching APIs and libraries are located within packages/data.
    • Note: it's perfectly fine for isolated apps to include their own data fetching apis within their respective package folders.

Docs

The NextJS application at packages/docs is responsible for rendering MDX components. Shared components that contain a corresponding mdx file are aggregated by this package. For more information, check out the docs readme.

Running locally

  • run yarn install from the root.
  • run yarn docs from the root of this repository. Executes yarn run docs --parallel --stream which does the following:
    • starts @rb/monorepo-docs in dev mode using next dev
    • runs @rb/react-style-system and @rb/react-components in watch mode (using tsc) which triggers a recompile on change (hot reloading).
    • There's additional configuration details in the packages/docs package that forces the site to hot-reload when MDX files are changed.

Conventions

  • Every package must contain at least the following:
    • a package.json file.
    • either a src folder with code specific to the package's library or framework or an index.js/index.ts that exports the code or configuration of the package ( JS/TS packages only).
    • a tsconfig.json (TypeScript projects only).
  • Within a TypeScript React app, it's recommended that path aliasing be setup such that directories from the local package starts with ~.
    • The base ESLint configuration is set up to split import groups based on external, internal, and sibling/parent/child. A 4th grouping is configured for apps-specific internal files. This is done for organizational purposes, as it's much easier to determine the origin of the imported code.
    • Example for a package with src/components and src/pages folder:
  // src/components/simple-div/SimpleDiv.tsx
import React from "react"

export default function SimpleDiv(): JSX.Element {
  return <div />
}
// src/pages/about.tsx
import React from "react"

import SimpleDiv from "~components/simple-div/SimpleDiv.tsx"

import {localUtilityFunc} from "./utils"

export default function AboutPage(): JSX.Element {
return <SimpleDiv onClick={localUtilityFunc} />
}

React Best Practices:

Separate your styles from your api logic. This makes testing significantly easier and keeps your component files small and self-contained.

  • A Data component does data fetching and then renders its corresponding View component. That’s it.
Problem:
// src/components/example/Example.tsx
import React from "react"

import useDataExample from "./utils"

export default function Example(): JSX.Element {
  // Problem: we've now coupled this component to some arbitrary 
  // API logic. This component may not render properly if the api 
  // isn't available during testing (common during CI).
  const {data} = useSomeApiData()
  return (
    <div>
      {/* apply styles, etc... */}
      {data}
    </div>
  )
}

Solution: split the component using the Data/View pattern.

// src/components/example/ExampleView.tsx
import React from "react"

export interface ViewProps {
  // never use `any` like this.  It's just an example.
  data: any
}

export default function ExampleView({data}: ViewProps): JSX.Element {
  return (
    <div>
      {/* apply styles, etc... */}
      {data}
    </div>
  )
}
// src/components/example/ExampleData.tsx
import React from "react"

import ExampleView from "./ExampleView"
import useDataExample from "./utils"

export default function ExampleData(): JSX.Element {
  const {data} = useSomeApiData()
  return <TableView data={data} />
}

Now we're more flexible. We've eliminated the API coupling by placing the styles in a separate component. However, this presents with a tradeoff.

Pros:

  • More flexible and likely more accurate tests.
  • Can reuse the ExampleData container to supply the same logic to another component.

Cons:

  • Additional file to maintain (potentially offset by SoC).
  • We now have to mock the API logic in order for the tests to pass.

Read more on the Data/View pattern here.

Feature Driven Development (FDD).
  • This is a lightweight Agile technique. It involves a project structure where your code is organized by what it accomplishes (i.e. features), rather than lumping all modules of like types into separate blobs of components, routes, logic, actions, etc.
  • There is a direct correlation between the problem space (the requirements) and the implementation (the code)
FDD Folder Structure
  • Reusable components that are specific to an application but not a feature should reside in src/components.

  • Reusable components without a specific application should be placed in the react-components package.

  • For a given featured name <feature-name>, place all related code in src/features/<feature-name>.

    • For large features, split the feature folder into multiple subfolders.

packages/libs/react-*

  • Should not include code specific to project.
  • They should not rely on project specific code, constants, router, etc.

References

See the following blog posts. This guy is pretty good. I used his monorepo as a starting point for this repository:

tsx-monorepo's People

Contributors

r-bower avatar

Stargazers

Evan Carey avatar Sam Holmes avatar

Watchers

 avatar

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.