How to run node.js ES6 file on mac - node.js

Can someone help me run a node.js file that has ES6 features? This is my current workflow:
Save change in file
npm run build --- builds file to my src/dist folder
cd into my dist directory
node
var file = require('./index.js')
file.someMethod()
Then when I make a change to my method, I need to repeat all the steps above again.
Does anyone know of a more efficient way to do this?
Thanks in advance!

You dont need anything if you are not using import/export. Just Install node 8.x and then run node my_file.js. Nodejs supports most of the es6 features out of the box.
If you want to use import/export then I would recommend to use typescript: https://www.typescriptlang.org/. It has compiler TS (statically typed ES6) to ES5.
Oh, and of course both babel and typescript have watcher modules (auto recompiling on file change).

It really depends on what npm run build actually does in your app. Does it run gulp/grunt? Webpack? Etc. If it's webpack there is a webpack-dev-server that you should look into.
If it's grunt or gulp then you have a custom build chain that you're working with. If all you need is to support es6 features without having to build the project then you could use something simple like babel-cli and run your file from outside the dist directory.
$ npm i -g babel-cli
$ babel-node
> var file = require('./index.js');
> file.someMethod()
By running babel-node you're running the normal node repl but with babel required. Es6 features should now be supported in the repl without needing to be compiled to es5.
You may also want to try simply updating to the latest version of node because node 8 has pretty extensive es6 support.

Related

Electron, TypeScript, SQLite: package.json not found

I'm having trouble using the npm sqlite3 package with electron. I'm compiling my electron app from Typescript files to Javascript, bundling them with browserify, and then running the main bundle to launch the main process.
But when I try to use sqlite3, I have problems. I've tried using electron-rebuild as its own separate step before compiling the typescript. I've tried installing sqlite3 with a --build-from-source flag. But whenever I try to run my main bundle, I get a "package.json does not exist" error, which seems to be coming from node-pre-gyp code in my main bundle, which is from the sqlite3 module.
Does anyone have any ideas as to what I'm doing wrong? I don't understand why the code is building itself again with node-pre-gyp when I already rebuilt it with electron-rebuild. I have a package.json in the root directory of the project, but the main bundle is in (root)/build/js-bundles, and the code is looking for package.json in (root)/build.
I know my description isn't all that clear, so if anything isn't obvious I'll do my best to clarify. (The program works fine when I remove the dependency on sqlite3).
Okay, so the problem is that I was using browserify to bundle the sqlite3 dependency. By excluding sqlite3 with the --exclude flag, the problem disappeared.
The issue seems to be that building sqlite3 generates a sqlite3.js file whose sole purpose is to find (and load?) the built node-sqlite3.node binary -- but only at runtime. When sqlite3 is bundled and the bundle is run, it will attempt to locate the binary, but it can't, because my bundle isn't in the node_modules/sqlite directory, it's in my build directory. By excluding sqlite3 from the browserify bundling, at run-time, the import * as sql from "sqlite3" will find node_modules/sqlite3/sqlite3.js, find the binary, and then load it into the program.
The lesson seems to be that while browserify knows how to bundle standard NodeJs modules like fs and path, bundling custom native node modules from npm doesn't work. The program has to find it at run-time.
I don't know anything about the inner workings of NodeJs and how the program knows to look for sqlite3 in build/../node_modules/sqlite3 (I didn't know that it could), so I'd be happy if anyone more knowledgeable could provide details.
Also, even after excluding sqlite3, I still had problems because I hadn't built sqlite3 against my version of electron. Resources for doing this can be found at electron-rebuild in the general case, or in the case of sqlite3, at mapbox/node-sqlite3 in the Installing section.

WebStorm: import/export statement in JavaScript

