A modern Javascript project setup

Paolo Savoldi
Netscape
Published in
10 min readAug 2, 2016

As a Web developer, you know that things are evolving fast. Especially JavaScript development dramatically changed in the past few years. A bunch of new tools and best practices are available today to create and maintain code.

In this article I will show my personal way to setup and maintain a generic JavaScript project. In detail, I will talk about GitHub, NodeJs, Webpack, Babel and the new ES6/ES2015 JavaScript syntax.

GitHub

Are you a Git-Hubber?

GitHub is an amazing way to maintain and share your code among colleagues but, also, among yourself when you’re coding from different locations.

If you don’t know Git/GitHub, this article covers only the essentials aspects with no detailed description on how and why Git/GitHub works. I’m not a Git advanced user, but I find it really simple.

So, why GitHub?

  • To have an online repository for your source code.
  • To share the same source code between different locations and/or collaborators. You have immediate access to your code everywhere.
  • To keep track of your bugs. Among other things, GitHub features an issues tracking section.
  • To keep track of every single change for every file. Git is primarily a version control software.

NodeJS

Server-side JavaScript? WHAT?!

Simply put, with NodeJS you may execute Javascript code on your machine — without a browser. You can run JavaScript code through the command-line in a shell environment.

So, why NodeJS?

We’ll not directly run JavaScript code using NodeJS, but we’ll take advantage of the environment to be able to launch other tools. In detail:

  • We’ll use the NodeJS package manager, named NPM. With it, we’ll be able to download useful javaScript libraries using the command line.
  • We’ll also use NPM to manage the entire project. Keep reading for details.

BabelJS

JavaScript evolved

I will not run into a discussion about what and why the other name of JavaScript is ECMAScript.

You should just be aware that JavaScript has a new syntax and new interesting features. This new language is called ES6, or ES2015. For details, query the excellent StackOverflow site.

The interesting parts are:

  • a new way to define classes, much more C++/Java/PHP like.
  • the possibility to subdivide JavaScript code (functions, classes) into external modules and import them.
  • an alternative, less verbose, syntax to define functions.

Bad news: at present time, browsers do not (or partially) understand the new language. This is where Babel comes to help. “Babel transforms your JavaScript”. From the new ES6 Syntax to the plain old “standard” JavaScript, ready to be executed by actual browsers.

Why Babel?

Of course it is not mandatory to use ES6 Syntax today. But it would be a good idea to do so because:

  • imports are really useful and simplify code organization.
  • obvious advantages derived by the new syntax specs. The code will be clearer and easier to follow.
  • if you want to create applications with ReactJS, there’s plenty of example projects and tutorials out there, coded in ES6. Being unaware of the new syntax will make you unable to understand the code.
  • it will be the main language on the web for the next years. You will be ready when the revolution comes!

Webpack

Bundling?!

Even a small/medium sized project may have a number of .js source files. They are normally included in your web page, and you have to keep track of the dependencies manually:

<script src="jquery.js"></script>
<script src="awesome_lib_that_uses_jquery.js></script>
<script src="awesome_lib_that_uses_awesome_lib_that_uses_jquery.js>
...

Why not have a way to bundle them in a single .js file? Doing so, we would have the following advantages:

  • An unique http request issued by the browser, as we’ll load a single file containing all the code.
  • No more worries about what to include first.
  • The possibility to minify the code as part of the bundling process.

Webpack does the trick. It is an advanced module bundler: it takes many JavaScript files from a directory and bundles them into one single JavaScript file.

Practice!

If you agree to use such tools and you’re not afraid of new adventures, we can go on the practical.

Preparing you PC

  1. Install NodeJS. See the NodeJS website for details.
  2. Install Git on your machine. I’m using windows, so I installed the Git for Windows that comes with a nice Git Bash in which I can issue Linux commands.

Setup the project

  1. Create a GitHub account and add a new empty repo.
  2. CD into your projects root and clone the online repo. You will have to setup an SSH key, maintaining the private key on your machine and the public key added to your GitHub account.
git clone git@github.com:<your_github_account>/<your_repo>

This will create a new folder in your projects root. CD into that folder.

3. Initialize the project using NPM.

