Npm workspaces - call workspace script from root package - node.js

I'm struggling with multiple npm packages in a root git repository with custom dev scripts to handle launch, compile, build and so on. Now I came across npm workspaces and wanted to use this stunning new feature in my following project structure but I can't get it to work:
projectx (root)
- package.json
- apps
-- backend
-- src
-- package.json (name: #projectx/backend, scripts: "dev":"ts-node or whatever")
-- common
-- src
-- package.json (name: #projectx/common)
-- frontend
-- src
-- package.json (name: #projectx/frontend, scripts: "dev":"webpack")
My root package.json contains:
{
"name": "packagex",
"version": "1.0.0",
"description": "",
"main": "index.js",
"private": "true",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"back:dev": "npm workspace #projectx/backend dev",
"front:dev": "npm workspace #projectx/frontend dev",
"dev": "run-p back:dev front:dev"
},
"workspaces": [
"apps/*"
],
"repository": {
"type": "git",
"url": "git_url"
},
"author": "me",
"license": "ISC",
"devDependencies": {
"npm-run-all": "^4.1.5"
}
}
And now I want to start backend and frontend with npm-run-all and the command on root: npm run dev which results in:
And I also want to share the common package with backend and frontend, which should be possible in this case. Maybe anobody else is facing the same problem or has some ideas what I am doing wrong here.

npm#7.7.0 added a way to call scripts from child packages/workspaces, here are some examples based on your original:
Running a script named "dev" in all workspaces located under apps/backend:
npm run dev -w apps/backend
Running a script named "dev" in all workspaces:
npm run dev --ws
Running a script named "dev" in a package named #projectx/frontend:
npm run dev -w #projectx/frontend
More info:
Related CHANGELOG entry: https://github.com/npm/cli/releases/tag/v7.7.0
Docs: https://docs.npmjs.com/cli/v7/commands/npm-run-script#workspaces-support
Blog post: https://dev.to/ruyadorno/npm-workspaces-npm-run-and-exec-1lg0

Your "workspaces" property in package.json looks right. I'm using NPM Workspaces and it's working well, but it's still missing a lot of features so you need to wire things up yourself. I also don't think npm worksace is a command (but maybe for the future?), so here's a checklist to get it to work:
Make sure you're using Node 15+ and NPM 7+
Set all package.json to "private": true,
Delete all package-lock.json inside of your project, go to the root, then npm install. It should generate one root level package-lock.json that contains all dependencies for your workspaces
Since you're using npm-run-all, add this to your scripts:
"scripts": {
"back:dev": "cd apps/backend && npm run dev",
"front:dev": "cd apps/fontend && npm run dev",
"dev": "npm-run-all build --parallel back:dev front:dev"
}
Then start it with npm run dev.
Note, you may want to consider using start scripts instead of dev to shorten the command you need to type (e.g. npm start instead of npm run dev), but npm run dev will still be fine.

In root package.json you can also add short name for each package:
"scripts": {
"api": "npm --workspace=#app/api run",
}
#app/api is a name in package.json
And run scripts in ./packages/api folder from root like so:
npm run api lint
npm run api dev

I think you wish to:
keep scripts and dependencies separate (thus the 4 package.json files), for ease of maintenance
May I suggest a work-around without workspaces that might do what you're after:
{
...
"scripts": {
"//back:dev": "npm workspace #projectx/backend dev",
"back:dev": "npm --prefix apps/backend dev",
"//front:dev": "npm workspace #projectx/frontend dev",
"front:dev": "npm --prefix apps/frontend dev",
"dev": "run-p back:dev front:dev"
},
"//workspaces": [
"apps/*"
],
"devDependencies": {
"#local/back": "file:apps/backend",
"#local/front": "file:apps/frontend",
"npm-run-all": "^4.1.5"
}
}
The npm --prefix runs npm scripts in another folder than the current one.
The #local/back dependencies are not necessary for that, but I've found such useful if eg. a package depends on another. You might use that trick to reach for the common by:
"dependencies": {
"#local/common": "file:../common"
}
I wished a week ago that workspaces would offer a better solution, but didn't find any benefit over the above mechanisms.
I would also like workspaces to:
only expose those files in the files entry of the particular package.json (now, all are shown)
only allow import to paths in the exports of the particular package.json, if it has one
See
NPM Workspaces monorepo - share local package's distribution folder as root instead of the entire source files

Related

Node & React - npm start - is running BUT localhost:3000 "cant be reached"

(having node version 12 and npm version 6)
Backend: Node.js
Front: React.js
i cloned repository
cd into the directory
ran
npm install (installing dependencies etc...)
and when i ran
npm start
and i get
[Ben#Mac:~/Desktop/test]$ npm start
> answers-entry-level-exam#1.0.0 start /Users/Ben/Desktop/test
> lerna run start --parallel
lerna notice cli v3.22.1
lerna info Executing command in 1 package: "npm run start"
#ans-exam/server: > #ans-exam/server#1.0.0 start
/Users/Ben/Desktop/test/server
#ans-exam/server: > ts-node-dev index.ts
#ans-exam/server: Using ts-node version 8.5.2, typescript version 3.7.2
#ans-exam/server: server running 3232
which seems like the server is running okay
but localhost:3000 cant be reached
not opening anything
the first time it did open and there was a MacOS popup on the right side of the screen related to node ( i think that is the issue but cant figure out how to fix)
my package.json:
{
"name": "answers-entry-level-exam",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"b": "npm run bootstrap",
"bootstrap": "lerna bootstrap",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "lerna run start --parallel",
"postinstall": "npm run bootstrap"
},
"author": "",
"license": "ISC",
"devDependencies": {
"lerna": "^3.22.1"
}
}
Thanks!
I cloned again the repo and it fixed that
Cheers to all those who tried to help :)
Try localhost:3232. I see in your output server running 3232

How to hide a section in .hbs and .js while taking an ember production build

Our Ember application is developed in 2.8 version and we follow POD structure.
We are generating two different builds as below
1) For our dev server : No change in code,just do build
2) For our test server: Delete a section in HBS and also remove a route from router.js then do build
And we take build using "npm run-scripts build" which is configured in our package.json as below
"scripts": {
"build": "ember build",
"start": "ember server",
"test" : "ember test"
},
I would like to know in ember 2.8v can i have a condition written to remove the section based on build.
Like if i give npm run-scripts buildDev it will do the regular build
and if i give npm run-scripts buildTest it will do sections removals and give a build
but in package.json both will be configured like
"scripts": {
"build" : "ember build",
"buildDev" : "ember build --environment=production",
"buildTest": "ember build --environment=production",
"start": "ember server",
"test" : "ember test"
},
Do you only want to disable a section or do you need to remove it from the build?
Its pretty easy if you want to only disable something:
First you can use environment variables in your config/environment.js. So something like this:
if(process.env.DEV_BUILD) {
ENV.disableSomething = true;
}
In your package.json you could do this:
"build": "cross-env DEV_BUILD=1 ember build",
This uses cross-env to set the env variable in windows and *nix systems.
You can then import the config and use it:
import ENV from 'hss/config/environment';
...
if(!ENV.disableSomething) {
this.route('foo');
}
...
However if you want to actually remove some code you could write your own addon for this to replace some variable with true or false. then the minifier will remove the code.

