Blog | CoWhite Softwarehttp://django.cowhite.com/blog/2017-07-10T13:29:06+00:00BlogManaging front-end javascript dependencies using Node Package Manager and bower2017-07-10T13:29:06+00:00ravi/blog/author/ravi/http://django.cowhite.com/blog/managing-front-end-javascript-dependencies-using-npm/<p>Maintaining the dependencies of libraries and packages can be cumbersome in the modern development environment if not handled carefully. It is impractical to include the external packages in code management systems. Dependencies can make setting up of new development environment a pain and deployment even harder.</p>
<h3>Node Package Manager</h3>
<p>Let us take a look at how to properly handle node dependencies with <a href="https://www.npmjs.com/" target="_blank">node package manager</a>. Node package manager is the largest software registry and hosts libraries for node. If you have already installed nodejs, you have already installed npm (node package manager). If you are on Ubuntu you can install node with</p>
<div class="codehilite"><pre>curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
</pre></div>
<p>If you are using any other operating systems use the appropriate installer from the <a href="https://nodejs.org/en/download/" targe="_blank">official download page</a>. You should be able to check if the installation is done properly by checking version numbers as follows.</p>
<div class="codehilite"><pre>ravi@ubuntu:~$ node --version
v6.11.0
ravi@ubuntu:~$ npm --version
3.10.10
</pre></div>
<p>Change to your project directory and issue the command</p>
<div class="codehilite"><pre>npm init
</pre></div>
<p>This will initialise a node project. It asks you a series of questions about the project you are going to build. Answer the questions (you can skip them by pressing enter, npm takes default answers) and get done with it, you now have a node project directory. The output looks something like this. </p>
<div class="codehilite"><pre> <span class="nx">This</span> <span class="nx">utility</span> <span class="nx">will</span> <span class="nx">walk</span> <span class="nx">you</span> <span class="nx">through</span> <span class="nx">creating</span> <span class="nx">a</span> <span class="nx">package.json</span> <span class="nx">file.</span>
<span class="nx">It</span> <span class="nx">only</span> <span class="nx">covers</span> <span class="nx">the</span> <span class="nx">most</span> <span class="nx">common</span> <span class="nx">items</span><span class="p">,</span> <span class="ow">and</span> <span class="nx">tries</span> <span class="k">to</span> <span class="nx">guess</span> <span class="nx">sensible</span> <span class="nx">defaults.</span>
<span class="nx">See</span> <span class="sb">`npm help json`</span> <span class="nx">for</span> <span class="nx">definitive</span> <span class="nx">documentation</span> <span class="k">on</span> <span class="nx">these</span> <span class="nx">fields</span>
<span class="ow">and</span> <span class="nx">exactly</span> <span class="nx">what</span> <span class="nx">they</span> <span class="k">do</span><span class="nx">.</span>
<span class="nx">Use</span> <span class="sb">`npm install <pkg> --save`</span> <span class="nx">afterwards</span> <span class="k">to</span> <span class="nx">install</span> <span class="nx">a</span> <span class="nx">package</span> <span class="ow">and</span>
<span class="nx">save</span> <span class="nx">it</span> <span class="nx">as</span> <span class="nx">a</span> <span class="n">dependency</span> <span class="k">in</span> <span class="nx">the</span> <span class="nx">package.json</span> <span class="nx">file.</span>
<span class="nx">Press</span> <span class="p">^</span><span class="nx">C</span> <span class="nx">at</span> <span class="nb">any</span> <span class="nx">time</span> <span class="k">to</span> <span class="nx">quit.</span>
<span class="nx">name</span><span class="p">:</span> <span class="p">(</span><span class="nx">frontend</span><span class="p">)</span>
<span class="nx">version</span><span class="p">:</span> <span class="p">(</span><span class="mf">1.0.0</span><span class="p">)</span>
<span class="nx">description</span><span class="p">:</span>
<span class="nx">entry</span> <span class="nx">point</span><span class="p">:</span> <span class="p">(</span><span class="nx">index.js</span><span class="p">)</span>
<span class="nx">test</span> <span class="nx">command</span><span class="p">:</span>
<span class="nx">git</span> <span class="nx">repository</span><span class="p">:</span>
<span class="nx">keywords</span><span class="p">:</span>
<span class="nx">author</span><span class="p">:</span>
<span class="nx">license</span><span class="p">:</span> <span class="p">(</span><span class="nx">ISC</span><span class="p">)</span>
<span class="nx">About</span> <span class="k">to</span> <span class="nx">write</span> <span class="k">to</span> <span class="p">/</span><span class="nx">home</span><span class="p">/</span><span class="nx">ravi</span><span class="p">/</span><span class="nx">cowhite</span><span class="p">/</span><span class="nx">blogtests</span><span class="p">/</span><span class="nx">frontend</span><span class="p">/</span><span class="nx">package.json</span><span class="p">:</span>
<span class="p">{</span>
<span class="s2">"name"</span><span class="p">:</span> <span class="s2">"frontend"</span><span class="p">,</span>
<span class="s2">"version"</span><span class="p">:</span> <span class="s2">"1.0.0"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="p">:</span> <span class="s2">""</span><span class="p">,</span>
<span class="s2">"main"</span><span class="p">:</span> <span class="s2">"index.js"</span><span class="p">,</span>
<span class="s2">"scripts"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"test"</span><span class="p">:</span> <span class="s2">"echo </span><span class="se">\"</span><span class="s2">Error: no test specified</span><span class="se">\"</span><span class="s2"> && exit 1"</span>
<span class="p">},</span>
<span class="s2">"author"</span><span class="p">:</span> <span class="s2">""</span><span class="p">,</span>
<span class="s2">"license"</span><span class="p">:</span> <span class="s2">"ISC"</span>
<span class="p">}</span>
<span class="nx">Is</span> <span class="nx">this</span> <span class="nx">ok</span><span class="o">?</span> <span class="p">(</span><span class="nx">yes</span><span class="p">)</span>
</pre></div>
<p>You should be seeing a new <code>package.json</code> file in your working directory. This file contains the whole information about the project.</p>
<p>The next step is to install packages that your project needs. The syntax of the command to install a package is </p>
<div class="codehilite"><pre><span class="nx">npm</span> <span class="nx">install</span> <span class="o"><</span><span class="nx">package_name</span><span class="o">></span>
</pre></div>
<p>This command will install the package only for the current project and the package will not be accessible from other locations. To install a node package globally - that can be accessed from any location - use the <em>global</em>. The syntax will be</p>
<div class="codehilite"><pre><span class="nx">npm</span> <span class="nx">install</span> <span class="na">-g</span> <span class="o"><</span><span class="nx">package_name</span><span class="o">></span>
</pre></div>
<p>Go ahead and install a node package called <code>node-sass</code> with</p>
<div class="codehilite"><pre>npm install node-sass
</pre></div>
<p>You will see that npm has created a <code>node_modules</code> directory. All the packages for the project are installed into this directory. That is good. But how do we manage dependencies with npm? We need to use the --save flag while installing a package. Now try this.</p>
<div class="codehilite"><pre>npm install --save node-sass
</pre></div>
<p>And look into the <code>pacakage.json</code> file. We can find that the package that we have just installed, <code>node-sass</code> is listed as a dependency, along with its version number.</p>
<div class="codehilite"><pre>{
"name": "frontend",
"version": "1.0.0",
"description": "A test of management capabilities of npm",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"node-sass": "^4.5.3"
}
}
</pre></div>
<p>Make sure that this <code>package.json</code> file is included in the version control system and is distributed along with the source code of project. To install dependencies in a new environment use the command</p>
<div class="codehilite"><pre>npm install
</pre></div>
<p>This will install all the dependencies of the project in a go. We can automate installation of dependencies in a server environment with this.
<br>
It is also possible that you require some packages only in development environment. For example, <code>node-jslint</code> is a package that checks the syntax of javascript code. It is not useful in the production environment, but is only needed for development. Such packages can be installed with the flag --save-dev as follows.</p>
<div class="codehilite"><pre>npm install --save-dev node-jslint
</pre></div>
<p>When we install a package with this flag, the y are listed in package.json as a development dependency. The package.json file will now look like this.</p>
<div class="codehilite"><pre>{
"name": "frontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"node-sass": "^4.5.3"
},
"devDependencies": {
"node-jslint": "^0.1.1"
}
}
</pre></div>
<p>In the server install only the production dependencies with</p>
<div class="codehilite"><pre>npm install --only=prod
</pre></div>
<p>Similarly, we can use <code>npm install --only=dev</code> to install only development dependencies.</p>
<h3>Bower</h3>
<p>While npm is a package manager for node libraries, <a href="https://bower.io/" target="_blank">bower</a> is a package manager for javascript libraries and is mainly useful for managing front-end components like html, js, css. To be honest we do not anymore need bower in modern applications and npm serve our purposes, because almost all popular packages/libraries have been supporting npm.</p>
<p><br></p>
<p>We need npm to install bower because bower is itself a node package. Install bower with</p>
<div class="codehilite"><pre>npm install -g bower
</pre></div>
<p>If you are on linux systems, you must run the command as a superuser.</p>
<div class="codehilite"><pre>sudo npm install -g bower
</pre></div>
<p>The flag <code>-g</code> specifies that the package will must be installed globally, so that bower is accessible from any directory.</p>
<p><br></p>
<p>Bower works just like npm, with same kind of syntax. To initialise a bower project directory use the command</p>
<div class="codehilite"><pre>bower init
</pre></div>
<p>The asks a series of questions like npm does. Answer them and confirm to initialise the project. This will create <code>bower.json</code> file that has all the information regarding the project. This is similar to <code>package.json</code> for npm.
<br>
To install a library using bower use the syntax </p>
<div class="codehilite"><pre><span class="nx">bower</span> <span class="nx">install</span> <span class="o"><</span><span class="nx">package_name</span><span class="o">></span>
</pre></div>
<p>Just like npm we can use the <code>--save</code> and <code>--save-dev</code> flags. Go ahead and install bootstrap with </p>
<div class="codehilite"><pre>bower install --save bootstrap
</pre></div>
<p>This will install bootstrap into a directory <code>bower_components</code> and the updated <code>bower.json</code> looks like</p>
<div class="codehilite"><pre>{
"name": "frontend",
"authors": [
"Ravi Teja P <rvteja92@gmail.com>"
],
"description": "",
"main": "",
"license": "MIT",
"homepage": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"bootstrap": "^3.3.7"
}
}
</pre></div>
<p>To install dependencies already listed in <code>bower.json</code> run</p>
<div class="codehilite"><pre>bower install
</pre></div>
<p>To install only production dependencies use the flag <code>--production</code> or <code>-p</code>.</p>
<div class="codehilite"><pre>bower install --production
</pre></div>
<p>Make sure that <code>bower.json</code> and <code>package.json</code> files are saved along with the other code into your version control systems and do not include <code>node_modules</code> or <code>bower_components</code> directories.</p>