I'm using WebStorm and a newbie to it. when I use import/export statements, it gives me an error of
Unexpected token import
but if I try with require/module.exports it works fine.
N.B- I've configured language version as ES6 from Languages and Frameworks.
This is not WebStorm but Node.js that fails. While import is a part of ES6, native support for ES6 modules in Node.js is very limited and requires special setup - see https://nodejs.org/api/esm.html#esm_enabling. So, you have to compile your code with Babel first. Usually transpiling is a part of build process (using Gulp, Grunt, WebPack, etc.). Or, you can transpile your code on-the-fly by passing -r babel-register to Node.js. Of course, you need creating appropriate .babelrc and install the required modules (npm install --save-dev babel-cli babel-preset-env)

How to create a simple (Hello World) node.js TypeScript project with ES6 modules?

Imagine a very simple program with a main file and some functions in a separate file, using ES6 modules and intended to be run with node.js.
my-utils.ts:
import * as fs from "fs";
export function readSimpleFile() {
return fs.fileReadSync("hello.txt", "utf-8");
}
main.ts:
import {readSimpleFile} from "./my-utils"
console.log(readSimpleFile());
What is the minimum set of files I need to add to the project and commands I have to run to get it building, running and checking types?
If you are to run a typescript project with node you need to have at least node, npm and typescript installed on your plateform.
Using an IDE to setup the project
Using intelliJ IDEA or Webstorm (they are the ones I know the best), the compilation of typescript into javascript is done automatically; you only need to do some settings.
Let us assume you have a file called project.ts containing your hello world code; IDEA or Webstorm will compile your code to project.js. Then you will only need to do node project.js to run your project.
Doing everything from scratch
First you need to know where exactly your npm packages are installed globally. This command can help you identify the path: npm config get prefix. In this folder, you should have a nodes_modules subfolder that contains the typescript module. If there is no typescript module, that is because you did not install typescript globally (npm install -g typescript).
Then you have to add the path of the bin of typescript subfolder in your environment variable.
Now you can compile the project with typescipt: tsc project.ts and you can run it node project.js.
Since you are using node function like fs you will need to install node typings npm install #types/node --save-dev before compiling with tsc.
Compilation option
To enable or disable all strict type checking options, you might need to use compilation option. You have to create the file in which you will specify the compilation option: tsc --init will create a tsconfig.json in which you can specify what behaviour you would like to have during the compilation of your app. All options are listed here.

browserify will not compile express js

I wrote a very basic express.js app. Then tried to make it one .js file. Browserify compiled the whole thing to a one file. But browserify-compiled code didn't work. As far as I know, browserify just replaces require statements with module codes. Error is:
C:\Users\HP\n\express\app.js:27025
__proto__: http.IncomingMessage.prototype
^
TypeError: Cannot read property 'prototype' of undefined
at Object.__dirname.173.accepts (C:\Users\HP\n\express\app.js:27025:34)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.170../application (C:\Users\HP\n\express\app.js:26823:11)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.168../lib/express (C:\Users\HP\n\express\app.js:26154:18)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.153.express (C:\Users\HP\n\express\app.js:24010:15)
Browserify is designed specifically to package code for a browser.
Node.js supports a number of modules that a browser doesn't which have to be emulated by builtins. These modules will be replaced by a browser-specific shim. Some only supply a subset of the Node API that makes sense to have in a browser.
So you are running an app that has converted all the Node.js modules to support running what it can in a browser, back in Node where the modules are available but are no longer being used.
Try rollup or you could possibly configure babel to work like you need
I had this very same issue but like you said the compile code should work on server side. I solved it from this link:
https://www.linkedin.com/pulse/bundling-nodemodules-your-nodejs-app-one-single-file-xuan-son-nguyen/
Use browserify for bundling and terser for minifying. Starting by installing them globally:
npm install -g browserify
npm install -g terser
Next, we have to add a build script to package.json
...
"scripts": {
...
"build": "browserify --node --ignore-missing index.js | terser > bundle.js"
}
...
Each time you want to promote to production, you have to make a new bundle:
npm run build
A new file called "bundle.js" will be created.
Let there be peace, and there was peace. Happy coding.

How to run TypeScript files from command line?