How to get environment variable in npm script?

I am trying to access an enviroment variable in the npm script itself like so:
"scripts": {
"test": "istanbul cover node_modules/.bin/_mocha --root ../SERVER/routes -- --recursive"
},
And start this script like so:
SERVER=somewhere npm test
How can I get the resolved value of SERVER variable in the npm script in the package.json itself?
For the windows users, you may use your variables like this: %SERVER% instead of $SERVER.
Or better approach to use cross-env module which will allow you to do it like linux on all platforms:
npm i cross-env
And use it :
"scripts": {
"test": "cross-env-shell \"istanbul cover node_modules/.bin/_mocha --root ../$SERVER/routes -- --recursive\""
}
Will using $SERVER work for you?
"scripts": {
"test": "istanbul cover node_modules/.bin/_mocha --root ../$SERVER/routes -- --recursive"
}

npm: how to run test & lint on each change?

I am using a bare npm ( no grunt/gulp) approach to develop my new MEAN project.
My config is like the following:
File package.json:
...
"start": "nodemon ./bin/www",
"lint": "jshint **/*.js",
"test": "mocha --recursive",
"dependencies": {
...
},
"devDependencies": {
...
},
Before starting, I run an npm start and nodemon starts monitoring my project tree for changes, triggering a restart after each source file change.
So far so good.
But what if I'd like to include - say - the lint and/or the test stages on each restart?
I didn't find any clue nor in the nodemon page nor in the npm one...
So you should have a definition of the start in your package.json to first run lint, then test then the actual run server.
You can find an example in following post:
http://substack.net/task_automation_with_npm_run
you should run the 'npm run monitor' command to start the monitoring and the restart should call the npm run start script.
but basically you want to have (based on your package.json)
"scripts": {
"start": "npm run lint & npm run test & node ./myfile.js",
"lint": "jshint **/*.js",
"test": "mocha --recursive",
"monitor": "nodemon ./bin/www"
.....

Watcher automation in Mocha

I would like to achieve automation of motcha --watcher feature using package.json file without globally installing mocha.
One of npm features is to allow add custom scripts into npm command. Previously I configured test runner successfully and I can type in bash now:
npm test
Everything works fine, so I would like also do something similar because
./node_modules/mocha/bin/mocha --watch app.js test.js"
is not too efective.
My goal is to run mocha watcher by typing in bash:
npm watch
Unfortunately watcher doesn't run - instead I see standard output of npm command without parameters. It looks like my custom script wasn't registered by npm.
Here is my actual package.json file
{
"name": "screencast",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha test.js", // works properly after typing 'npm test'
"watch": "mocha --watch app.js test.js" // Syntax looks ok, but command 'npm watch' d
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.10.6"
},
"devDependencies": {
"mocha": "^2.0.1",
"supertest": "^0.15.0"
}
}
Anyone had this issue before?
For a 'custom' script like watch, you have to do npm run watch instead of npm watch

Resources