Vercel: Yarn workspaces

Created on 19 Oct 2017  路  30Comments  路  Source: vercel/vercel

Does now work with yarn workspaces? If so, what's the correct setup?

Most helpful comment

Okay, I think I know how I'd want/expect this to work.

Let's say I have a monorepo with multiple microservices that structured as a yarn workspace:

root/
  package.json   # Shared dependencies here
  yarn.lock      # Shared lock file
  now.json       # Shared now config
  server1/
    package.json # server1 specific deps here
  server2/
    package.json # server2 specific deps here
    now.json     # server2 specific now configuration
    yarn.lock    # Duplicate deps that don't match the root version are in this optional lock file

Now from the root folder I start deploying server2:

now deploy server2/

Here is what now-cli should do in this case:

  1. Detect that server2/ is a workspace in a monorepo by checking if there's a "workspaces" field in the package.json
  2. Merge the package.json and yarn.lock from the root folder with the ones in the server2/ folder locally (maybe we can directly use the same merging algorithm yarn uses somehow?)
  3. Merge the now.json configuration files, letting the more specific server2/now.json override the root one
  4. Upload the server2/ folder with the merged files
  5. Build and run as usual :tada:

Am I making sense?

Note: This should also work if you're deploying from inside the server2 folder, so now-cli would move up a level and check if the parent folder has the workspaces key in its package.json and that the current folder is a workspace.

All 30 comments

@TooTallNate Do Yarn workspaces require some sort of change on the platform end?

I'm struggling with this right now, the biggest trouble is that when you're deploying a workspace the dependencies of the root package.json aren't included:

root/
  package.json # Shared dependencies here
  workspace1/
    package.json # workspace1 specific deps here
  workspace2/
    package.json # workspace2 specific deps here
now deploy workspace1/

# Build error: Cannot find dependency "shared-dependency"

This also means that when deploying workspace1 I don't have a yarn.lock in that folder, (that's the way workspaces work) so Zeit uses npm instead of yarn which means I get errors because I use package aliases. Ref #938

It'd be great if yarn workspaces were detected and yarn used.

Okay, I think I know how I'd want/expect this to work.

Let's say I have a monorepo with multiple microservices that structured as a yarn workspace:

root/
  package.json   # Shared dependencies here
  yarn.lock      # Shared lock file
  now.json       # Shared now config
  server1/
    package.json # server1 specific deps here
  server2/
    package.json # server2 specific deps here
    now.json     # server2 specific now configuration
    yarn.lock    # Duplicate deps that don't match the root version are in this optional lock file

Now from the root folder I start deploying server2:

now deploy server2/

Here is what now-cli should do in this case:

  1. Detect that server2/ is a workspace in a monorepo by checking if there's a "workspaces" field in the package.json
  2. Merge the package.json and yarn.lock from the root folder with the ones in the server2/ folder locally (maybe we can directly use the same merging algorithm yarn uses somehow?)
  3. Merge the now.json configuration files, letting the more specific server2/now.json override the root one
  4. Upload the server2/ folder with the merged files
  5. Build and run as usual :tada:

Am I making sense?

Note: This should also work if you're deploying from inside the server2 folder, so now-cli would move up a level and check if the parent folder has the workspaces key in its package.json and that the current folder is a workspace.

This should probably also work if you're deploying from inside the server1 folder, so now-cli would move up a level and check if the parent folder has the workspaces key in its package.json and that the current folder is a workspace.

It would potentially need to move up more than one level (until it reaches the root or a package.json with a workspaces key).

Anyway, I would love to know if now-cli plans to support workspaces. It would make managing microservices so much easier if we could use a monorepo format!

@Qix- @TooTallNate any hints as to whether this will be tackled sometime? It's fine if not, I'd just love to know :blush:

I'm going to have a go here as I need this for some mono-repo work we're doing.
Maybe some of the work at #3319 might help as well.

One of the yarn maintainers wrote on Twitter:

Yarn exposes some of its algorithms as packages, so everything is possible if you send a PR. You should definitely be able to reuse the root yarn.lock in a workspace in isolation, the extra resolutions will be ignored

Sounds good?

@mxstbr I really like your proposal of how this should be implemented

