blues-stack icon indicating copy to clipboard operation
blues-stack copied to clipboard

chore: add nx to the repo

Open vsavkin opened this issue 3 years ago • 7 comments
trafficstars

This PR is a follow-up of my conversation with Kent.

This PR shows how to add Nx to this repo, make some operations faster, and improve some dev ergonomics.

  1. Everything but "npm run dev" is cacheable now, so if you run "npm run build" twice, the second time will always be free.
  2. "npm run dev"'s output is nicer (see the video below).
  3. This PR enables Nx Cloud, which provides distributed caching and nicer UI for the invoked commands (see the video below). This is optional. Nx Cloud GitHub app can be enabled to post a comment to every PR with the links to the commands the PR ran.

Watch this video to see how everything works now: LINK

I intentionally didn't change anything about the repo itself to make it less overwhelming. So I want to mention that this isn't the best way to use Nx (or any such tool really). For instance, cypress and prisma can be made separate from app, which would make the dev ergonomics nicer etc.

This repo is also small, so both DX and performance advantages Nx offers aren't really that important here. The build command is fast enough without caching and distribution, and the output of say "validate" is understandable without the niceties Nx and Nx Cloud offer. It would have been easier to show the before and after if, say, all the stacks were in the same repo.

vsavkin avatar May 04 '22 14:05 vsavkin

Even though you say this doesn't really suite the best use case scenario for the blues stack, I'm already really impressed. I think this is very cool. It's not that we need Nx to help with development of the stack. What we're doing here is making it so when people generate a Remix stack the output is a project pre-configured with Nx so people building their remix app have the best possible experience with the CLI during development. So Nx isn't for us developing the template, it's for everyone else using the template. I think this is a nice step up!

kentcdodds avatar May 04 '22 14:05 kentcdodds

Made the changes:

  1. Remove all nx-cloud related stuff, remove unused npm dep.

  2. On "name": "blues-stack"

Nx most of the time is used for managing repos with multiple projects in them. There is no restriction on what that name is. You change the name to any value. You just need to make sure to change the following in nx.json to the same value:

  "cli": {
    "defaultProjectName": "blues-stack"
  },
  1. I want to mention that I marked pretty much everything (except dev) cacheable. Caching is cool etc, but you don't have to use it if you only care about process orchestration and the terminal output. If that's the case the cacheableOperations in nx.json can be removed, and the nx section in package.json can be reduced to this:
    "targets": {
      "test:e2e:run": { "dependsOn": [ "build-all" ] },
      "test:e2e:dev": { "dependsOn": [ "build-all" ] }
    }

vsavkin avatar May 06 '22 19:05 vsavkin

This is looking good. I've updated things a bit to make the name that shows up in the output be what they called their app. One issue I bumped into is I did the following:

  1. Run npm run build
  2. Change server.ts
  3. Run npm run build

And I noticed that it didn't rebuild the server.ts file. It said it could use the cache. In looking at the config it looks like we only show where the output files go, but we don't say anything about the input files. How does nx know that it can trust the cache without knowing which input files there are? In this case, it's wrong 😬

kentcdodds avatar May 09 '22 22:05 kentcdodds

@vsavkin could you bring this PR up to date and go through the remarks? Thank you 🙏🏼

machour avatar Jun 08 '22 21:06 machour

@vsavkin Could you please rebase on latest main & resolve conflicts + conversations?

MichaelDeBoey avatar Aug 25 '22 18:08 MichaelDeBoey

Here's a sample remix.config.js I'm using to define routes in each Nx lib project under libs/example-feature/src/lib/routes/ instead of defining all routes in apps/remix-app/app/routes. It also uses watchPaths to only watch referenced libs for file changes rather than everything in the monorepo.

It's not thoroughly tested yet but maybe others using Nx will find it useful. You could consider adding the watchPaths example to this PR.

For the below to work you will need to patch out the code in emptyModulesPlugin that limits it to working on files under /app. https://github.com/remix-run/remix/blob/fd00bc657ef7f2b55c53e5f9dbd77185fa7d5734/packages/remix-dev/compiler/plugins/emptyModulesPlugin.ts#L20

const { createGlobPatternsForDependencies } = require("@nrwl/react/tailwind");
const { defineConventionalRoutes } = require("@remix-run/dev/dist/config/routesConvention");
const path = require("path");
const fs = require("fs");

/**
 * @type {import('@remix-run/dev').AppConfig}
 */
module.exports = {
  // ignore all files in routes folder
  ignoredRouteFiles: ["**/.*"],
  // add routes for all referenced lib projects
  routes: defineLibraryRoutes,
  // watch referenced libs for file changes during dev
  watchPaths: () => createGlobPatternsForDependencies(__dirname, "/**"),
};

async function defineLibraryRoutes() {
  let routeManifest;
  const appFolder = path.join(__dirname, "app");

  const libDirectories = createGlobPatternsForDependencies(__dirname, "/lib/");
  for (const dir of libDirectories) {
    // check if referenced library has routes defined
    const routesFolder = path.join(dir, "routes");
    if (!fs.existsSync(routesFolder)) continue;

    // get all routes from library based on default conventions
    let manifest = defineConventionalRoutes(dir, ["**/*.test.{js,jsx,ts,tsx}"]);

    // convert route file paths to be relative to app directory
    for (const [, route] of Object.entries(manifest)) {
      const routeFile = path.join(dir, route.file);
      route.file = path.relative(appFolder, routeFile);
    }

    routeManifest = { ...routeManifest, ...manifest };
  }

  return routeManifest;
}

jrestall avatar Sep 12 '22 03:09 jrestall