How to execute nested "npm run commands" inside an npm#^7.0.0 monorepo set up within the context of the current workspace? - npm

I have a monorepo with several workspaces within it. It has been very common for me to use chained npm scripts for simple tasks instead of using a task runner. So for example, the following configuration (pseudo code) is very common for me and usefull as well, specially for pre and post build scripts
"scripts": {
"prebuild:task1":"task1 --task1-arguments",
"prebuild:task2":"task2 --task2-arguments",
"prebuild": "npm run prebuild:task1 && npm run prebuild:task2",
"build":"build-script --build-arguments",
}
So the above is the package.json for the child worskpace itself and then in the master package.json I have the call to the script that triggers the build for that workspace.
build:packageA: "npm run build -w packageA"
All seems working well but the chained "npm run script" inside the workspace is actually execute in the context of the master monorepo and not inside that particular workspace.
So, in summary, the first call is to run the build script in the workscape and then triggers the prebuild script of that workspace BUT as that script execute chained npm run scripts those are run in the context of the master repo which happens that they don't exist in there. So the callstack might be ...
(master) build:packageA
(packageA) prebuild
(master) npm run prebuild:task1 >>>> EXIT ERROR
The only way I found, up to now, to bypass this issue was to make my child workspace a monorepo itself holding zero woskpaces. Essentially I have a "workspaces" key in its package.json pointing to the root directory. This enables me to use the -w flag in the scripts section so to refer all scripts to itself. So my current workaround looks like this ...
"workspaces": ["."],
"scripts": {
"prebuild:task1":"task1 --task1-arguments",
"prebuild:task2":"task2 --task2-arguments",
"prebuild": "npm run prebuild:task1 -w packageA && npm run prebuild:task2 -w packageA",
"build":"build-script --build-arguments -w packageA"
}
Isn't there already a better way to solve this?
Thanks in advance to everyone!

Following this post https://stackoverflow.com/a/67060676 I found out that npm changed the way it calls nested scripts in workspaces.
I ran into similar issues like you while running npm#7.5, but the feature was introduced in npm#7.7. Updating node to v17 and npm to 8.3 resulted in everything is running as intended.
In my case I wanted to execute nested npm run build commands in workspaces.

Related

Why does package.json script behave differently than identical terminal command

In my npm project, in my package.json file, I have the following lines of code:
"scripts": {
"build": "webpack"
},
While in my terminal, if I run npm webpack, I get the error message:
Unknown command: "webpack"
But if I run npm run build, I get a prompt from webpack saying I need webpack-cli... so the command is obviously recognized.
I'm confused about the different behavior of these two commands. In this case, isn't running npm run build identical to running npm webpack in my terminal? Why does one command fail and one succeed? What is actually happening when I run npm run build?
If we look at the documentation,
Environment
Package scripts run in an environment where many pieces of information are made available regarding the setup of npm and the current state of the process.
path
If you depend on modules that define executable scripts, like test suites, then those executables will be added to the PATH for executing the scripts.
Maybe this is the reason webpack is not recognized by the command line.

is it possible to do tasks using npm-scripts only without task runner?

I am new to npm run scripts can I do the following tasks using only npm run scripts? (i.e without any task runner like gulp and grunt)
concat js
scss to css watch
get notified about succesful js concatenation and scss to css conversion
and moving only html, css, js to deployment directory
Any help would be greatly appreciated!
I don't see why not? To give you a little context:
npm run scripts allow you to easily run: any custom script you create, or any script provided from within your node_modules directory. This is exactly what any task runner is providing you with: i.e. custom scripts to accomplish common development tasks, they have just premade these scripts whereas with npm run scripts you're creating them yourself. These npm scripts are created by adding them to the "scripts" field within your package.json file and can be executed by typing the following: npm run <script-name>.
How are we able to just run the binaries of locally installed packages?
Well, the binaries of locally install packages are made available to you courtesy of your PATH environment variable. This is extremely convenient and allows you to run said binaries simply by typing the the name of said package instead of having to point to: node_modules/.bin/<node_module>. Furthermore, to see which scripts are available to you issue a: npm run
Ok back to your question.. Yes you'll will just have to create custom scripts utilizing various libraries to accomplish said task.
For example, scss to css watch, you could create a script like so:
"scripts": {
"buildscss": "sass --watch app/sass:public/stylesheets"
},
Alternatively, you could use node-sass to handle this task:
npm install --save-dev node-sass
"scripts": {
"buildscss": "node-sass --output-style compressed -o dist/css src/scss"
}
To serve and automatically inject changes you can utilize browser-sync. Something like the following:
npm i -D browser-sync
"scripts": {
"serve": "browser-sync start --server --files 'dist/css/*.css, dist/js/*.js'"
}
Alternatively if you only want to move html, css, js to a deployment directory, <dist> in this case, you could do the following:
"scripts": {
"copy": "cp <html_dir> dist/ && cp <css_dir> dist/ && cp <js> dist/",
}
As for your question about notifications: your custom script would run other custom scripts and print to the console the outcome of said script. There is much more that you can do with npm run scripts, such as: linting, watching, combining scripts, etc.. For a great tutorial check out this link as I am just scratching the surface.
Hopefully that helps!