Hi guys I have the same problem while deploying apps with shared dependencies.
I am getting: Error! The build step of your project failed. To retry, runnow --force`.

I thought a following workaround could help:

  1. build app localy
  2. deploy build folder

But for some reasons, it always tries to either install or build the project even I leave the build step empty.

I've prepared a test repo for it: https://github.com/tomaswitek/next-workspaces.
I discussed it yesterday with @sergiodxa on a slack.
I tried everything @sergiodxa suggested without a success.
Can somebody help me pls?
Here is our whole conversation:

Tom Witek [11:57 PM]
Hi guys, is there a way how to build next app locally and just upload it to now?


sergiodxa [11:59 PM]
yes, just upload the ,next file and don't ignore it in your .gitignore or .npmignore (edited)

Tom Witek [12:01 AM]
@sergiodxa `now .next` ?
https://next-ssqxhaqfku.now.sh/

sergiodxa [12:01 AM]
no, upload your app code with the .next directory
you need the package.json
and any custom server code

Tom Witek [12:02 AM]
aaaaah ok
thx @sergiodxa
I guess also now.json should be included :wink:

sergiodxa [12:04 AM]
yes

Tom Witek [12:04 AM]
The original problem was that I have linked npm dependencies which can鈥檛 be buit on the server directlly, so I thought I鈥檒l build it locally and then just deplo it

sergiodxa [12:04 AM]
you need to upload everything + the .next folder
and don't have a build script or define an empty now-build directory

Tom Witek [12:12 AM]
@sergiodxa it stopped on ` Initializing鈥

sergiodxa [12:12 AM]
if you access the deployment URL with `/_logs` do you see logs?
did you got a deployment URL?

Tom Witek [12:14 AM]
no I didn't
I guess it gets stuck on installing npm modules

sergiodxa [12:16 AM]
:thinking_face: change the dependencies you can only install locally to devDependencies
and deploy with `NODE_ENV` as `production` on now.json or with `-e NODE_ENV=production`

Tom Witek [12:18 AM]
good idea let me try
OK man I give up, it鈥檚 still throwing errors on me and it鈥檚 too late. Anyway thank you for your help!!! (edited)
good night

Is there someone working on this?
If not, I can try...

@chabou yes please! I don't think anybody's working on this :pray:

@mxstbr I have a few questions to:

聽Merge the package.json and yarn.lock from the root folder with the ones in the server2/ folder locally (maybe we can directly use the same merging algorithm yarn uses somehow?)

1) There should be just one yarn.lock file. So there is no merging needed for this file right? We just need it for deployment.
2) Do you specify some dependencies in root package.json? Or what is the exact reason for merging package.json files?

@chabou is there already some branch open? Can I help?

I'd like to help if you need, so we can ship this :) @chabou

I use something like this until better support for workspaces is added:

"scripts": {
  "deploy": "yes | cp ../../yarn.lock . && now -e NODE_ENV=production && now alias"
}

And add this copied yarn.lock to .gitignore.

@rauchg should this work with now v2? I tried but now tries to upload the whole monorepo instead of what I specified in the now.json:

{
  "name": "myapp",
  "alias": ["myapp.com", "www.myapp.com"],
  "builds": [
    { "src": "packages/web/build/index.html", "use": "@now/static" },
    { "src": "packages/server/index.js", "use": "@now/node" }
  ],
  "public": false,
  "scale": {
    "gru1": {
      "min": 1,
      "max": "auto"
    }
  },
  "version": 2
}
  • scale is no longer necessary. Just regions
  • public: false is always the default now
  • I recommend building in the cloud instead of ahead of time. Look into @now/static-build
  • For the server, you probably want @now/node-server. But most importantly, you probably want to break it down into smaller entrypoints instead, which is the recommended way (@now/node)

@rauchg Thanks.

Sorry I was not clear at my issue description, but I just managed to make it work :)

Details below for reference.


It's a yarn workspace project. I have the following files:

- now.json
- packages
  - server
    - index.js

now.json

{
  "name": "myapp",
  "builds": [{ "src": "packages/server/index.js", "use": "@now/node" }],
  "routes": [
    { "src": "/(.*)", "dest": "/packages/server/$1" }
  ],
  "regions": ["gru1"],
  "version": 2
}

