I am trying to setup WebStorm with Flow typing for a Node.js project.
I have it all working fine with NPM scripts but would like to integrate with the IDE.
Here is the scripts portion of my package.json:
"scripts": {
"dev":
"watch --wait=1 'flow-remove-types src/ -d lib/ --all --pretty' ./src/ & nodemon ./lib/server.js",
"start": "npm run flow:build && node ./lib/",
"lint": "eslint src/**",
"test": "npm run flow:build && jest lib",
"coverage": "jest --collectCoverageFrom=src/**.js --coverage src",
"flow": "flow",
"flow:check": "flow check ./src/",
"flow:build": "flow-remove-types ./src/ -d ./lib/ --all --pretty",
"flow:deps": "flow-typed install",
"flow:watch": "flow-watch"
},
Now if I modify the run configuration for a test and:
change the src directory to lib
specify a before launch, run NPM script 'flow:build'
then I can run that configuration.
I still have two problems.
Debugging will not stop on a breakpoint
If I hit the arrow in the source code gutter to run the test, it creates a new config which runs against the flow source and fails
Does anyone have Node.js and flow working well together in WebStorm?
You can use --sourcemaps and -pretty flags:
flow-remove-types --pretty --sourcemaps --out-dir out/ in/
The -m or --sourcemaps flag adds sourcemaps files to your /out folder
The -p or --pretty flag removes the empty spaces in the files of your /out folder
flow-remove-types does not generate sourcemaps, so there is absolutely no way for debugger to map the generated file in lib to original files in src. You have to add breakpoints to the generated files located in lib folder if you like to debug your tests
no way - configuration is generated for the file you hit the arrow in. If you like to run individual tests from gutter, hit the arrow in generated file, not in the source one
You can use Babel flow preset instead of flow-remove-types:
npm install --save-dev babel-cli babel-preset-env babel-preset-flow
create a .babelrc file in your project root dir:
{
"presets": ["flow"]
}
And that's all you have to do - no precompiling, etc., running from gutter/debugging for source files will work out of the box
Related
I'm setting up a new project with nodejs, express, typescript, and babel. So I use babel for faster transpile typescript code and etsc for types checking
When I writing code, I'd like to the application applied changes automatically without me manually restart the application. My solution is running babel cli for transpile code with nodemon.
My script is like this
"scripts": {
"ts-check": "tsc --noemit",
"build-ts": "etsc",
"build": "rm -rf dist && yarn run build-ts",
"dev": "nodemon --exec babel src --out-dir dist --extensions \".ts\" --source-maps inline",
"start": "node ./dist/src/index.js"
},
But the problem is the application keeps restart even when I don't make any changes to the code. So how do I solve that?
Is there a better solution for applied changes automatically?
Here is what I got
The first problem is nodemon runs only babel command and not your ./dist/src/index.js. And the second problem is babel being run transpiles your .ts files into .js and then nodemon notices .js files changed and reruns your command (babel) that again transpiles your .ts files into .js ones with new timestamps. And I believe you've got the idea.
So in fact you need two serapate but dependent things: recompile your .ts files into .js ones, and restart node only when .js files changed.
You may achive that with something like that:
"scripts": {
...
"dev": "babel src --watch --out-dir dist --extensions .ts --source-maps inline & nodemon"
...
So you're starting simultaneously both babel in watch mode and nodemon. When there are changes in .ts files babel will recompile them into .js and when there are changes in .js files nodemon will restart node.
There is a minor drawback however. On the first run while there is no ./dist/src/index.js file nodemon will throw an error. It's not critical, nodemon will continue to run. And just after babel finished transpiling code nodemon will pick up the changes and go on without issues.
Though if you do not want to see that error in console you may include a delay before nodemon starts. Just long enough for babel to finish it's first run.
"scripts": {
...
"dev": "babel src --watch --out-dir dist --extensions .ts --source-maps inline & sleep 5 && nodemon"
...
I have an angular project. when we run ng build command the build artifacts are created in dist folder as we have set "outDir": "dist", in angular-cli.json. After this I have to manually copy these files from dist to Webcontent folder of java to generate a WAR file.
Is there any way to automate the process coping the artifacts. If I set the path of WebContent as outDir value "outDir": "../server/WebContent", the build command is cleaning up the existing java files before generating build artifacts.
Any suggestions will help..
Consider the following solution:
Add a npm script named build in your projects package.json file to execute your ng build command.
Also add a post hook npm script named postbuild to copy your files.
The following describes how to achieve this on a *Nix platform, and also provides a cross-platform solution.
*Nix (Linux, macOS, ... )
On *nix platforms npm utilizes sh as the default shell for running npm scripts. Therefore add the following to the scripts section of your projects package.json:
package,json
"scripts": {
"build": "ng build",
"postbuild": "cp -r dist/ ../server/WebContent"
}
This postbuild npm script utilizes the shells cp command to recursively copy artifacts from the dist directory to the ../server/WebContent directory. The postbuild script will automatically run when the build script successfully completes.
Running:
Via your command line run the following command instead of ng build:
npm run build
Cross-platform (Linux, macOS, Windows, ... )
For a cross-platform solution firstly install shx - it’s a wrapper around ShellJS Unix commands:
cd to your project directory.
Then run the following command:
npm install -D shx
Define the scripts section of your projects package.json as follows:
package.json
"scripts": {
"build": "ng build",
"postbuild": "shx cp -r \"dist/*\" \"../server/WebContent\""
}
Running:
Via your command line run the following command instead of ng build:
npm run build
In a nodejs express.js application, and trying to build the app using babel for cross browser compatibility.
package.json scripts:
"scripts": {
"start": "node dist/app.js",
"build": "babel src -d dist"
}
On running npm build and check my build folder everything builds correctly except my non-js files like [.html,.css,.ejs]. At the moment just copied those file to the build folder in their respective sub directories and everything works fine.
I have even tried
"build": "babel src -d dist --ignore *.css,*.ejs,*.png,*.jpg"
Is there a way to do this in a better way instead of copying the non-js files. Thanks in advance any help will be highly appreciated.
If you have non-JavaScript files in the source directory that should be automatically copied to the output location when the command is run, simply add the --copy-files flag.
babel src -d dist --copy-files
The flag doesn't take any arguments and will copy all non-JS files over.
I'm developing an Express app. The code uses ES6 import statements, so it needs to be transpiled by Babel in ES5 code so it can be run with Node. The ES6 source code is stored in my src directory, and the compiled code is placed in my dest directory.
I would like an npm command that I can run that will watch for any changes in my src directory, transpile the project into dest, and then restart the Express app.
Below is my solution so far (I run npm run server:watch). It uses chokidar-cli to execute the server:build and server:run scripts whenever any js file changes within my src directory. This works perfectly except that the Express app does not die when the code is transpiled again, so I get a 'port in use' exception when I try to run server:watch again.
// package.json
"scripts": {
"server:clean": "rm -f dist/*",
"server:build": "npm run server:clean && ./node_modules/.bin/babel ./src --experimental --source-maps-inline -d ./dist",
"server:run": "nodemon dist/app.js --watch",
"server:watch": "chokidar 'src/*.js' -c 'npm run server:build && npm run server:run'"
}
Am I on the right track here? What is the best solution to this sort of problem?
(For clarification, I am talking about transpiling server-side code, so webpack or any other module bundler would be inappropriate here)
nodemon is watching your dist files, and is never terminating. With your watch script, you're launching a second instance of nodemon every time there's a file change, hence the "port in use" error.
You need to launch nodemon once, and keep in running in the background while your watch script is running. This is most easily done with https://github.com/mysticatea/npm-run-all.
Install it by running:
npm install npm-run-all --save-dev
on the command line.
Then you'd edit your scripts to:
// package.json
"scripts": {
"server:clean": "rm -f dist/*",
"server:build": "npm run server:clean && ./node_modules/.bin/babel ./src --experimental --source-maps-inline -d ./dist",
"server:run": "nodemon dist/app.js --watch",
"server:watch": "chokidar 'src/*.js' -c 'npm run server:build'",
"server:dev": "run-p server:run server:watch"
}
Then, you simply run npm run server:dev on the command line to start up your server via nodemon, and start the watch/rebuild process, all in one command.
Side note: If you're developing on Windows, you won't be able to use single quotes in your scripts, you have to use double-quotes, escaped with \" in the JSON.
When testing locally I was previously running:
"build-live": "nodemon --exec ./node_modules/.bin/ts-node -r dotenv/config -- ./index.ts"
I then figured my Procfile should be something like:
web: ./node_modules/.bin/ts-node -- ./index.ts
But it says module 'typescript' not found, even when it is in package.json. I read in a few places that ts-node is not the way to go to deploy to Heroku, so I am not sure what to do.
UPDATE: I think I am supposed to compile it, so I tried:
web: ./node_modules/.bin/tsc --module commonjs --allowJs --outDir build/ --sourceMap --target es6 index.ts && node build/index.js
This succeeds, however when actually running it, a bunch of the libs I'm using get "Cannot find module '...'".
Alternatively you can have the TypeScript compile as a postinstall hook and run node build/index.js as the only Procfile command:
Your package.json should contain a postinstall hint that gets executed after npm install and before the node process launches:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
You can then leave your Procfile as is:
web: npm start
This 'build on deploy' approach is documented by Heroku here.
The command you've given Heroku is to launch the web "process" by compiling index.ts and dependencies and starting node at index.js. Depending on how things are timed, index.js might or might not exist at the time node starts.
You need to already have your sources compiled by the time you want to start your app. For example, web should just be web: node index.js or similar.
Each build process is different, so you need to figure that out for your own setup. But, suppose you have a classical setup where you push to git and then Heroku picks up that change and updates the app with the new slug. You could just compile things locally and include index.js and any other build output in the repository, for it to be available in the slug for Heroku to use.
A better approach is to use a build server which has an integration with Heroku. After you do the build there, configure it to send the build results to Heroku. Travis has a straighforward setup like this. This way you don't need to include build outputs in your repository, which is considered an anti-pattern.
On a sidenode, try using a tsconfig.json to keep the tsc configuration. It will save you from having to write such long command lines all over the place.
Fabian said that we could do something like:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
As of me writing this, I tested this and can state: postinstall is not required since build script is ran by Heroku. If you want to do it without build script, then you can use heroku-postbuild which will run after dependencies are installed there you run tsc to compile.
My problem was about missing Typescript npm modules. The Typescript compiler tsc was not found when deployed the app to Heroku.
The Heroku deploy process (rightly) does not install development dependencies, in my case the Typescript module was part of devDependencies and thus the tsc command was not running on the Heroku platform.
Solution 1
Add typescript to dependencies: npm i typescript -s
Solution 2
Open Heroku console:
Select console type:
Run the command npm i typescript && npm run tsc
Install typescript as a dev dependency (cf. https://www.typescriptlang.org/download). Once built, your app does not need typescript anymore!
npm install -D typescript
Then in your package.json:
{
"main": "index.js", // <- file will be generated at build time with `tsc`
"scripts": {
"build": "tsc",
"start": "node ."
"start:dev": "ts-node index.ts" // idem, install ts-node as a dev dependency
}
}
The key point here is "build": "tsc".
Why?
Heroku does install all dependencies during build and remove the dev dependencies before the app is deployed (source here).
Node.js deployments will automatically execute an app’s build script during build (since March 11. 2019 source here)
In package.json
"scripts": {
"tsc": "./node_modules/typescript/bin/tsc",
"postinstall": "npm run tsc"
},
Works for me for Heroku deployment.
Installing typescript npm install -D typescript and writing tsc in the build script "build": "tsc", does not work for me. Also, try to run npm i typescript && npm run tsc in the Heroku console which also does not work.
In my case, I remove some dependencies from "devDependencies" to "dependencies", so it goes like this:
"dependencies": {
// The other dependencies goes here, I don't touch them.
// But all TS dependencies I remove to here.
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3",
"ts-loader": "^8.0.18"
},