Mixing concurrently and cross-env in a package.json script - node.js

Building a monorepo template, I'm facing an issue in the scripts of my package.json. I'm trying to make my scripts compatible with npm alternatives like yarn or pnpm. So I tried to use a config object to specify the wanted CLI:
{
"config": {
"cli": "npm"
}
}
Then I was able to access the value through the environment variable npm_package_config_cli. Since the usage of environment variables has different syntaxes between unix systems and windows, I used cross-env. This worked well for most of my scripts, for example:
"dev-front": "cross-env-shell \"cd ./frontend && $npm_package_config_cli run dev\"",
Here you can see the usage of cross-env-shell to execute the command between quotes:
cd ./frontend && $npm_package_config_cli run dev
With $npm_package_config_cli being resolved by cross-env according to the OS.
My package.json purpose is to drive the scripts in frontend and backend folders of my monorepo template. So I'm using concurrently to keep track of the different outputs. My issue is when using cross-env-shell along with concurrently. I tried to call cross-env-shell "inside" concurrently and vice-versa, with single and/or double quotes, but $npm_package_config_cli is not resolved on windows.
A minimal package.json with the failing dev script (dev-front and dev-back are working):
{
"config": {
"cli": "npm"
},
"scripts": {
"dev": "concurrently -n front,back -c green,yellow -t 'HH:mm:ss' -p '{name} {time}' 'cross-env-shell \"cd ./frontend && $npm_package_config_cli run dev\"' 'cross-env-shell \"cd ./backend && $npm_package_config_cli run dev\"'"
"dev-front": "cross-env-shell \"cd ./frontend && $npm_package_config_cli run dev\"",
"dev-back": "cross-env-shell \"cd ./backend && $npm_package_config_cli run dev\""
},
"devDependencies": {
"concurrently": "^7.6.0",
"cross-env": "^7.0.3"
}
}
Any hint on the valid syntax? Is there a better approach?

Trying harder, the following combination worked with concurrently wildcards:
{
"config": {
"cli": "npm"
},
"scripts": {
"dev": "cross-env-shell 'concurrently -c green,yellow -t \"HH:mm:ss\" -p \"{name} {time}\" \"$npm_package_config_cli:dev-*\"'",
"dev-front": "cross-env-shell \"cd ./frontend && $npm_package_config_cli run dev\"",
"dev-back": "cross-env-shell \"cd ./backend && $npm_package_config_cli run dev\""
},
"devDependencies": {
"concurrently": "^7.6.0",
"cross-env": "^7.0.3"
}
}

Related

How do I use nodemon with docker in my node.js application?

I am new to Docker and coding. I have already added it as dev-dependency but still I have to build the image every time I make a change to the code. I have tried looking this up but have not found a solution that is suitable/working because I am using process.json file.
My Dockerfile :
FROM node:12.14.1-alpine
# app name
ENV APP_NAME=mock-api
ENV WORK_DIR /deploy/${APP_NAME}
# Create app directory
RUN mkdir -p ${WORK_DIR} && \
chown node:node ${WORK_DIR}
RUN apk add --update gnupg
WORKDIR ${WORK_DIR}
COPY ["yarn.lock", "package.json", "./"]
RUN yarn global add pm2 && yarn install --prod --frozen-lockfile && yarn cache clean
COPY --chown=node:node . .
EXPOSE 3000
USER node
CMD ["pm2-runtime", "--no-daemon", "--raw", "process.json"]
Process.json :
{
"apps": [
{
"name": "mock-api",
"script": "./app.js"
}
]
}
package.json:
{
"name": "mock-api",
"version": "1.0.0",
"description": "Mock API for the testing environment",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "arorasannidhya#gmail.com",
"license": "ISC",
"dependencies": {
"koa": "2.12.0",
"koa-joi-router": "^6.0.2",
"koa-logger": "3.2.1",
"koa-router": "9.0.1",
"openpgp": "4.10.4",
"pm2": "^4.2.3",
"uuid": "^7.0.2"
},
"devDependencies": {
"nodemon": "^2.0.4"
}
}
Nodemon is the utility to run the node application (it watches file in the directory and when changed runs index.js or app.js (whatever is your root file))
It cannot be used to build a docker image, you will need to do something like this https://vsupalov.com/rebuilding-docker-image-development/#:~:text=In%20Conclusion,see%20the%20results%20right%20away!