Having to create a .nuxt folder every time I compile my app

Every time I run npm run dev(that's how my team set up that project) I get this error:
ERROR EEXIST: file already exists, mkdir 'X:......\my-project\.nuxt'
I then need to do mkdir .nuxt and try again. Usually it works, sometimes it doesn't: it keeps asking me that everytime I run npm run dev and after 5 or 10 times it works. Sometimes I won't work no matter how many times I try, so I restart my machine and then it works.
Any idea what's going on?
I have had issues of this kind when running in the past with gulp in parallel tasks that would delete and write to the same deleted directory. But, without having more information about this, and just knowing that sometimes the .nuxt directory is missing. I can't really get to the root of the problem. It might be something related with the nuxt.config.js
This is the only solution that I see for now.
Even though this might not fix the original issue what you could do to at least be able to develop without having to worry any longer is:
Add the rimraf package and run it always before running the dev command.
Add the mkdirp package and run it after the deletion of the folder happen
If you add the commands globally now you should have in your terminal both commands available and you can run
rimraf ./.nuxt && mkdirp .nuxt && npm run dev
This would be the least intrusive approach as it wouldn't affect any of your team members.
If also they are affected by this you can also add this packages as a devDependency and add another npm run dev command as shown here.
{
...
"scripts": {
"dev": "rimraf ./.nuxt && mkdirp .nuxt && npm run dev"
}
...
}

How to prevent yarn from running a package.json script after add somthing in the devDependencies?

If I run yarn add <dependency> -D, yarn will install the dependency AND run a task in my package.json. It'll run the "start" script.
At first I was annoyed so I renamed "start" with something else, but now it'll run "build" after the add command...
Is there a way to prevent yarn from running any command after add ?
Here's my current scripts in package.json :
"scripts": {
"clean": "mkdir -p lib && rm -r lib",
"build": "yarn clean && tsc",
"test": "tsc && mocha -c",
"test:watch": "tsc-then -- mocha -c"
}
note: I opened an issue for those who are interested, as it seems to be specific to watchy^0.9.0 #atom/watcher problem #20
You have the --ignore-scripts flag.
From yarn add --help:
--ignore-scripts don't run lifecycle scripts
yarn add --ignore-scripts -D package-name-1 ...
You can find this, and more with yarn add --help.
This is on Yarn 1.7.0.
I've been having this issue as well since I switched to Yarn over NPM. It appears that yarn, when given an unknown command, searches for one with the same name in your package.json scripts.
Additionally, for some reason yarn runs an excessive amount of additional lifecycle scripts on top of ones specified here on npm.
I had three scripts; build, update, and prepare. Renaming build to babel stopped that from being run. Renaming update to submodules stopped that. And renaming prepare to update-and-transpile stopped it.
So... just pick a more convoluted name for the time being and it stops being run.
I realize this isn't exactly an answer to your question, I'm going to file an issue on their GitHub about disabling this functionality.

IntelliJ stuck after running npm scripts

I have created a Scala, Play project. I am trying to add Angular2 in it. I added two npm commands through edit configuration. They are suppose to install the required packages and use webpack to bundle final JS. I notice that nothing happens after 2nd script is executed (I do not know if that script is hung or there is some other issue (see pic). It seems that the 2nd npm script is stuck because on stopping the run command, I see exit code 1 - Process finished with exit code 1
Is there a way to find out if Intelli build/run process is still running?
The issue was with the 2nd script (npm start). I had to remove --profile --watch flag from the webpack command. This works - "scripts": {
"start": "webpack --config webpack.config.dev.js --progress"
}