NPM Workspaces build a monorepo of multiple websites

Hi,

I’m preparing the field to move from our monolithic websites to a monorepo with npm workspaces.
But I encounter some issue, the monorepo is pretty simple, it’ll contain multiple websites that will shares common data, utilities and some UI components, all websites will be generated with 11ty.

I got it build, but I always got the npm ERR! code ENOWORKSPACES, but it build.
I got it build by adding NPM_FLAGS --location=global.
So next thing I did try was creating a file outside the site folder (utilities folder, sass generator)

But I always got the error cannot find module ‘sass’, I tried directly in utilities/eleventy-sass and as argument in the site folder .eleventy.config, because at first I though utils was outside of the site it will not be accessible, but by argument it should be no?

Everything work on my local machine.
Next thing I’ll try is tu move my script inside .eleventy.config to see if it the problem is from the npm install

Here is an exemple of folder structure that I would like to achieve.

  • Root
    • packages
      • cms (website - 11ty + netlify CMS)
      • sysadminotaur (website - 11ty)
      • website-2 (website - 11ty)
      • website-3 (website - 11ty)
      • ui (ui components)
      • utils (some sripts utilities, like eleventy-sass that I will re-use in every website)

sass is in the package.json of the website folder, so it should be there

Here is my build settings for a website.