Docker - Puppeteer require somethings and wont run

I've created a container with Docker from a NodeJS app,
but when I try to run it the application will start but goes in error loop.
My Dockerfile contain
RUN npm install
but it continuously break on:
ERROR PuppeteerCrawler:PuppeteerPool: Browser launch failed {"id":12}
Error: Could not find browser revision 756035. Run "npm install" or "yarn install" to download a browser binary
If i run Node main.js there are no problem.
//Dockerfile
FROM apify/actor-node-basic
COPY package*.json ./
RUN npm --quiet set progress=false \ && npm install --only=prod
--no-optional \ && echo "Installed NPM packages:" \ && npm list \ && echo "Node.js version:" \ && node --version \ && echo "NPM version:" \ && npm --version
COPY . ./
WORKDIR .
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "Worker.js" ]
// package.json
{
"name": "SoccerBrain",
"version": "0.0.1",
"description": "This is an example of an Apify actor.",
"dependencies": {
"apify": "^0.21.0",
"puppeteer": "^5.0.0",
"rimraf": "^3.0.2"
},
"devDependencies": {},
"scripts": {
"start": "node Worker.js",
"test": "echo \"Error: oops, the actor has no tests yet, sad!\" && exit 1"
},
"author": "It's not you it's me",
"license": "ISC"
}
what's append?

Run eslint "ONLY" on the staged files

I am trying to use a pre-commit hook to detect eslint errors before commit happens. I am using husky and lint-staged. But it runs the lint command for all the files in src and not on staged files only. Here is my package.json file.
"scripts": {
"test:ci": "cross-env CI=true react-scripts test --bail --passWithNoTests",
"lint": "eslint src/**/*.{js,jsx}",
"lint:fix": "eslint . --fix",
"precommit": "npm run lint && npm run test:ci"
}
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"npm run precommit"
],
"*.jsx": [
"npm run precommit"
]
}
Is there any way so that it works ONLY on staged files and not on other files present in the directory?
With husky v7/lint-staged v11.2.0 - the staged files will simply by added onto the end of your command, separated by spaces. If you have a .husky/pre-commit file which calls npx lint-staged, and then you have a lint-staged config like so:
{
'*.js': [
'eslint'
]
}
And you modify src/foo.js and src/bar.js, the command that will be run is:
eslint src/foo.js src/bar.js
Doesn't matter what command you have inside of your lint-staged config. Files are just added onto end of command, separated by spaces.
These files will be passed to your test:ci command but they won't make it to your lint subcommand.
You can wrap in bash function... Something like this:
"precommit": "!runIt() { npm run lint $# && npm run test:ci $#;}; runIt",
Wrote this on my phone, and I barely know bash, so syntax might be wrong
With the ESLint CLI you have a help parameter npx eslint -h, --help or you can check the CLI docs at the official ESLint docs page/CLI. There's a section related to caching, so that ESLint only looks at files that have been changed.
Caching:
--cache Only check changed files - default: false
--cache-file path::String Path to the cache file. Deprecated: use --cache-location - default: .eslintcache
--cache-location path::String Path to the cache file or directory
--cache-strategy String Strategy to use for detecting changed files in the cache - either: metadata or content - default: metadata
According to this lint-staged example, I implemented that in order to lint only staged files (takes like 5 secs) except when there are more than 5 staged files, it checks all the repo (can take more than 1 min):
Upgrade lint-staged package to the latest version
Add a .lintstagedrc.js file at the root of your repo. It could contain something like this:
module.exports = {
'**/*.js?(x)': (filenames) =>
filenames.length > 5 ? 'eslint --ext .js,.jsx . --ignore-path .gitignore --fix .' : `eslint ${filenames.join(' ')} --fix`,
"*.json": [
"prettier --write"
]
}
Remove your old "lint-staged" command from the package.json file
"husky": {
"hooks": {
"pre-commit": "lint-staged"
},
},
"lint-staged": {
"*.js": [
"eslint src/**/*.{js}",
"cross-env CI=true react-scripts test --bail --passWithNoTests",
"git add"
]
},

