DEV Community

loading...
Cover image for Getting On with ES6 & NodeJS & eslint (without Babel !)

Getting On with ES6 & NodeJS & eslint (without Babel !)

tusharpandey13 profile image Tushar Pandey ・4 min read

Intro

So, I'm making a Node - Express - Mongo server boilerplate to get the hang of it and I found out that Node now has support for es6 modules by default! :)

This post will go through the process of creating one such project with es6 support, eslint configuration and some hacks :P

Note:

This tutorial involves setting the --es-module-specifier-resolution=node\" flag in the command line of node, which is an experimental flag. This is the 'hack' mentioned above. This is done in order to omit the '.js' file extension while importing modules. However, if you are uncomfortable with experimental tags, you could either use '.js' extensions everywhere in the code or use Babel.

ES6 ?

Having support for es6 modules means that you could do the following:

import Stuff, {some, other, stuff} from 'some/library';
export thing;
export default anotherThing;

This breaks the monotony of require() and IMO, this is a much cleaner syntax. Earlier, if you wanted to do this, you had to

  1. use TS (which although can be a good thing, adds an extra 'build' step before execution and while this pattern might suffice for frontend development, it's a completely show-killer for me.)
  2. use the Babel library that 'transpiles' your es6 code to it's equivalent commonJS code.

Note that although these statements are supported, currently they map to their require() and module.exports equivalents in node, so doing essentially the same thing as Babel, but with no extra dependencies.
Also, using import and export is the correct way forward, because at some point of time in future, node is going to adopt this way of using modules and not completely relying on require().

Also, did I mention that using import and exports is faster than require() ? :)

Let's start the code now.

Project Setup

Note

This tutorial will guide you in making a simple, barebones node app with es6 support. I will not be including any other stuff like express, extra dependencies etc. for the sake of simplicity.

Do a npm init to get the basic package.json:

{
  "name": "es6-api",
  "version": "1.0.0",
  "description": "es6-api",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "es6",
    "api"
  ],
  "author": "",
  "license": "ISC"
}

Now, we need to add a few things to package.json:

  • To add support for ES6 modules, add the line "type": "module" to your package.json.
  • Add a "dev" script in the "scripts" property like: "dev":"node --es-module-specifier-resolution=node src/index.js"
  • Change "main": "index.js", to "main": "src/index.js", make a folder src and touch a file index.js in it.

Your package.json should look like this now:

Alt Text

Run npm install eslint && npx eslint --init in the root dir (where package.json is stored) to setup eslint.

Answer all the questions according to your choice. Make sure to set the option 'What type of modules does your project use?' to 'esm'. These were my choices, but yours might differ:

Alt Text

It will write the config to .eslintrc.json in the root dir and install a local copy of eslint in the node_modules directory.

Open .eslintrc.json and you should see the config similar to this:

Alt Text

Now here, we need to make some changes to make eslint work with our esm setup.

First, add the line "es6": true to the "env" porperty value. Then, make a new property called "globals" and add the following line in it's value: "__dirname": true. This we'll come to this later in the code.

The config should look like this now:

Alt Text

Now that eslint is setup, we can go ahead and edit the src/index.js file. Add the following code to it:

// src/index.js

import path from 'path';

global.__dirname = path.resolve('./');
console.log(__dirname);

This code will do 2 things:

  1. Verify that we can in fact, use import statement.
  2. In node with esm, variables like __dirname which are normally availabe in the global scope, are undefined. These 2 statements make it available in the global scope again. Notice that we also added the line "__dirname": true in .eslintrc.json. Without that, eslint will give an error saying that __dirname is not defined.

Now that our starter code is ready, return to the root dir and run npm run dev. You should get the following output:

Alt Text

Exporting stuff

Let's look into making our own modules and exporting stuff.

Start by making a directory example in the src directory. Touch a file index.js inside it and add the following code:

const value1 = 99;
const value2 = 100;

export { value2 };
export default value1;

We're making a module here and exporting value1 as a default export and value2 as a named export. We will also import these values in the main index.js.

Replace the code of src/index.js by:

import path from 'path';
import value1, { value2 } from './example';

global.__dirname = path.resolve('./');
console.log(value1, value2);

By now, your project should like this:

Alt Text

Run npm run dev and you should see

> es6-api@1.0.0 dev /home/tushar/src/tmp/tut/es6-api
> node --es-module-specifier-resolution=node src/index.js

99 100

That confirms that our es6 module was loaded successfully in node without using babel!.

Footnotes

You can go wild with esm by using await import(...), module-aliases, importing commonJS modules and much more, but I think that would be out of the scope of this article.

Also note that since import as of now is identical to require(), you can basically load data from a JSON file by writing await import('file.json').

If you liked this tutorial or have some suggestions, please drop a comment below. Thank you for reading. Bye and have a nice day.

Discussion (2)

pic
Editor guide
Collapse
bronhy profile image
bronhy • Edited

Nice article, thank you for the post.

You could add an update to the post. Now in 2021 we do not need es6 and globals lines in the .eslintrc.json.

eslint.org/docs/user-guide/configu... - es2021 - adds all ECMAScript 2021 globals and automatically sets the ecmaVersion parser option to 12.

Collapse
synox profile image
Aravindo Wingeier • Edited

Thanks, that is very useful. I am missing the package.json entry to run eslint, and also I would call the script "start" and not "dev".

PS: for beginners it would recommend using XO github.com/xojs/xo instead of using eslint directly.