npm init -y

The -y option stands for not asking a confirm everytime. As a result of this action, a package.json file is created. It contains the project configuration. It is useful for two main reasons:

  • it keeps track of the libraries used by the project.
  • it allows to define a command to be launched every time we need to build the project and create the bundle.

4. Install Webpack

npm install --save-dev webpack

That’s it! A “node_modules” folder will be created. It will contain a number of subdirectories that will be automatically added by npm when you install new packages. The save-dev option is for adding webpack in the package.json file.

You will notice that package.json has been automatically updated by npm and now contains “webpack” in the “devDependencies” section.

5. Configure Webpack

The webpack configuration is done in the webpack.config.js file:

module.exports = {
entry: './src/index.js',
output: {
path: './build',
filename: 'bundle.js'
}
};

Note: if you experience troubles with the previous configuration about the “path” value, please see this comment https://medium.com/@kaleemkhan/date-18th-july-2017-6d70bdc4d1c8

This should be quite clear. It tells where to find the project entry-point, and where to place the output.

6. Install Babel

We’ll not launch Babel directly. Since we’re using webpack for bundling, we’ll use Babel with it to automatically translate (transpile) the source files before bundling.

How to use Babel with Webpack? The official site is quite clearer:

Babel for Webpack: installation and usage
npm install --save-dev babel-loader babel-core

Then add a loader in the webpack config:

module.exports = {
entry: './src/index.js',
output: {
path: './build',
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}]
}

};

With this, every .js file encountered by Webpack will be processed by Babel first. Babel needs to be configured. We want it to translate ES6 to current JavaScript.

7. Tell Babel what to do

Babel features are packed in separate libraries named presets. To translate ES6 we need to install the following:

npm install --save-dev babel-preset-es2015

The Babel configuration is saved in the .babelrc file. Create it with the following content:

{
"presets": ["es2015"]
}

Note: if you are on Windows, you won’t be able to create a file whose name begins with a full stop. You can create the file using the Git Bash, sending the “touch .babelrc” command.

8. Install jQuery

No more need to download the jQuery code and manually place in your project folder. Just give

npm install --save jquery

and the jQuery library is available for import.

import $ from 'jquery'

jQuery was saved in the “dependencies” section, because it’s a library used by the runtime code. The other libraries installed so far, instead, need to be used to build the project. Again, query StackOverflow for details.

When you need a library, you should check the corresponding npm page (for jQuery: https://www.npmjs.com/package/jquery). It contains useful information about installation and usage in the Node environment.

The jQuery npm page.

9. Write some code

I wrote a little class that displays a simple currency converter. It’s a basic example on how to define and use a class in ES6.

Converter.js

import $ from 'jquery';export default class {

constructor(rootElement, eur_usd_coeff) {
this.rootElement = rootElement;
this.eur_usd_coeff = eur_usd_coeff;
this.EUR = 0;
this.USD = 0;
}

render() {
// detach event listeners
$('button').off('click');

// define html
let html = `
<table>
<tr>
<td>EUR</td>
<td>&nbsp;</td>
<td>USD</td>
</tr>
<tr>
<td><input id="EUR" value="${this.EUR}"/></td>
<td>
<button id="convertEURtoUSD">>>></button><br>
<button id="convertUSDtoEUR"><<<</button>
</td>
<td><input id="USD" value="${this.USD}" /></td>
</tr>
</table>
`;

rootElement.innerHTML = html;

// attach event listeners
$('#convertEURtoUSD').on('click', function() {
this.convertEURtoUSD()
});
$('#convertUSDtoEUR').on('click', () => {
this.convertUSDtoEUR()
});
}

convertEURtoUSD() {
this.EUR = $('#EUR').val();
this.USD = this.EUR * this.eur_usd_coeff;
this.render();
}

convertUSDtoEUR() {
this.USD = $('#USD').val();
this.EUR = this.USD / this.eur_usd_coeff;
this.render();
}

};

index.js

import Converter from './Converter';const rootElement = document.getElementById('rootElement');
var conv = new Converter(rootElement, 1.11745);
conv.render();

It’s worth dwelling on a few points:

$('#convertEURtoUSD').on('click', () => { 
this.convertEURtoUSD()
});
// is exactly the same as$('#convertEURtoUSD').on('click', function() {
this.convertEURtoUSD()
}.bind(this));