Base directory:    packages/sysadminotaur
Build command:     npm run build
Publish directory: packages/sysadminotaur/dist
8:38:22 AM: Build ready to start
8:38:24 AM: build-image version: d7b3dbfb0846505993c9a131894d1858074c90b4 (focal)
8:38:24 AM: build-image tag: v4.10.1
8:38:24 AM: buildbot version: fe6512288e75c8fa5aadaebb51ed1f96e9314fd4
8:38:24 AM: Building without cache
8:38:24 AM: Starting to prepare the repo for build
8:38:24 AM: No cached dependencies found. Cloning fresh repo
8:38:24 AM: git clone https://github.com/michael-proulx/11ty-monorepo
8:38:25 AM: Preparing Git Reference refs/heads/main
8:38:25 AM: Parsing package.json dependencies
8:38:26 AM: Different publish path detected, going to use the one specified in the Netlify configuration file: 'packages/sysadminotaur/dist' versus 'dist' in the Netlify UI
8:38:26 AM: Starting build script
8:38:26 AM: Installing dependencies
8:38:26 AM: Python version set to 2.7
8:38:27 AM: v16.16.0 is already installed.
8:38:27 AM: Now using node v16.16.0 (npm v8.11.0)
8:38:27 AM: Started restoring cached build plugins
8:38:27 AM: Finished restoring cached build plugins
8:38:27 AM: Attempting ruby version 2.7.2, read from environment
8:38:27 AM: Using ruby version 2.7.2
8:38:28 AM: Using PHP version 8.0
8:38:28 AM: npm workspaces detected
8:38:28 AM: Installing NPM modules using NPM version 8.11.0
8:38:28 AM: npm ERR! code ENOWORKSPACES
8:38:28 AM: npm ERR! This command does not support workspaces.
8:38:28 AM: npm ERR! A complete log of this run can be found in:
8:38:28 AM: npm ERR!     /opt/buildhome/.npm/_logs/2022-08-09T12_38_28_769Z-debug-0.log
8:38:29 AM: added 1 package, and audited 3 packages in 84ms
8:38:29 AM: found 0 vulnerabilities
8:38:29 AM: NPM modules installed
8:38:29 AM: Started restoring cached go cache
8:38:29 AM: Finished restoring cached go cache
8:38:29 AM: Installing Go version 1.17 (requested 1.17)
8:38:33 AM: unset GOOS;
8:38:33 AM: unset GOARCH;
8:38:33 AM: export GOROOT='/opt/buildhome/.gimme/versions/go1.17.linux.amd64';
8:38:33 AM: export PATH="/opt/buildhome/.gimme/versions/go1.17.linux.amd64/bin:${PATH}";
8:38:33 AM: go version >&2;
8:38:33 AM: export GIMME_ENV="/opt/buildhome/.gimme/env/go1.17.linux.amd64.env"
8:38:33 AM: go version go1.17 linux/amd64
8:38:33 AM: Installing missing commands
8:38:33 AM: Verify run directory
8:38:34 AM: ​
8:38:34 AM: ────────────────────────────────────────────────────────────────
8:38:34 AM:   Netlify Build                                                 
8:38:34 AM: ────────────────────────────────────────────────────────────────
8:38:34 AM: ​
8:38:34 AM: ❯ Version
8:38:34 AM:   @netlify/build 27.9.1
8:38:34 AM: ​
8:38:34 AM: ❯ Flags
8:38:34 AM:   baseRelDir: true
8:38:34 AM:   buildId: 62f2553eea18ae3dbc082ae5
8:38:34 AM:   deployId: 62f2553eea18ae3dbc082ae7
8:38:34 AM:   systemLogFile: 3
8:38:34 AM: ​
8:38:34 AM: ❯ Current directory
8:38:34 AM:   /opt/build/repo/packages/sysadminotaur
8:38:34 AM: ​
8:38:34 AM: ❯ Config file
8:38:34 AM:   No config file was defined: using default values.
8:38:34 AM: ​
8:38:34 AM: ❯ Context
8:38:34 AM:   production
8:38:34 AM: ​
8:38:34 AM: ────────────────────────────────────────────────────────────────
8:38:34 AM:   1. Build command from Netlify app                             
8:38:34 AM: ────────────────────────────────────────────────────────────────
8:38:34 AM: ​
8:38:34 AM: $ npm run build
8:38:34 AM: > build
8:38:34 AM: > npx @11ty/eleventy
8:38:35 AM: npm WARN exec The following package was not found and will be installed: @11ty/eleventy
8:38:43 AM: [11ty] Eleventy CLI Fatal Error: (more in DEBUG output)
8:38:43 AM: [11ty] 1. Error in your Eleventy config file '/opt/build/repo/packages/sysadminotaur/.eleventy.js'. You may need to run `npm install`. (via EleventyConfigError)
8:38:43 AM: [11ty] 2. Cannot find module 'sass'
8:38:43 AM: [11ty] Require stack:
8:38:43 AM: [11ty] - /opt/build/repo/packages/sysadminotaur/.eleventy.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateConfig.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateRender.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateData.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/Eleventy.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/cmd.js (via Error)
8:38:43 AM: [11ty]
8:38:43 AM: [11ty] Original error stack trace: Error: Cannot find module 'sass'
8:38:43 AM: [11ty] Require stack:
8:38:43 AM: [11ty] - /opt/build/repo/packages/sysadminotaur/.eleventy.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateConfig.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateRender.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/TemplateData.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/src/Eleventy.js
8:38:43 AM: [11ty] - /opt/buildhome/.npm/_npx/34c007b21a377b7f/node_modules/@11ty/eleventy/cmd.js
8:38:43 AM: [11ty]     at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
8:38:43 AM: [11ty]     at Function.Module._load (node:internal/modules/cjs/loader:778:27)
8:38:43 AM: [11ty]     at Module.require (node:internal/modules/cjs/loader:1005:19)
8:38:43 AM: [11ty]     at require (node:internal/modules/cjs/helpers:102:18)
8:38:43 AM: [11ty]     at Object.<anonymous> (/opt/build/repo/packages/sysadminotaur/.eleventy.js:1:14)
8:38:43 AM: [11ty]     at Module._compile (node:internal/modules/cjs/loader:1105:14)
8:38:43 AM: [11ty]     at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
8:38:43 AM: [11ty]     at Module.load (node:internal/modules/cjs/loader:981:32)
8:38:43 AM: [11ty]     at Function.Module._load (node:internal/modules/cjs/loader:822:12)
8:38:43 AM: [11ty]     at Module.require (node:internal/modules/cjs/loader:1005:19)
8:38:43 AM: npm ERR! Lifecycle script `build` failed with error:
8:38:43 AM: npm ERR! Error: command failed
8:38:43 AM: npm ERR!   in workspace: @devolutions/websites-sysadminotaur
8:38:43 AM: npm ERR!   at location: /opt/build/repo/packages/sysadminotaur
8:38:43 AM: ​
8:38:43 AM: ────────────────────────────────────────────────────────────────
8:38:43 AM:   "build.command" failed                                        
8:38:43 AM: ────────────────────────────────────────────────────────────────
8:38:43 AM: ​
8:38:43 AM:   Error message
8:38:43 AM:   Command failed with exit code 1: npm run build (https://ntl.fyi/exit-code-1)
8:38:43 AM: ​
8:38:43 AM:   Error location
8:38:43 AM:   In Build command from Netlify app:
8:38:43 AM:   npm run build
8:38:43 AM: ​
8:38:43 AM:   Resolved config
8:38:43 AM:   build:
8:38:43 AM:     base: /opt/build/repo/packages/sysadminotaur
8:38:43 AM:     command: npm run build
8:38:43 AM:     commandOrigin: ui
8:38:43 AM:     environment:
8:38:43 AM:       - NPM_FLAGS
8:38:43 AM:     publish: /opt/build/repo/packages/sysadminotaur/dist
8:38:43 AM:     publishOrigin: ui
8:38:44 AM: Caching artifacts
8:38:44 AM: Started saving build plugins
8:38:44 AM: Finished saving build plugins
8:38:44 AM: Started saving pip cache
8:38:44 AM: Finished saving pip cache
8:38:44 AM: Started saving emacs cask dependencies
8:38:44 AM: Finished saving emacs cask dependencies
8:38:44 AM: Started saving maven dependencies
8:38:44 AM: Finished saving maven dependencies
8:38:44 AM: Started saving boot dependencies
8:38:44 AM: Finished saving boot dependencies
8:38:44 AM: Started saving rust rustup cache
8:38:44 AM: Finished saving rust rustup cache
8:38:44 AM: Started saving go dependencies
8:38:44 AM: Finished saving go dependencies
8:38:44 AM: Build failed due to a user error: Build script returned non-zero exit code: 2
8:38:44 AM: Creating deploy upload records
8:38:45 AM: Failing build: Failed to build site
8:38:45 AM: Failed during stage 'building site': Build script returned non-zero exit code: 2 (https://ntl.fyi/exit-code-2)
8:38:45 AM: Finished processing build request in 21.088469905s

Netlify site: https://devolutions-sysadminotaur.netlify.app/
Github: GitHub - michael-proulx/11ty-monorepo

The key here is to remove the base directory to start.

Next you’ll want to work with your sites the exact same way you would on your local machine by using npm workspace commands and options.

To build the packages/sysadminotaur site:

Build command

npm run sysadminotaur:build -w @devolutions/websites-sysadminotaur

When building sites or packages that depend on other packages in your workspace, make sure to build the dependencies prior, so the sites can access the correct resolved publish paths.

NOTE: when using workspaces, npm packages are hoisted to the root of the monorepo under node_modules and when you set the base directory to the project path, you are running the build command at a path that cannot see the root of the monorepo.

1 Like

Thank you talves, I did some research and I think that I found my issue, my package-lock is build localy, but here at Devolutions we are using jfrog for our private repository, but by default my npm install is set to jfrog.

By using NPM_FLAGS = --verbose, I got all the 401 fetch from jfrog because it’s not set in netlify.

I’ll give a try by using npm by default.

1 Like

thanks for coming back and sharing your solution, @proulx.mick! This will be beneficial to additional forums members that encounter the same obstacle.

Happy building :rocket:

Thank you all, by setting my .npmrc to npm registry it fixed my package-lock.json

...
registry = https://registry.npmjs.com

I tried my build settings, but it didn’t work.

base directory:    packages/sysadminotaur
build command:     npm run build
publish directory: packages/sysadminotaur/dist

So I switch to talves solution and it works perfectly

base directory:    Not set
build command:     npm run build -w @devolutions/websites-sysadminotaur
publish directory: packages/sysadminotaur/dist
1 Like

Glad the solution worked for you. :grin:

1 Like