Npm dependencies not installing when using base directory

I’m trying to deploy multiple sites from an Nx monorepo that has one package.json at the root. The problem is that setting a base directory for each site is causing Netlify to skip installing the npm dependencies, causing the builds to fail.

I’ve set up an isolated reproduction of the issue at https://github.com/lourd/nx-test, connected to the sites musing-react-e41a45 and agitated-next-e512a6. The repo has a Next.js app at apps/my-next-app and a client-rendered React app at apps/my-react-app. Each of those directories has a netlify.toml in them. In the Netlify UI, each site has their base directory set to their respective directory in apps.

Here’s a link to a failing build of the Next.js app, and a link to a failing build of the React app. They both fail with an error related to the fact that no npm dependencies are being installed during the build process.

I tried working around this by 1. adding yarn install to the build command, and 2. calling yarn install as part of the onPreBuild event in a custom build plugin. Those workarounds worked for the React app, but not for the Next.js app. That’s because the Next.js app also uses the @netlify/plugin-nextjs build plugin, and it tries to install the plugin before running any of the build plugins, regardless of the order they’re listed in the config file. This causes a Dependencies installation error error:

npm ERR! notarget No matching version found for @netlify/plugin-nextjs@4.`
Here's the Next.js app's netlify.toml:
[build]
  publish = "../../dist/apps/my-next-app/.next"
  command = "nx build my-next-app"
  [build.environment]
    PROJECT_NAME = "my-next-app"
    NETLIFY_USE_YARN = "true"

[[plugins]]
  package = "../../tools/netlify-plugins/force-install"

[[plugins]]
  package = "../../tools/netlify-plugins/only-build-when-affected"

[[plugins]]
  package = "@netlify/plugin-nextjs"

I tried to reproduce the issue locally using the Netlify CLI/dev environment, but the builds succeed when doing that :confused:.

Thanks in advance for your help!

I also tried installing the Next.js build plugin through the Netlify UI, leaving it out of the netlify.toml. Then the build fails with this error:

10:44:37 AM: ❯ Loading plugins
10:44:37 AM:    - @netlify/plugin-nextjs@3.9.2 from Netlify app
10:44:37 AM:    - ../../tools/netlify-plugins/force-install@0.0.0 from netlify.toml
10:44:37 AM:    - ../../tools/netlify-plugins/only-build-when-affected@0.0.0 from netlify.toml
10:44:37 AM: ​
10:44:37 AM: ────────────────────────────────────────────────────────────────
10:44:37 AM:   1. @netlify/plugin-nextjs (onPreBuild event)                  
10:44:37 AM: ────────────────────────────────────────────────────────────────
10:44:37 AM: ​
10:44:37 AM: ​
10:44:37 AM: ────────────────────────────────────────────────────────────────
10:44:37 AM:   Plugin "@netlify/plugin-nextjs" failed                        
10:44:37 AM: ────────────────────────────────────────────────────────────────
10:44:37 AM: ​
10:44:37 AM:   Error message
10:44:37 AM:   Error: This site does not seem to be using Next.js. Please run "npm install next" in the repository.
10:44:37 AM:   If you are using a monorepo, please see the docs on configuring your site: https://ntl.fyi/next-monorepos
10:44:37 AM: ​
10:44:37 AM:   Plugin details
10:44:37 AM:   Package:        @netlify/plugin-nextjs
10:44:37 AM:   Version:        3.9.2
10:44:37 AM:   Repository:     git+https://github.com/netlify/netlify-plugin-nextjs.git
10:44:37 AM:   npm link:       https://www.npmjs.com/package/@netlify/plugin-nextjs
10:44:37 AM:   Report issues:  https://github.com/netlify/netlify-plugin-nextjs/issues
10:44:37 AM: ​
10:44:37 AM:   Error location
10:44:37 AM:   In "onPreBuild" event in "@netlify/plugin-nextjs" from Netlify app
10:44:37 AM:       at validateNextUsage (/.netlify/plugins/node_modules/@netlify/plugin-nextjs/helpers/validateNextUsage.js:15:12)
10:44:37 AM:       at onPreBuild (/.netlify/plugins/node_modules/@netlify/plugin-nextjs/index.js:32:5)

Hi @Lou

The reason for this is there is no package.json in the directory you are building from as demonstrated in the Monorepo documentation so npm has no idea what dependencies are required to build the project.

Hey @coelmay, thanks for the answer.

npm has no idea what dependencies are required to build the project

The typical behavior for running npm install or yarn install from a subdirectory without a package.json is to walk up the tree until it does find a package.json and install the dependencies listed there. Netlify is somehow changing that behavior.

The Netlify Monorepo documentation does not have guidance for building multiple sites when you only have one package.json. It does say this:

Although it’s possible to declare dependencies at the root, we recommend a setup where you define all dependencies at a more specific, subdirectory level.

But it seems like using Yarn workspaces/defining a package.json per site is effectively a requirement. Is that right?

In my testing of yarn workspaces, all dependencies for a specific app are in the package.json for that app, with the only thing in the root package.json the workspaces setup. Building with yarn from the project root (as opposed to app root) you can then use yarn --cwd <path> <yarn command> and set the publish directory accordingly.

Sorry if I miscommunicated — I’m not currently using yarn workspaces and wasn’t trying to. I’m using Nx with a single package.json at the root of my repo. Do I have to use yarn workspaces for deploying multiple sites from one repo, or can I have one root package.json and deploy multiple sites?

Apologies, I wasn’t suggesting you needed to use yarn workspaces, was merely using that as an example.

It appears this is how Nx works, based on https://nx.dev/l/r/core-concepts/why-monorepos, and Nx and Lerna | Nx.

I’m not familiar with Nx, so cannot offer specific advise regarding it’s usage (reading and regurgitating documentation without testing it first isn’t going to help you in this instance.)

Thanks for trying to help.

Yes, one package.json in the root and multiple sites is how Nx is typically set up. The issue I’m having isn’t with Nx, it’s with Netlify build not installing the dependencies from that file because the base is set to a subdirectory. This is confusing because the normal behavior for npm and yarn is to install dependencies from the closest parent directory with a package.json file.

Rather than setting a base directory and running npm run build (for example) you might try leaving the base directory empty and setting the build command to (for example)

cd path/to/app && npm run build

and setting the publish directory to path/to/app/BUILD there BUILD is the name of the output directory (e.g build, or dist.)

1 Like

That kind of works! The dependencies do get installed, then, and the builds succeed. It does preclude me from being able to have site-specific netlify.toml files, though, since each site has the same base directory.
I might be able to workaround that by using _redirects and _headers files copied to the output directory as part of a site’s build process, but I’m not sure about the rest of the netlify.toml options.

I don’t believe there is workaround for the netlify.toml options you have such as plugins with this way of building (happy to stand corrected; nice to know it was at least a partial success.) Without testing it is hard to say for certain, but it would appear that in the current form building won’t work, and you will need to have a package.json per app just as you have individual netlify.toml files.

You might (if you haven’t already) find help via the Nx community as someone may have encountered similar issues before.

1 Like

I don’t think that’s true. From what I know. that’s true for module resolution. For example, if a module is not found in cwd, then Node will keep going to the root of the file system till it finds the module. I don’t think that’s the same behaviour with package.json, but I’d happy to be corrected about this.

About your actual problem, I can see multiple workarounds, though I won’t recommend them. The best way would still be to create multiple package.json in the entire repo.

So here’s what you can do. Set the base path to your sub-folder. Netlify will not install dependencies. Then when you actually start the build, either:

  1. cp ../package.json ./package.json && npm i && npm run build OR
  2. cd ../ && npm i && cd ./sub-folder/ && npm run build

Basically, you will have to change your command to manually install your packages. So you can either do that by copying your package.json to your cwd or cd into the parent directory, install packages, cd back into your project directory and run the build.

The reason why I won’t recommend this workflow is because, this way node_modules directory probably won’t be cached by the build system and thus, builds might take longer.