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

🧰 Frontend Infrastructure and Tooling 🛠️ #3

Merged
merged 22 commits into from
Apr 12, 2021

Conversation

codemonkey800
Copy link
Collaborator

@codemonkey800 codemonkey800 commented Apr 9, 2021

Description

View Rendered README.md

This PR sets up the infrastructure and tooling for the napari hub frontend. The README includes a list of the tech we use:

From client/README.md

References

Several frontend infra/tooling choices were inspired by decisions made in other CZI frontend repos:

CSS Modules in edu-design-system

In the beginning, the edu-design-system was originally using twin.macro for CSS-in-JS Tailwind styles. I experimented with twin.macro in the React POC and found the developer experience awesome. Later on the team switched to CSS modules for several reasons outlined in chanzuckerberg/edu-design-system#362. After consideration, I decided that CSS modules would be a good choice because:

  1. Able to take advantage of full flexibility of SCSS.
  2. More accessible for non-JavaScript experts.
  3. Meaningful class names per element.
  4. Easy to work with dynamic className using clsx package.
  5. Zero-runtime vs emotion which has a runtime
  6. No incredibly long Tailwind class name strings. For example: tw="flex flex-auto items-center justify-center lg:grid ..."
  7. We can separate Tailwind classes by line and organize them based on functionality:
.appBar {
  @apply flex flex-auto;
  @apply items-center justify-center;
  @apply lg:grid ...;
}

Plop Generators in edu-design-system

The team has a plopfile.js file for generating components. This would be extremely valuable to have in the napari hub client because we can:

  1. Standardize the component file structure.
  2. Automate away the boilerplate for common routines.
  3. Provide tooling for people less experienced with frontend or that are new to the repo.

E2E Testing in corpora-data-portal

The team setup the corpora-data-portal in a way that allows E2E tests with Playwright, and so the E2E test configuration for napari hub closely resembles the configuration used in the corpora-data-portal repo.

@codemonkey800 codemonkey800 force-pushed the jeremy/frontend-infra branch from 08a9dea to 6391670 Compare April 9, 2021 17:30
@codemonkey800 codemonkey800 force-pushed the jeremy/frontend-infra branch from 6391670 to 8953850 Compare April 9, 2021 17:31
@codemonkey800
Copy link
Collaborator Author

There are a lot of things to document here regarding the tooling and infrastructure that I didn't quite get to doing in this PR. I plan on writing up some documentation in a future PR detailing everything outlined here. Also, things might change during review, so I want to make sure I write documentation for what's already merged in 😄