This way to define functions is called “arrow functions” syntax. Arrow functions have an additional advantage: they automatically binds the current main object. This topic would deserve an entire article to be well explained, but I think a little practice is better. Try to “console.log(this)” inside the arrow function and see what “this” is with/without the .bind.
For details, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

10. Build

We’re close to the objective. We’re just one step far from the bundle.js. Configure the package.json “build” script to run webpack:

...
"scripts": {
"build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
...

To buil the project now you can simply run:

npm run build

That’s it. You will find the bundle.js in the “/build” folder.

11. Run in the browser

In the “/build” folder create a simple html page:

<!doctype html>
<html>
<head>
</head>
<body>
<div id="rootElement"></div>

<script src="bundle.js"></script>
</body>
</html>

As you can see, it provides the root element for the application and loads the bundle.js file.

I launch the file on my machine pointing at localhost, since I have a Wamp server running.

12. Git push

It’s time to push our code in the online repository!

Note that the “node_modules” directory contains a huge number of elements downloaded automatically by the npm utility. They should not be saved in the source code repository, since all dependencies are tracked in package.json and could be downloaded when needed by typing:

npm install

bundle.js should not be part of the repository too, as it’s the result of the “webpacking” process and it’s not source code at all — see it as the compiled code.

To exclude such elements, add them in the .gitignore file:

node_modules
bundle.js

We are ready. To save the code in the online repository, I follow the steps:

git status

to see the new or modified files.

git add .

to include them in the next commit.

git commit -m "first commit"

to commit them.

At this point, the changes are saved in your local Git repository. To push them online, type

git push

Visit your online GitHub repo and see the code you just pushed. Cool.

13. Clone your repo to work from another machine

When you’re working on a different machine, you may want to download the source code from the online repo. The first time you need to clone the repo:

git clone git@github.com:<your_github_account>/<your_repo>

Since the ”/node_modules” directory was not uploaded in the repo, we need to install the required packages (dependencies). This is where the package.json come in help: instead of installing every package, just give

npm install

and wait for the magic.

Since the “bundle.js” file was not uploaded in the repo, we need to build the project to produce it. It’s quite straightforward:

npm run build

and, again, remember to thank the “package.json” file.

14. commit new changes

You may want to work and modify the code. Just act like before. A quick recap:

git status
git add .
git commit -m "second commit"
git push

When working in team, you should give a “git pull” command right before the “git push”. This is to download the latest version of the code that may be changed. This could lead to manually merge the code, but this is another topic. See the GitHub pages for details: https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line/.

The code is updated online. Cool.

15. Download the latest code version

You may want to download the updated code from the first machine: since the local repo exists yet, you won’t clone it again. Just cd into the project folder and give

git pull

to update the files.

Conclusion

See my github repo containing the project here. You may clone it and use as a starting point for your next project.

The code in the repo has a little bug. Are you able to find and correct it?

Please notice me about any error or any part you may find obscure. I tried to be as clear as possible.

References

GitHub
https://github.com/

The complete code used in this article
https://github.com/paooolino/modern-javascript-setup

How to create a SSH key and save it to your GitHub account
https://help.github.com/articles/generating-an-ssh-key/

Babel
https://babeljs.io/

How to setup Babel for various tools
https://babeljs.io/docs/setup/

Webpack
https://webpack.github.io/

NodeJS
https://nodejs.org/en/

Npm
https://www.npmjs.com/

jQuery npm repository page
https://www.npmjs.com/package/jquery

ES6 features
http://es6-features.org/

Follow-up

See the next article: A simple React project setup for rapid application prototyping

Edit

September 9, 2016

Due to some feedback from the excellent subreddit r/javascript, I updated the code in the “render” function to use the ES6 template literals.

July 28, 2017

Added a note about the Webpack config path value thans to @kaleemkhan

Follow me on Twitter

https://twitter.com/paooolino

--

--

Paolo Savoldi
Netscape

Passionate web programmer. I like to keep things simple.