Leaflet with browserify: basic tutorial

This post will will show you how to build a very simple application that uses leaflet js with browserify.
http://browserify.org/

why do you want to do that?

Browserify will let us use node modules on the browser side (and there is like 255000 total packages to choose on npm) , on NPM you will find lot’s of client-side packages like JQuery, and of course, our one and only LeafletJS. Also, it let you separate your own code on modules, making it more easy to maintain especially when you end up with a very large JavaScript project.

And what will you do with all those modules?, browserify will recursively analyse all the require() calls in your app to build a unique bundle file that you can serve up to the browser in a single <script> tag. We’ll see that later.

let’s get started

First thing is to have node installed. Then you will create a new folder with the name of your project and in that folder open a terminal an type:

 $ npm init

This will ask you a bunch of questions, and then write a package.json for you.

Then we add browserify to our project by typing on the terminal:

 $ npm install browserify --save-dev

Note:

you need broserify installed also globally in order to use it from the terminal or on scripts.
 $ npm install -g browserify 

We’ll also add leaflet and JQuery (the –save flag will automatically update our package.json file)

$ npm install leaflet --save
$ npm install jquery --save

Now we will create the main JavaScript file called app.js :


// require modules
var L = require('leaflet');
var $ = require('jquery');
// Create the map
var map = L.map('map').setView([41.3921, 2.1705], 13);

// Indicate leaflet the specific location of the images folder that it needs to render the page
L.Icon.Default.imagePath = 'lib/leaflet/images/';

// Use OpenStreetMap tiles and attribution
var osmTiles = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var attribution = '© OpenStreetMap contributors';

// Create the basemap and add it to the map
L.tileLayer(osmTiles, {
    maxZoom: 18,
    attribution: attribution
}).addTo(map);

// Add some geojson from this URL
var geojsonURL = 'http://mappingandco.github.io/geojsonDB/barcelona/neighbourhoods.geojson'

$.getJSON(geojsonURL, function(neighbourhoods) {
    L.geoJson(neighbourhoods, {
        onEachFeature: function (feature, layer) {
            layer.bindPopup(feature.properties.NBarri);
        }
    }).addTo(map);
});

On app.js file what we do is require the modules that we are going to use, and then use the L and $ variables like we usually do to create a map. We also will add some geojson file with an AJAX call using the  $.getJSON method from jQuery. After we have our app.js ready we create the bundle that will unify all this code. To do that we add a new line on our package.json to write the browserify bundle to a file called bundle.js on a script:

"scripts": { 
     "build": "browserify app.js -o bundle.js"
}

With that script each time you run this:

$ npm run build

browserify will compile app.js code into bundle.js file. In our index.html we just need to add one file into the scripts, no need to add leaflet.js, jquery.js and app.js because all are compiled into bundle.js

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Leaflet with browserify template</title>
    <link rel="stylesheet" href="lib/leaflet/leaflet.css">
    <link rel="stylesheet" href="dist/css/style.css">
</head>
<body>
    <div id="map"></div>
    <script src="bundle.js" charset="utf-8"></script>
</body>
</html>

You may have noticed that I have included and independent leaflet.css file. There are two ways of doing that, you can include the node_modules folder when you upload this application to the server and simply use the css from there:

<link rel="stylesheet" href="node_modules/leaflet/dist/leaflet.css" />

and on main.js file you fix the path to the images folder:

L.Icon.Default.imagePath = 'node_modules/leaflet/dist/images/'

Or, and I think this is a better solution, not include the node_modules folder (if you are using git you just include it on the .gitignore file) and create a  leaflet folder with the leaflet.css and the images folder.

The general style for our app will be on the style.css file:

body, html { margin:0; padding:0; height:100%; }
#map { height:100%; }

If you don’t want to run $ npm run build every time you do some change on the code, there is another module that will automatically do the save part for you, is called watchify

# install it via npm
$ npm install watchify --save-dev

Add a new script to your package.json so it look like this:

"scripts": { 
     "build": "browserify app.js -o bundle.js",
     "watch": "watchify app.js -o bundle.js"
}

When you run this it will create the bundle.js, same as browserify, but it will recompile the bundle every time you save the app.js file, and that will make your like more easier.

$ npm run watch

 

what about leaflet plugins?

You can also load leaflet plugins with npm, let’s add leaflet hash.

$ npm install leaflet-hash --save

On app.js

// require the module 
require('leaflet-hash');

// add the hash
var hash = new L.Hash(map);

This time we don’t assign this module to any variable because leaflet plugins use the global L variable.

creating our own module

We said that one of the advantages of using browserify was adding modularity to our code, we create modules that are more easy to maintain and that can be reused in different projects. Let’s create a module that will add a marker to our map. We will put it on a folder called ./my_modules and we will call it marker.js

/* ./my_modules/marker.js. */
var L = require('leaflet');

var bcnMarker = L.marker([41.3921, 2.1705]).bindPopup('Barcelona.<br> Come to visit :) ');

module.exports = bcnMarker;

What we do in this module is create a marker called bcnMarker and export it by assigning onto module.exports. Then, in app.js we can require that module that we have just created same way that we did before. The only difference is that for loading local modules we need to add the ./  indicating that is a local path:

// require modules
var $ = require('jquery');
var L = require('leaflet');

require('leaflet-hash');

// here we add our module
var bcnmarker = require('./my_modules/marker');

And then you can use bcnMarker anywhere on the code

bcnmarker.addTo(map).openPopup();

Now you have you first leaflet project with broserify. If you want a quick setup you can use this package.json

With this file if you run $ npm install, it will install automatically leaflet, browserify, jquery and leaflet-hash at once.

You can check the complete example on github.

Sources: