The issue arises when I execute npm run dev; it doesn’t behave the same as running source setup-env.sh && npm run build directly in the terminal. The npm script initiates a subshell, preventing me from altering the parent shell environment or exporting variables.
Key Concerns
I need to change the Node.js version with nvm through the sourced script. Because npm creates a subshell, the state of nvm isn’t retained. This leads to the version switch happening every time I execute the command, causing a delay of around 3-4 seconds.
Desired Outcome
Is there a method to execute npm scripts without the creation of a subshell, allowing the sourced script to adjust the current shell environment? I want the nvm version change to be set once and maintained, not repeated with each command execution.
I understand I could run the source command manually before npm start, but I’m looking for a solution that automates this within the npm script.
The problem is npm runs scripts in subshells, so you can’t change the parent shell’s environment. But there are workarounds. Put a .nvmrc file in your project root with the Node version you want, then create a shell alias that sources your environment script and runs npm commands together. Or use direnv - it automatically loads environment variables when you cd into a directory. I’ve found this cuts out the constant nvm switching since the environment gets set once per terminal session instead of every time npm runs.
Yes, npm scripts spawn subshells, which limits their ability to modify the parent shell environment. I faced similar issues with nvm and found a workaround. Instead of sourcing your setup script directly in the npm command, create a wrapper script that combines both the environment setup and the npm execution. For example, you could create a script named run-dev.sh that sources setup-env.sh before calling npm run build. By running this script in your terminal session, you maintain the nvm changes, achieving automation while avoiding subshell limitations.
Try using exec in your npm script instead of running commands normally. Something like "dev": "exec bash -c 'source setup-env.sh && npm run build'" might work better since exec replaces the current process instead of spawning a subshell. Worth testing!