I'm having a surprisingly hard time finding an answer to this. With plain Node.JS, you can run any js file with node path/to/file.js, with CoffeeScript it's coffee hello.coffee and ES6 has babel-node hello.js. How do I do the same with Typescript?
My project has a tsconfig.json which is used by Webpack/ts-loader to build a nice little bundle for the browser. I have a need for a build step run from the console before that, though, that would use some of the .ts files used in the project to generate a schema, but I can't seem to be able to run a single Typescript file without compiling the whole project.
How do I do the same with Typescript
You can leave tsc running in watch mode using tsc -w -p . and it will generate .js files for you in a live fashion, so you can run node foo.js like normal
TS Node
There is ts-node : https://github.com/TypeStrong/ts-node that will compile the code on the fly and run it through node 🌹
npx ts-node src/foo.ts
Run the below commands and install the required packages globally:
npm install -g ts-node typescript '#types/node'
Now run the following command to execute a typescript file:
ts-node typescript-file.ts
We have following steps:
First you need to install typescript
npm install -g typescript
Create one file helloworld.ts
function hello(person){
return "Hello, " + person;
}
let user = "Aamod Tiwari";
const result = hello(user);
console.log("Result", result)
Open command prompt and type the following command
tsc helloworld.ts
Again run the command
node helloworld.js
Result will display on console
To add to #Aamod answer above, If you want to use one command line to compile and run your code, you can use the following:
Windows:
tsc main.ts | node main.js
Linux / macOS:
tsc main.ts && node main.js
Edit: May 2022
ts-node now has an --esm flag use it.
Old Answer:
None of the other answers discuss how to run a TypeScript script that uses modules, and especially modern ES Modules.
First off, ts-node doesn't work in that scenario, as of March 2020. So we'll settle for tsc followed by node.
Second, TypeScript still can't output .mjs files. So we'll settle for .js files and "type": "module" in package.json.
Third, you want clean import lines, without specifying the .js extension (which would be confusing in .ts files):
import { Lib } from './Lib';
Well, that's non-trivial. Node requires specifying extensions on imports, unless you use the experimental-specifier-resolution=node flag. In this case, it would enable Node to look for Lib.js or Lib/index.js when you only specify ./Lib on the import line.
Fourth, there's still a snag: if you have a different main filename than index.js in your package, Node won't find it.
Transpiling makes things a lot messier than running vanilla Node.
Here's a sample repo with a modern TypeScript project structure, generating ES Module code.
I created #digitak/esrun, a thin wrapper around esbuild and that executes a TypeScript file almost instantly. esrun was made because I was disappointed with ts-node: too slow, and just didn't work most of the time.
Advantages of esrun over ts-node include:
very fast (uses esbuild),
can import ESM as well as CJS (just use the libraries of your choice and esrun will work out of the box),
there is an included watch mode, run your script with the --watch option and any change to your entry file or any of its dependencies will re-trigger the result
you can use esrun in inspect mode to use the DevTools console instead of your terminal console.
After installing, just run:
npx #digitak/esrun file.ts
Just helpful information - here is newest TypeScript / JavaScript runtime Deno.
It was created by the creator of node Ryan Dahl, based on what he would do differently if he could start fresh.
You can also try tsx.
tsx is a CLI command (alternative to node) for seamlessly running TypeScript, its build upon esbuild so its very fast.
https://github.com/esbuild-kit/tsx
Example:
npx tsx ./script.ts
As of May 2022 ts-node does support es modules
npx ts-node --esm file.ts
you will likely need to add "type": "module", to your package.json. And some of the imports might be wonky unless you turn on experimental-specifier-resolution=node
npmjs.com/package/ts-node#commonjs-vs-native-ecmascript-modules
For linux / mac you can add the ts-node-script shebang.
Install typescript / ts-node globally (see 1 below for non global install):
npm install ts-node typescript --save-dev --global
Add this as the first line in your .ts file:
#!/usr/bin/env ts-node-script
Then make the file executable:
$ chmod +x ./your-file.ts
You can then run the file directly from the command line:
$ ./your-file.ts
Notes:
1 For non global install you can install local to your project
npm install ts-node typescript --save-dev
and add the relative path to the shebang script eg:
#!/usr/bin/env ./node_modules/.bin/ts-node-script
2 Support for shebangs was officially added in ts-node v8.9.0.
Like Zeeshan Ahmad's answer, I also think ts-node is the way to go. I would also add a shebang and make it executable, so you can just run it directly.
Install typescript and ts-node globally:
npm install -g ts-node typescript
or
yarn global add ts-node typescript
Create a file hello with this content:
#!/usr/bin/env ts-node-script
import * as os from 'os'
function hello(name: string) {
return 'Hello, ' + name
}
const user = os.userInfo().username
console.log(`Result: ${hello(user)}`)
As you can see, line one has the shebang for ts-node
Run directly by just executing the file
$ ./hello
Result: Hello, root
Some notes:
This does not seem to work with ES modules, as Dan Dascalescu has pointed out.
See this issue discussing the best way to make a command line script with package linking, provided by Kaspar Etter. I have improved the shebang accordingly
Update 2020-04-06: Some changes after great input in the comments: Update shebang to use ts-node-script instead of ts-node, link to issues in ts-node.
Write yourself a simple bash wrapper may helps.
#!/bin/bash
npx tsc $1 && node ${1%%.ts}
For environments such as Webstorm where the node command cannot be changed to ts-node or npx:
npm install ts-node typescript (Install dependencies)
node --require ts-node/register src/foo.ts (Add --require ts-node/register to "Node parameters")
This answer may be premature, but deno supports running both TS and JS out of the box.
Based on your development environment, moving to Deno (and learning about it) might be too much, but hopefully this answer helps someone in the future.
Just in case anyone is insane like me and wants to just run typescript script as though it was a .js script, you can try this. I've written a hacky script that appears to execute the .ts script using node.
#!/usr/bin/env bash
NODEPATH="$HOME/.nvm/versions/node/v8.11.3/bin" # set path to your node/tsc
export TSC="$NODEPATH/tsc"
export NODE="$NODEPATH/node"
TSCFILE=$1 # only parameter is the name of the ts file you created.
function show_usage() {
echo "ts2node [ts file]"
exit 0
}
if [ "$TSCFILE" == "" ]
then
show_usage;
fi
JSFILE="$(echo $TSCFILE|cut -d"." -f 1).js"
$TSC $TSCFILE && $NODE $JSFILE
You can do this or write your own but essentially, it creates the .js file and then uses node to run it like so:
# tsrun myscript.ts
Simple. Just make sure your script only has one "." else you'll need to change your JSFILE in a different way than what I've shown.
Install ts-node node module globally.
Create node runtime configuration (for IDE) or use node in command line to run below file js file (The path is for windows, but you can do it for linux as well)
~\AppData\Roaming\npm\node_modules\ts-node\dist\bin.js
Give your ts file path as a command line argument.
Run Or Debug as you like.
Create your TypeScript file (ex. app.ts)
npm i -D typescript ts-node -> to install the dev dependencies local
npx nodemon app.ts
Using nodemon, automatically recompile app.ts every time you change the file
Here is the command
tsc index.ts --outDir .temp && node .temp/index.js && rm -rf .temp
<<<<<<<<< Compile >>>>>>>>> <<<<<<< Run >>>>>>> << Clean >>
There is also an option to run code directly from the CLI, not the *.ts file itself.
It's perfectly described in the ts-node manual.
As a first step, install ts-node globally via npm, yarn, or whatever you like.
...and now just use ts-node -e 'console.log("Hello, world!")' (you may also add the -p flag for printing code)
This little command is perfect for checking, does everything installed fine. And for finding some other error, relevant with tsconfig.json options.
We can run it using nodemon as well
nodemon ./filepath/filename.ts
This question was posted in 2015. In 2018, node recognizes both .js and .ts. So, running node file.ts will also run.

Resources