packages/server/index.js

module.exports = (req, res) => {
  res.end('It works!')
}

This worked great. It uploaded around 500b of files and showed It works! in the browser.

But my real project actually had more packages inside the monorepo, like the mobile one:

 - now.json
 - packages
   - server
     - index.js
+  - mobile
+    - android (huge folder)
+    - ios (huge folder)
+   - ...

When I ran the same now command with the same now.json:

Expected: Keep working as before. Upload 500b of files.
Behavior: it tried to upload hundreds of files and broke with File size limit exceeded (5 MB). It probably included the mobile folder, but that was not intended.

Adding packages/mobile to .nowignore solved it.

I also have a web project that uses create-react-app:

 - now.json
 - packages
   - server
     - index.js
  - mobile
    - android (huge folder)
    - ios (huge folder)
   - ...
+  - web
+    - dist
+    - src

Here's my final now.json that is working:

{
  "name": "myapp",
  "alias": "myapp.com",
  "builds": [
    { "src": "packages/web/dist/**", "use": "@now/static" },
    { "src": "packages/server/index.js", "use": "@now/node" }
  ],
  "routes": [
    { "src": "/api", "dest": "/packages/server/" },
    { "src": "/(.*)", "dest": "/packages/web/dist/$1" }
  ],
  "regions": ["gru1"],
  "version": 2
}

PS: /api is just for test purposes, I'll use small entry points later.

The only pending issue is that it only worked with @now/static. When trying @now/static-build I got build errors like Couldn't find the binary git, which may be related to this issue here (because of hoisted node modules due to yarn workspaces).

As you can see above, this works as of Now 2.0!

02/04 07:24 AM (1m) info No lockfile found.

@leo it's clearly not working?

@igl it's working for me, I have one yarn.lock file in the root of my project and no lock files in any of the workspaces.

@tim-phillips can you share a snippet of your now.json?

@igl Sorry, I鈥檝e only done this in a private project and I can鈥檛 share anything from that. You might want to make a simplified repo that reproduces this issue and post it to https://spectrum.chat/zeit/now

Here's a public repo, a barebones project for the moment: https://github.com/fillipvt/portfolio

It has yarn workspaces with 2 NextJS apps and 1 GraphQL implementation. The most recent push to production did work.

alright i will have to investigate the "No lockfile found" happening in my project.

How is this suppose to work with a multi app - monorepo? You'll get 1 project in Now, with 1 config at the root? We have a setup kinda like this:

root/
   apps/
      app-1/
          next.config.js
      app-2/
          next.config.js
    packages/
        internal-package/

@fillipvt question for you... why do you need to treat shared-components as an actual BUILT npm package?

doesn't transpileModules: ['@fillipvt/components'], take care of doing all the "building" of that shared package when you run next?

Also have the same issue with @maraisr. Our set-up is like this

root/
  apps/
    api/ <-- not deployed to now
    client/ <-- serverless app deployed to now
      next.config.js
  libs/
    shared_stuff/

The issue is that the libs/ is not included in the files sync to now so they are missing during the build process.

  1. Tried moving just the now.json to the root but not enough
{
  "version": 2,
  "routes": [
    {
      "src": "^/service-worker.js$",
      "dest": "/_next/static/service-worker.js",
      "headers": {
        "cache-control": "public, max-age=43200, immutable",
        "Service-Worker-Allowed": "/"
      }
    }
  ],
  "builds": [
    {
      "src": "apps/client/next.config.js",
      "use": "@now/next"
    }
  ]
}

Running now results to a success but the deployed app is a directory listing and navigating to apps/client/ will open a site but the CSS paths are not working.

  1. Tried adding a "now-build": "next build apps/client" with a root/now.json

Still no

  1. Tried adding a "now-build": "next build" instead

Still no

  1. Tried moving next.config.js to root folder.

Doesn't work too


Ended up moving the shared folders to the client folder so they can by synced to now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

morgs32 picture morgs32  路  29Comments

CaptainChemist picture CaptainChemist  路  40Comments

ghost picture ghost  路  28Comments

kertof picture kertof  路  107Comments

SteveALee picture SteveALee  路  51Comments