Netlify not running yarn preinstall lifecycle hook (monorepo)

I can’t get my package.json preinstall lifecycle hook to run during netlify’s build. It runs fine locally when I do a yarn or yarn install, but does not run in the netlify build environment.

Here’s a minimal test case reproduction: I added this commit to a barebones test-repo: test preinstall · jaredh159/monorepo-test@516a7b0 · GitHub

The hello package just deploys a static index.html file from packages/hello/build/index.html. The preinstall script I wrote adds a line to the end of the file. And I modified the build command so that it cats out the file, as a test of whether it’s working on Netlify. (Also the deployed site would have the added line, but cat-ing it out allows it to be seen in the deploy logs as well).

Here’s the deploy log: Netlify App

And the published site, not showing the PREINSTALL text:

Hey @jaredh159, I don’t see where you call yarn as part of the build process, so it seems like the preinstall script is not getting called. The “build” command in your netlify.toml is to cat out the index.html. Do you want to try adding yarn before the cat? :yarn::smile_cat:

@jen thanks for the response!

I’m not calling yarn because netlify calls yarn for me (instead of npm i when it detects a yarn.lock).

That said, I got some help on this from someone else trying to tackle the same issue (the goal here with the pre-install hook is to improve the unsupported Lerna monorepo node_modules caching to reduce build times), and he pointed out that netlify is calling yarn in the monorepo subdir not the root dir, which I hadn’t thought of. So I think I need to put the preinstall script in the monorepo package’s package.json instead of the root package.json - in case that helps anyone else running into the issue.

I haven’t had a chance to test this yet, but I feel like it’s pretty promising and likely explains my problem.

Would definitely love to see yarn workspaces / lerna monorepo get some more love as a first-class citizen in the Netlify world, if you’re taking feature requests. Really love Netlify, and appreciate all that you guys do, I know you have a lot on your plate though! Thanks!

Hey @jaredh159, that does sound promising! Many thanks for reporting back in case other people come across this post.

And we definitely do have open issues/feature requests for supporting Lerna/Yarn workspaces, as well as improved docs for how our existing monorepo support actually works. I will add this post to those issues :+1:

Just to follow up on this… I didn’t get this working, but I also didn’t try a bunch more because I took a different approach, which ultimately is working well.

My motivation was that I was having really long build times because of poor caching, and was paying for a lot of build minutes. I’ve now switched to building via a github action and then using netlify-cli to push the deploy to netlify, so I build for free on Github and deploy in seconds rather than minutes on netlify.

Maybe that will help someone else struggling with this issue. ¯_(ツ)_/¯

1 Like

@jaredh159 Would you mind sharing the details for the solution you did with github actions? (I’ve never used them) Netlify is just not good enough for this scenario.

We have a monorepo with yarn/lerna/workspace and we build native dependencies that may take a lot of time to compile. We are also losing money and time on build minutes.

@AdoDev sure, although I’ve moved away from the monorepo (tired of fighting lots of little battles with tools and services with incomplete monorepo support) – I still deploy some of my netlify sites (especially the ones with long build times) via a Github action.

I wrote the action myself, and while it’s not publicly listed or advertised, it’s open source and pretty generic. You’re welcome to use it if suits you, here’s a link to the yml file:

You use it in a workflow file like this (providing your own secrets, of course):

- name: deploy
    id: deploy
    uses: friends-library-dev/action-ts-pack/actions/deploy@master
      netlify_api_token: ${{ secrets.NETLIFY_API_TOKEN }}
      site_id: ${{ secrets.NETLIFY_API_SITE_ID }}
      build_dir: your/path/to/build/dir
      functions_dir: your/path/to/functions/dir # optional
      github_token: ${{ github.token }}