<commit_before>title: npm based front-end workflow
date: 2015-09-17 13:30:00
description: A tutorial on how to use npm to easily manage your front-end dependencies and compile your assets
category: tutorials
author: <NAME>
---

Long gone are the days where developers used to download dependencies manually, place them in their project folder, and include them in their web page using multiple **script** and **link** tags. The fast evolution of web development gave birth to a wide variety of tools that help developers speed up their workflow, write clean code, automate repetitive tasks, and maintain maximum performance.

A modern front-end workflow would be as follows:

* Using {% link Bower http://bower.io/ true %} to easily manage the packages your project depends on.
* Using CSS and JS preprocessors for code modularity and simplicity, for example {% link Less http://lesscss.org/ true %} and {% link CoffeeScript http://coffeescript.org/ true %}.
* Using a task runner, {% link Gulp http://gulpjs.com/ true %} or {% link Grunt http://gruntjs.com/ true %}, to automate assets compilation and minification.

This was my personal setup a while ago before changing some parts recently.

As you probably know, {% link npm https://www.npmjs.com/ true %} is the larget ecosystem of open source libraries in the world. And alongside being a powerful package manager, npm can also be used as a simple script runner, which we can benefit from to avoid the need of any other task runners. Furthermore, many people mistake npm as being a package manager for back-end libraries only, or as being the "Node Package Manager", that's totally wrong! npm contains all open source libraries related to HTML, CSS, and JavaScript. You can read more about that in this {% link post http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging true %} from npm's blog.

With that being said, It's clear now that you don't really need all the tools I stated above to manage your front-end project, you can literally use npm to do everything and that's what we will do now! We'll create a simple website by managing everything using npm!

## The setup

The first step to start building our website is, of course, to create a folder where we will put everything, then we will use **npm init** to set it up:

{% codeblock lang:bash %}
$ mkdir Lab/website && cd Lab/website
$ npm init
{% endcodeblock %}

{% asset_img npm-init.png %}

**npm init** will take you trough some simple steps to create your **package.json** file, this is the file that will keep track of all your project's dependencies, and this is where you will also be writing the tasks you want to automate.

Let's now take care of setting up our project's structure:

{% asset_img structure.png %}

As you can see from the picture, we will have two main folders, **src** and **dist**. The first one will contain the plain source code of our website, while the second one will contain the production version with compiled and minified assets.

## HTML

The next step is to setup our **index.html** page:

{% codeblock lang:html website/src/index.html %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My website</title>
    <link rel="stylesheet" href="css/style.css" charset="utf-8">
  </head>
  <body>
    <p>Hello World!</p>
    <script src="js/bundle.js" charset="utf-8"></script>
  </body>
</html>
{% endcodeblock %}

As you might have noticed, I have put just one **link** and one **script** tags, because the idea is that all our CSS and JavaScript files will be compiled and concatenated into one single file. This will make our website renders faster because we will make less request to the server and we'll have less files to fetch!

Now is the time to minify our cool HTML page and save it to the dist folder! For this I'm going to install a package called {% link html-minifier https://www.npmjs.com/package/html-minifier true %} from npm:

{% codeblock lang:bash %}
$ npm install html-minifier --save-dev
{% endcodeblock %}

The reason I added **--save-dev** is to save the package as a development dependency in our **package.json** file, this also adds the package to the **./node_modules/.bin** folder so it can be executed using npm.

Now to minify our HTML page we should normally type the following line in the terminal:

{% codeblock lang:bash %}
$ html-minifier --collapse-whitespace ./src/index.html -o ./dist/index.html
{% endcodeblock %}

Tried it? Didn't work, right? The reason it didn't work is because we didn't install the package globally and your system doesn't know where to find **html-minifier**. We should instead add the line above to our **package.json** file as a script and run it using npm:

{% codeblock lang:javascript website/package.json %}
{
  "name": "website",
  "version": "1.0.0",
  "description": "My npm based website",
  "scripts": {
    "html": "html-minifier --collapse-whitespace ./src/index.html -o ./dist/index.html"
  },
  "author": "<NAME>",
  "devDependencies": {
    "html-minifier": "^0.7.2"
  }
}
{% endcodeblock %}

You can give your script any name you like, I chose "html" just for simplicity. We can now execute our script like this:

{% codeblock lang:bash %}
$ npm run html
{% endcodeblock %}

{% asset_img npm-run-html.png %}

You will then find your minified web page inside the **dist** folder. Minification removes all the unnecessary stuff like comments and white spaces, thus producing files with smaller size, which gives our website's loading speed an important boost.

## CSS

I'm going to use {% link Stylus https://learnboost.github.io/stylus/ true %} as my CSS preprocessor, so we'll start by installing the {% link Stylus https://www.npmjs.com/package/stylus true %} package from npm:

{% codeblock lang:bash %}
$ npm install stylus --save-dev
{% endcodeblock %}

You should always make your style files modular, which means you need to have one main file that includes styles from other files in the directory. I usually create a folder called "includes" where I put all the files that I will be including.

{% asset_img css-includes.png %}

{% codeblock lang:stylus website/src/css/includes/paragraphs.styl %}
body
  p
    color #fff
{% endcodeblock %}

{% codeblock lang:stylus website/src/css/main.styl %}
@import "includes/paragraphs"

bkgdcolor = #2481A3

body
  background bkgdcolor
{% endcodeblock %}

The next thing we should do, as you might have guessed, is to add a task to compile and minify our CSS:

{% codeblock lang:javascript website/package.json %}
...
"scripts": {
  ...
  "css": "stylus --include ./node_modules --compress ./src/css/main.styl -o ./dist/css/style.css"
},
...
{% endcodeblock %}

The last thing to do to compile your CSS is to type "**npm run css**" in your terminal, then you should able to see your compiled and minified code in the **dist** directory:

{% asset_img npm-run-css.png %}

Notice that I added "**--include ./node_modules --include-css**" to our script, the reason for this is that you might want to include CSS files from other npm packages. For example, let's say we want to add {% link Bootstrap http://getbootstrap.com/ true %} to our project:

{% codeblock lang:bash %}
$ npm install bootstrap --save
{% endcodeblock %}

This time I used **--save** instead of **--save-dev**, that's because we're not going to use Bootstrap in a npm script. npm will now take care of fetching the package with all it's dependencies (except development dependencies) and place everything in the **./node_modules** folder.

The next step is to include Bootstrap's CSS file in our **main.styl** file:

{% codeblock lang:stylus website/src/css/main.styl %}<commit_msg>Fix stylus script<commit_after>title: npm based front-end workflow
date: 2015-09-17 13:30:00
description: A tutorial on how to use npm to easily manage your front-end dependencies and compile your assets
category: tutorials
author: <NAME>
---

Long gone are the days where developers used to download dependencies manually, place them in their project folder, and include them in their web page using multiple **script** and **link** tags. The fast evolution of web development gave birth to a wide variety of tools that help developers speed up their workflow, write clean code, automate repetitive tasks, and maintain maximum performance.

A modern front-end workflow would be as follows:

* Using {% link Bower http://bower.io/ true %} to easily manage the packages your project depends on.
* Using CSS and JS preprocessors for code modularity and simplicity, for example {% link Less http://lesscss.org/ true %} and {% link CoffeeScript http://coffeescript.org/ true %}.
* Using a task runner, {% link Gulp http://gulpjs.com/ true %} or {% link Grunt http://gruntjs.com/ true %}, to automate assets compilation and minification.

This was my personal setup a while ago before changing some parts recently.

As you probably know, {% link npm https://www.npmjs.com/ true %} is the larget ecosystem of open source libraries in the world. And alongside being a powerful package manager, npm can also be used as a simple script runner, which we can benefit from to avoid the need of any other task runners. Furthermore, many people mistake npm as being a package manager for back-end libraries only, or as being the "Node Package Manager", that's totally wrong! npm contains all open source libraries related to HTML, CSS, and JavaScript. You can read more about that in this {% link post http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging true %} from npm's blog.

With that being said, It's clear now that you don't really need all the tools I stated above to manage your front-end project, you can literally use npm to do everything and that's what we will do now! We'll create a simple website by managing everything using npm!

## The setup

The first step to start building our website is, of course, to create a folder where we will put everything, then we will use **npm init** to set it up:

{% codeblock lang:bash %}
$ mkdir Lab/website && cd Lab/website
$ npm init
{% endcodeblock %}

{% asset_img npm-init.png %}

**npm init** will take you trough some simple steps to create your **package.json** file, this is the file that will keep track of all your project's dependencies, and this is where you will also be writing the tasks you want to automate.

Let's now take care of setting up our project's structure:

{% asset_img structure.png %}

As you can see from the picture, we will have two main folders, **src** and **dist**. The first one will contain the plain source code of our website, while the second one will contain the production version with compiled and minified assets.

## HTML

The next step is to setup our **index.html** page:

{% codeblock lang:html website/src/index.html %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My website</title>
    <link rel="stylesheet" href="css/style.css" charset="utf-8">
  </head>
  <body>
    <p>Hello World!</p>
    <script src="js/bundle.js" charset="utf-8"></script>
  </body>
</html>
{% endcodeblock %}

As you might have noticed, I have put just one **link** and one **script** tags, because the idea is that all our CSS and JavaScript files will be compiled and concatenated into one single file. This will make our website renders faster because we will make less request to the server and we'll have less files to fetch!

Now is the time to minify our cool HTML page and save it to the dist folder! For this I'm going to install a package called {% link html-minifier https://www.npmjs.com/package/html-minifier true %} from npm:

{% codeblock lang:bash %}
$ npm install html-minifier --save-dev
{% endcodeblock %}

The reason I added **--save-dev** is to save the package as a development dependency in our **package.json** file, this also adds the package to the **./node_modules/.bin** folder so it can be executed using npm.

Now to minify our HTML page we should normally type the following line in the terminal:

{% codeblock lang:bash %}
$ html-minifier --collapse-whitespace ./src/index.html -o ./dist/index.html
{% endcodeblock %}

Tried it? Didn't work, right? The reason it didn't work is because we didn't install the package globally and your system doesn't know where to find **html-minifier**. We should instead add the line above to our **package.json** file as a script and run it using npm:

{% codeblock lang:javascript website/package.json %}
{
  "name": "website",
  "version": "1.0.0",
  "description": "My npm based website",
  "scripts": {
    "html": "html-minifier --collapse-whitespace ./src/index.html -o ./dist/index.html"
  },
  "author": "<NAME>",
  "devDependencies": {
    "html-minifier": "^0.7.2"
  }
}
{% endcodeblock %}

You can give your script any name you like, I chose "html" just for simplicity. We can now execute our script like this:

{% codeblock lang:bash %}
$ npm run html
{% endcodeblock %}

{% asset_img npm-run-html.png %}

You will then find your minified web page inside the **dist** folder. Minification removes all the unnecessary stuff like comments and white spaces, thus producing files with smaller size, which gives our website's loading speed an important boost.

## CSS

I'm going to use {% link Stylus https://learnboost.github.io/stylus/ true %} as my CSS preprocessor, so we'll start by installing the {% link Stylus https://www.npmjs.com/package/stylus true %} package from npm:

{% codeblock lang:bash %}
$ npm install stylus --save-dev
{% endcodeblock %}

You should always make your style files modular, which means you need to have one main file that includes styles from other files in the directory. I usually create a folder called "includes" where I put all the files that I will be including.

{% asset_img css-includes.png %}

{% codeblock lang:stylus website/src/css/includes/paragraphs.styl %}
body
  p
    color #fff
{% endcodeblock %}

{% codeblock lang:stylus website/src/css/main.styl %}
@import "includes/paragraphs"

bkgdcolor = #2481A3

body
  background bkgdcolor
{% endcodeblock %}

The next thing we should do, as you might have guessed, is to add a task to compile and minify our CSS:

{% codeblock lang:javascript website/package.json %}
...
"scripts": {
  ...
  "css": "stylus --include ./node_modules --include-css --compress ./src/css/main.styl -o ./dist/css/style.css"
},
...
{% endcodeblock %}

The last thing to do to compile your CSS is to type "**npm run css**" in your terminal, then you should able to see your compiled and minified code in the **dist** directory:

{% asset_img npm-run-css.png %}

Notice that I added "**--include ./node_modules --include-css**" to our script, the reason for this is that you might want to include CSS files from other npm packages. For example, let's say we want to add {% link Bootstrap http://getbootstrap.com/ true %} to our project:

{% codeblock lang:bash %}
$ npm install bootstrap --save
{% endcodeblock %}

This time I used **--save** instead of **--save-dev**, that's because we're not going to use Bootstrap in a npm script. npm will now take care of fetching the package with all it's dependencies (except development dependencies) and place everything in the **./node_modules** folder.

The next step is to include Bootstrap's CSS file in our **main.styl** file:

{% codeblock lang:stylus website/src/css/main.styl %}
{'fraction_non_alphanumeric': 0.09765472312703583, 'fraction_numerical': 0.005211726384364821, 'mean_word_length': 4.071357779980178, 'pattern_counts': {'":': 20, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 8, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1360794', 'n_tokens_mistral': 4511, 'n_tokens_neox': 4121, 'n_words': 2125}