What does HackerNews think of wireit?

Wireit upgrades your npm/pnpm/yarn scripts to make them smarter and more efficient.

Language: TypeScript

npm workspaces plus Wireit works far better than Lerna, in my experience.

https://github.com/google/wireit

Wireit's ability to specify actual script dependencies, do caching (and on Github actions), and its long-running service script support make it much more useful and comprehensive than Lerna.

I agree that this should be built into npm. There's an RRFC for it here: https://github.com/npm/rfcs/issues/706

I must admit I'm a bigger fan of the wireit[0] approach, the only pause I have is its a Google project, my temptation is to fork it. The code isn't terribly complex

My biggest complaint with NX is: lack of a sane API for plugins, and it has more overhead than I'd care for. For the amount of complexity that NX has, I'd rather use Rush[1] which gives you everything NX does. My only complaint with Rush is that its development is really slow going, they really need to focus up on Rush plugins (they're good, but still experimental, and I'd love to see them clean up how `autoinstalls` work to be more intutive)

I'm on the fence about turbo from Vercel

[0]: https://github.com/google/wireit

[1]: https://rushjs.io/

I really like https://github.com/google/wireit/ for this purpose!

My monorepo looks like this:

    project-1/packages/core
    project-1/packages/preact
    project-2/packages/core
    project-2/packages/demos
    etc.
where a bunch of related projects live top-level in a repo. Each project has a packages folder that includes the core implementation, as well as demos, framework-specific adaptors, etc.

In each package's package.json, I have a series of commands (convert the TS to JS, make a bundle, deploy to Firebase, etc.). Each command can depend on another, either in the same project or anywhere else in the file hierarchy.

This provides two benefits:

1. Iterating across packages is faster, because I don't have to worry about making sure each package rebuilds in the right order if I make a change in a library.

2. Filesystem concerns are separated: rollup only needs to worry about bundling, and it only needs to bundle web-facing projects. The only tool my libraries need is tsc.

(Before wireit, using TypeScript and Rollup together was a pain in the ass because you'd have to fiddle with picking the right TS plugin and configuring it. This was also often the long pole on doing a Rollup version upgrade. Decoupling the two makes Rollup way simpler/easier/nicer to use, which makes wireit awesome even if you don't have multiple packages.)

It's also a good replacement for lerna. Each of my packages has a publish command that runs `gitpkg publish`. My root package.json has a publish command that depends on all the packages' publish commands. Thus, I can run `yarn run publish` in the root of my monorepo and trust that all of my packages have been published to our git host appropriately. (gitpkg lets you turn a git host into a private registry, so you can share modules without setting up an NPM registry.)

Here's a snippet from one of my package.jsons. They basically all look like this. (start is complicated because of https://github.com/google/wireit/issues/33. When that's resolved, it will be as simple as the others.)

    "scripts": {
      "start": "yarn run -TB concurrently \"yarn run build:tsc --watch\" \"rollup --config ./rollup.config.js --watch\" \"dhost site --bind-all\"",
      "build": "yarn run -TB wireit",
      "build:tsc": "yarn run -TB wireit",
      "build:bundle": "yarn run -TB wireit",
      "deploy": "yarn run -TB wireit"
    },
    "wireit": {
      "build": {
        "dependencies": [
          "build:tsc",
          "build:bundle"
        ]
      },
      "build:tsc": {
        "command": "tsc --build --pretty",
        "clean": "if-file-deleted",
        "files": [
          "src/**/*.{ts,tsx}",
          "tsconfig.json",
          "../../tsconfig.common.json"
        ],
        "output": [
          "dist/**",
          ".tsbuildinfo"
        ],
        "packageLocks": [
          "yarn.lock"
        ],
        "dependencies": [
          "../core:build",
          "../preact:build"
        ]
      },
      "build:bundle": {
        "command": "rollup --config ./rollup.config.js",
        "clean": true,
        "files": [
          "dist/**/*.js",
          "rollup.config.js"
        ],
        "output": [
          "site/mount.js",
          ".tsbuildinfo"
        ],
        "packageLocks": [
          "yarn.lock"
        ],
        "dependencies": [
          "build:tsc"
        ]
      },
      "deploy": {
        "command": "firebase deploy",
        "dependencies": [
          "build:bundle"
        ]
      }
    },
In the past, I'd put a "typescript:main" field in package.json and configured my bundler to prefer that field. I gave up at some point - probably when I migrated to rollup.

Moving forward, I'm going to use wireit for these things. Pure modules get built with tsc. At the highest level (e.g. where it needs to be embedded in a page), make a bundle with rollup.

wireit has two nice properties: incremental building and file-system-level dependencies. Within a repo, you can depend on ../package-b. However, if you have multiple monorepos that often get used together, you can also depend on ../../other-project/packages/package-b. No matter where in your tree you make changes, wireit knows when to make a new bundle.

I've just started with wireit (it was only launched recently), but it seems to be a nice solution to wrangling dependencies between related JS libraries.

[1] https://github.com/google/wireit