Nodemon not working using npm script from package.json on Docker

I'm working with NodeJS and Nodemon on Docker. When I try to run my NodeJS app using nodemon command directly in docker compose file, it runs.
Like this (working): [docker-compose]
command: nodemon source/index.js
But when I use a script from package.json, it doesn't work
Like this (not-working): [docker-compose]
command: npm run dev
Where my package.json file is
"scripts": {
"start": "node source/index.js",
"dev": "nodemon source/index.js"
}
I tried different things, when I simply run start script without nodemon, it works
Like this (working): [docker-compose]
command: npm run start
But when I try to use dev again with nodemon command inside it, it doesn't work. Container won't start. I have also tried the following and it also works
Like this (working): [docker-compose]
command: nodemon --exec npm start
I still don't understand, why nodemon command is not working inside script dev
I'm using Docker in Swarm Mode
Here are my both files
docker-compose
version: '3.7'
services:
node-service:
image: node-img:1.0
ports:
- 4000:4000
working_dir: "/node-dir"
volumes:
- ./node-dir/source:/node-dir/source
networks:
- ness-net
command: npm run dev
networks:
ness-net:
package.json
{
"name": "node-pkg",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node source/index.js",
"dev": "nodemon source/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^1.19.4"
}
}
Just add the "." to define the path in your package.json like this
"scripts": {
"start": "node ./source/index.js",
"dev": "nodemon ./source/index.js"
}
You need to add an environment variable to point on npm when running nodemon
C:\........\npm the path should be like this , and choose a name
Try this solution:
services:
node-app:
container_name: node-app
image: node:latest
restart: always
volumes:
- ./node/source:home/node/source
working_dir: /home/node/source
ports:
- 4000:4000
networks:
- main-network
command: "tail -f /dev/null && npm start"
depends_on:
- db
logging:
driver: "json-file"
options:
max-file: "4"
max-size: "100m
Here is package.json
"main": "index.js",
"scripts": {
"preinstall": "npm i nodemon -g",
"start": "nodemon index.js",
}
Please make sure there should be index.js and package.json in working directory.

babel watch on docker

i set docker instance with node.
i want to develop on this instance and use babel to "compile" my node code.
i use #docker/cli to compile with watch flag and i use nodemon with -L flag.
for some reason, nodemon is watching file changes great but not babel.
any idea?
this is my docker-compose.yml
main-app:
build: ./mainApp
user: "root"
command: yarn run start:watch
environment:
NODE_ENV: production
PORT: 8080
volumes:
- ./mainApp:/app
- /app/node_modules
ports:
- '8080:8080'
this is package.json:
"scripts": {
"build": "babel src --out-dir public",
"serve": "node public/server.js",
"build:watch": "babel --watch src -d public -s",
"serve:watch": "nodemon -L public/server.js",
"start:watch": "concurrently -k \"npm run build:watch\" \"npm run serve:watch\""
},
"dependencies": {
"express": "^4.16.1"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.35",
"#babel/core": "^7.0.0-beta.35",
"#babel/preset-env": "^7.0.0-beta.35"
},
as you can see i use concurrently to run them both.
what can be the problem babel is not watching my files?
PS: it works fine on my local machine
babel-watch didn't worked out for me.
As I was compiling code through babel cli and outputting in some another directory (to be used by second docker container)
I ended up using nodemon exec option
In my package.json, created new script especially for docker:
"docker-build:watch": nodemon -L --watch src --exec 'npm run build:watch'
and then using npm run docker-build:watch instead of npm run build:watch
Babel CLI uses Chokidar to watch file changes, to make it work inside a linux image you need to:

CHOKIDAR_USEPOLLING=true babel --watch


You can read more about this here
I was having a similar issue and ended up using 'babel-watch'. IT still required me to use the -L flag to enable poling to get it to work in Docker. I have not tried it, but the same approach may work with babel itself.
Take a look at the babel-watc readme for more details. https://github.com/kmagiera/babel-watch#troubleshooting
You filesystem configuration doesn't trigger filewatch notification
(this could happen for example when you have babel-watch running
within docker container and have filesystem mirrored). In that case
try running babel-watch with -L option which will enable polling for
file changes.

Resources