"noUnusedLocals": true,
"noUnusedParameters": true,
"paths": {
"@/*": ["./src/*"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This path mapping means that source code imports will be from @/*. For example, to import a component from a page:

import { AppBar } from '@/components';

Would love to hear opinions on this vs something like:

  • Tilde: ~/components or ~components
  • Relative: ../components
  • Dollar sign lib (similar to SvelteKit) : $lib/components
  • Src prefix: src/components

I decided to use the @/* prefix because:

  1. It's immediately obvious that this import is from the source code and not from a package
  2. Built in support for grouping and sorting using eslint-plugin-simple-import-sort
  3. Fixes issue with relative import hell import { AppBar } from '../../components';

Copy link
Member

Choose a reason for hiding this comment

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

is this common practice, or is there a different standardized way of doing this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

is this common practice, or is there a different standardized way of doing this?

@kne42 I've outlined the most common formats above, but there isn't really a standardized practice for path mapping. I do know that several CZI projects use the src/* format:

https://github.com/chanzuckerberg/corpora-data-portal/blob/d7bc0c2aef8a09b311f1bb20c1755567dabcc4fa/frontend/tsconfig.json#L14-L16
https://github.com/chanzuckerberg/aspen/blob/0ecfd26e05883e6b6f61712ed96697ede606e6d8/src/ts/tsconfig.json#L20-L24

There is a way we can customize the grouping and support something like src/* or something, but I don't have any strong opinions.

What is nice about @/* is that it works with eslint-plugin-simple-import-sort out of the box, and it's 2 characters less to type than src/*.

Copy link

@tihuan tihuan Apr 9, 2021

Choose a reason for hiding this comment

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

Ah I think @ is used for scoped packages too, like from '@angular, from "@emotion, from "@material-ui/core/styles", etc.. So that might collide with npm packages as well!

My projects have been straight up using from "src/*" for autocomplete and avoid collision. But definitely don't have strong opinion on this!

UPDATE: I missed the forward slash in @/* 😆 NVM! That should work just fine!

@codemonkey800 codemonkey800 force-pushed the jeremy/frontend-infra branch from f0d2059 to 5486951 Compare April 9, 2021 18:06
@@ -8,7 +8,7 @@ cool frontend tech for the website:
- :art: [SCSS modules](https://github.com/css-modules/css-modules)
- :nail_care: [Tailwind CSS](https://tailwindcss.com/) for utility styles
- :racing_car: [Tailwind JIT](https://tailwindcss.com/docs/just-in-time-mode) for on-demand Tailwind styles
- :package: [pnpm](https://github.com/pnpm/pnpm) for package management
- :package: [Yarn](https://classic.yarnpkg.com/en/) for package management
Copy link
Collaborator Author

@codemonkey800 codemonkey800 Apr 9, 2021

Choose a reason for hiding this comment

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

While I love that pnpm is growing significantly and is up to 2x faster than competitors, it still doesn't have Dependabot support.

Dependabot has support for parsing and updating the yarn.lock file, which is crucial for detecting and fixing security vulnerabilities. When Dependabot gets support for the pnpm-lock.yaml files, we can revisit swapping Yarn for pnpm.

Copy link
Member

@kne42 kne42 left a comment

Choose a reason for hiding this comment

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

I don't really know anything about front-end infra so I just left a few questions/suggestions, feel free to ignore them 😅

client/tailwind.config.js Outdated Show resolved Hide resolved
"noUnusedLocals": true,
"noUnusedParameters": true,
"paths": {
"@/*": ["./src/*"]
Copy link
Member

Choose a reason for hiding this comment

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

is this common practice, or is there a different standardized way of doing this?

@kne42
Copy link
Member

kne42 commented Apr 9, 2021

Oh I guess one other thing, it would be great if you could link out to client/README from somewhere in the main README so that people looking at the repo can figure out how to set it up and stuff!

Copy link

@tihuan tihuan left a comment

Choose a reason for hiding this comment

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

This is really great! Thanks for setting this up, @codemonkey800 🎉 !

Just some minor comments, otherwise LGTM! 🔥 🚀 ✨ 🤩

@@ -0,0 +1,12 @@
{
Copy link

Choose a reason for hiding this comment

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

Ah we probably just need to add .vscode to .gitignore, so we don't commit /.vscode/*!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I actually left this in on purpose to suggest extensions for the project and also enforce that VSCode use the TypeScript version in node_modules. Any particular reasons why we shouldn't include it?

Copy link

Choose a reason for hiding this comment

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

oh that's a great idea!! I didn't think of that 💡

My VSCode adds .vscode/settings.json to the project directory because I use https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock to set different color for different projects, so I just ignored .vscode completely 😆

No other reasons other than that!


export function Layout({ children }: Props) {
return (
<>
Copy link

Choose a reason for hiding this comment

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

nit: <></> doesn't seem needed, since we only have single child here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure thing! This was actually a leftover from the POC that I must have forgotten to change. Will update it!

});

it('should match snapshot', () => {
expect(component).toMatchSnapshot();
Copy link

Choose a reason for hiding this comment

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

should we only capture the fragment for snapshot 😄?

E.g.,

const { asFragment } = component;

expect(asFragment()).toMatchSnapshot();

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Amazing, this shortens the snapshot file considerable. I'm actually new to snapshot testing, so thanks for the tip 🤩

JIT performance benefits .

TODO Remove this code when this issue is resolved:
https://github.com/tailwindlabs/tailwindcss-intellisense/issues/293
Copy link

Choose a reason for hiding this comment

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

Looks like the issue is closed! tailwindlabs/tailwindcss-intellisense#293

Not sure if that's enough though:

This is fixed in v0.5.10 – note that this release does not include full support for the JIT engine. That is coming very soon though! 👀 For now the extension behaves as if you don't have JIT enabled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I love open source, it moves so quickly. I'll take a look and see if this fixes our use case 😆

{
"extends": "./tsconfig.json",
"compilerOptions": {
/*
Copy link

Choose a reason for hiding this comment

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

comment doesn't work in JSON, I remember, so not sure if this will throw a syntax error?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The tsconfig.json file is special because it allows comments for some reason. For example, the sci-components repo includes most of the comments from running tsc --init:

https://github.com/chanzuckerberg/sci-components/blob/0707ce87184e36181cbabeae2a43d1b2c08e0555/tsconfig.json

Copy link

Choose a reason for hiding this comment

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

Ahh TIL! Thanks for sharing! That's really awesome 🔥

"noUnusedLocals": true,
"noUnusedParameters": true,
"paths": {
"@/*": ["./src/*"]
Copy link

@tihuan tihuan Apr 9, 2021

Choose a reason for hiding this comment

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

Ah I think @ is used for scoped packages too, like from '@angular, from "@emotion, from "@material-ui/core/styles", etc.. So that might collide with npm packages as well!

My projects have been straight up using from "src/*" for autocomplete and avoid collision. But definitely don't have strong opinion on this!

UPDATE: I missed the forward slash in @/* 😆 NVM! That should work just fine!

'*.{js,ts,tsx,scss,md,yml,yaml,json}':
- prettier --write
'*.{js,ts,tsx}':
- eslint --fix
Copy link

Choose a reason for hiding this comment

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

Personally on precommit, my projects have been only running prettier and let Github Action run linters on each PR. That way we only need to run linter locally if GH action fails the linter instead of running lint on every local commit!

E.g., https://github.com/chanzuckerberg/khepri/blob/develop/.github/workflows/tests.yml#L17

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That sounds like a great idea now that I think about it. I was planning on having some GitHub actions for linting each PR too. Now that I think about it, we'd be linting every commit AND after the is released PR. So much time spent on linting when it could be done once when it's time for review. Occasionally I also find myself doing git commit --no-verify when doing a quick commit or while rebasing.

Thank you for the suggestion, I went ahead and updated the .lintstagedrc.yml file 😄

@liu-ziyang
Copy link
Contributor

Having no context on the relationship with the edu design system, I want to ask about the reference and how dependent are we on their setup? I totally appreciate that you are able to pull existing resources to our advantage, just want to make sure this wouldn't be a constraint when we need to release the hub to the community

@codemonkey800
Copy link
Collaborator Author

Having no context on the relationship with the edu design system, I want to ask about the reference and how dependent are we on their setup? I totally appreciate that you are able to pull existing resources to our advantage, just want to make sure this wouldn't be a constraint when we need to release the hub to the community

@ziyangczi No dependencies on anyone setup 😄 Everything we've used is all popular open source tooling used by many projects outside of CZI.

@neuromusic
Copy link
Collaborator

Everything we've used is all popular open source tooling

We should also consider getting Snyk setup for this repo. It monitors the repo for security vulnerabilities and license issues. CZI has an account & AFAIK the cellxgene, Meta, and IDseq teams all use it.

@codemonkey800
Copy link
Collaborator Author

Everything we've used is all popular open source tooling

We should also consider getting Snyk setup for this repo. It monitors the repo for security vulnerabilities and license issues. CZI has an account & AFAIK the cellxgene, Meta, and IDseq teams all use it.

@neuromusic Ooh I've seen that around in the source code of other repos while working on this PR. I'd love to add it, but mind if we move forward with merging this PR and adding Synk in another PR?

If yes, should we create a GitHub issue or Clubhouse story to capture that work? 🤔

@neuromusic
Copy link
Collaborator

sorry, yes... didn't intend for that to block this PR

@codemonkey800
Copy link
Collaborator Author

sorry for assuming! 😆

I wasn't sure if it was a request to add it to this PR or not, but thank you for the clarification 💯

"esbenp.prettier-vscode",
"jpoissonnier.vscode-styled-components",
"bradlc.vscode-tailwindcss"
]
Copy link

Choose a reason for hiding this comment

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

unblocker 😆 But highly recommends this spellchecker extension too!

https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I actually had to fix the location of the vscode settings too, so I went ahead and added it to the commit. I also use this extension 💯

@tihuan
Copy link

tihuan commented Apr 12, 2021

Everything we've used is all popular open source tooling

We should also consider getting Snyk setup for this repo. It monitors the repo for security vulnerabilities and license issues. CZI has an account & AFAIK the cellxgene, Meta, and IDseq teams all use it.

For Snyk, I remember some people were saying CZI ended Snyk contract already (or soon?), likely because Github now comes with free Dependabot checks. So definitely check with Infra to see what they recommend!

Copy link
Contributor

@justinelarsen justinelarsen left a comment

Choose a reason for hiding this comment

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

Great work @codemonkey800 ! I don't have much feedback, but overall it looks good to me.

md: '495px',
lg: '600px',
xl: '875px',
'2xl': '1150px',
Copy link
Contributor

Choose a reason for hiding this comment

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

Love this, so organized and clean way of storing the breakpoints! I was wondering why '2xl' and '3xl' are in quotes and the rest aren't?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

JavaScript will start parsing the 2xl and 3xl as numbers because of the leading 2 and 3, so we need to add quotes to make sure they're strings 😆

@codemonkey800 codemonkey800 merged commit 866d40f into chanzuckerberg:main Apr 12, 2021
@codemonkey800 codemonkey800 deleted the jeremy/frontend-infra branch April 12, 2021 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants