Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Monday, July 27, 2015

How to Use Bootstrap (CSS only) and Webpack

I thought it was going to be easy.

require("bootstrap-webpack");

I thought that with a single line of JavaScript, I could have Bootstrap available for use within my web application. However, that was not to be the case. After battling through Webpack producing errors about CSS, woff2 and various other issues, I finally reached my limit at:

Uncaught ReferenceError: jQuery is not defined

I'm sure I'm not the first person to run into this issue (a quick Google produced this solution) but what pushed me over the edge was that I only wanted Bootstrap for it's CSS; I had no need to add jQuery as I wasn't going to use any of Bootstrap's JavaScriptiness. As far as I was concerned, this was another hoop and I wasn't going to jump through it.

With invigorated motivation and a fierce sense of purpose, I set out to get Webpack running with Bootstrap's CSS and nothing more. There had to be a way where I could load bootstrap.min.css and that is what I sought out. 


From my previous attempts to use bootstrap-webpack, I felt that if I had the correct Webpack loaders installed and configured correctly, Webpack should be able to load the CSS file. After playing around with adding and removing loaders, I settled on five that appear to be the bear minimum you need:
  • babel-loader: to transpile the "require" keyword
  • css-loader & style-loader: for processing CSS
  • file-loader: for handling "eot" resources
  • url-loader: for handling woff, woff2, ttf & svg resources

I expect that as Bootstrap evolves, this set of loaders will change but as of v3.3.5, these are all you need.

webpack.config.js:

module.exports = {
    entry: {
        app: ["webpack/hot/dev-server", "./app/app.js"],
    },
    output: {    
        path: './app',
        filename: 'bundle.js'
    },
    module: {
      loaders: [
            { test: /\.jsx?$/, exclude: /(node_modules|bower_components)/, loader: 'babel' },
            { test: /\.css$/, loader: 'style-loader!css-loader' },
            { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
            { test: /\.(woff|woff2)$/, loader:"url?prefix=font/&limit=5000" },
            { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
            { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" }
      ]
    }
};

The loaders were configured as above. Most of this was extracted from the configuration for bootstrap-webpack. The only change of note was updating the test for the url-loader to match both woff and woff2.

This solution is perfect for use with an Angular application where you are using angular.ui. Adding Bootstrap's JavaScript and jQuery in this scenario would be a waste as angular.ui provides the same set of features. 


Oh, and with the Babel-loader installed, you are free to use ES6 to your heart's content!

Feel free to check out the repo on GitHub

//Code, rinse, repeat

Wednesday, March 25, 2015

How Do I Simultaneously Navigate Multiple Web Browsers?

With some JavaScript and Socket.IO!

However, before getting into that, here's a little background on why I needed to do this (feel free to scroll down if you want to jump to the code). Working as a developer, the majority of your code will be aimed at being deployed in production. By production, I mean an environment where it will be used to provide value to the organization employing you, be this a customer facing web application or a test harness that's used as part of the build process. When you are developing for a production environment, it makes sense to stay within the confines of the current tech stack that is being employed, unless it really makes sense to introduce a new element. For example, if your organization develops their web applications using only ASP.NET, it wouldn't make sense for one developer to start developing a couple new pages in PHP. Sticking to a tech stack improves maintainability tremendously, but it can also limit our ability to see beyond that technology stack. This is why I savor the opportunities to code something that won't go to production and won't need to be maintained by anyone. This gives me the freedom to choose whatever technologies I feel I can be most productive using to solve the problem at hand. It's great not to be confined to your production stack and have the opportunity to step outside of the box and try something new.

One of these opportunities presented itself when I ran into an issue where it appeared either sessions were getting mixed up or the wrong value was being used for the Set-Cookie HTTP header entry. From examining the webserver's logs and the database's audit log, it was clear that the affected parties' requests reached the webserver at exactly the same instance. This meant, that in order to attempt to reproduce this issue, I needed a way to trigger multiple browsers to navigate to the same URL at exactly the same time in order to increase the likelihood of causing an occurrence as this issue did not raise itself every time two or more requests were received simultaneously. This was the moment I had been waiting for, the moment to try something new!

I decided to use node.js as I felt that I would be able to get something up and running with minimal friction. The first solution I considered was where the browsers would repeatedly poll the server and ask if they should navigate or not. When the server said yes, each of the browsers would then navigate to the website I wanted to test. In my mind's eye, the implementation of this would be very easy for both the client and server, but something didn’t feel right about it. I ended up dismissing this approach as the accuracy of the synchronized navigation would rely solely on the shortness of the poll duration. I felt that the command to navigate should be sent from the server to all the browsers in the form of a broadcast. This led me to web sockets and ultimately Socket.IO.

The solution that I created has an index page and an admin page. When browsers load the index page, a connection is established with the web server and a message is broadcasted to the other connected browsers that one more has connected. The admin page allows messages to be sent to the connected clients and to command them to navigate to a url.

Server side

app.js:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(function () {
 'use strict';
 
 var http = require("http");
 var express = require("express");
 var app = express();
 var router = express.Router();
 
 app.use(express.static(__dirname + '/public'));
 
 router.use(function (req, res) {

  res.status(404).send("Did you get lost?");
 });

 router.use(function (err, req, res, next) {

  console.log("ERROR:");
  console.dir(err);
  
  if (req.xhr) {
   res.set('Content-Type','application/json');
   res.status(500).send({ message: "Oops, something went wrong." });
  } else {
   res.status(500).send("Oops, something went wrong.");
  }
 });

 app.use('/', router);

 var port = process.env.PORT || 3000;
 var server = http.createServer(app);
 server.listen(port);
 require('./sockets.js')(server);
 console.log("Listening on port %d", port);
 
}());

The majority of this is plumping for Express.js. The most significant part is line 34 as this is where the call to configure Socket.IO is being made. I've taken a liking to my modules returning a function when they need to perform some initialization upon import. Once you invoke the initialization function, this can then return the API for the module. This construct mirrors the behavior of a constructor by helping to ensure that the module is in a valid state before you start to use it. This can be seen at line 34 where I am invoking the imported sockets.js module and passing in the server variable. In this case, there is no API returned as once I've setup Socket.IO, I do not need to interact with it again.

sockets.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(function () {
 'use strict';
 var socketio = require("socket.io");
 
 module.exports = function (server) {
  
  var io = socketio.listen(server);
  
  io.on('connection', function (socket) {
   
   socket.on('join', function (data) {
    
    var address = socket.handshake.address;
    console.log("Joined: " + address);
    
    socket.emit('joined', { message: "You are connected!" });
   });
   
   socket.on('send message', function (data) {
    
    console.log("Message: " + data.message);
    
    io.emit('client message', { message: data.message });
   });
   
   socket.on('navigate', function (data) {
    console.log("Navigate: " + data.url);
    
    io.emit('navigate browser', { url: data.url });
   });
  });
 };
        
}());

Socket.IO revolves around emitting events and responding to them. Line 9 is an example of how you would setup a callback to respond to a "connection" event that is received by the server though the use of the on function. Responding to the "connection" event is the standard pattern for setting up the behavior for when a new connection is established. In lines 11 through 30, I am creating three listeners that will react to the connected socket emitting "join", "send message" and "navigate" events. The "send message" and "navigate" listeners both emit events of their own. As there are broadcasted on the io channel, they will be sent to all the other connected sockets. However, the "join" listener is only emitting the "joined" event on the connected socket. When you emit an event, you have the option to send data with it and this can be seen as the second parameter of the emit function.

Client side

index.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(function () {
 'use strict';
 
 var messages = document.getElementById('messages');
 var addMessage = function (message) {

  messages.innerHTML = messages.innerHTML + message + '<br />';
 };
 
 var socket = io.connect(location.host);
 
 socket.on('navigate browser', function (data) {
  
  location.href = data.url;
 });
 
 socket.on('client message', function (data) {
  
  addMessage(data.message);
 });
 
 socket.on('joined', function (data) {
  
  addMessage(data.message);
 });
 
 socket.emit('join');

}());

admin.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
(function () {
 'use strict';

 var socket = io.connect(location.host);
 
 var message = document.getElementById('message');
 document.getElementById('message-button').addEventListener('click', function () {

  socket.emit('send message', { message: message.value });
 });
 
 document.getElementById('navigate-button').addEventListener('click', function () {
  
  var url = document.getElementById('url').value;
  socket.emit('navigate', { url: url });
 });

}());

With Socket.IO, the client side of the wire follows a very similar pattern as on the server side. After connecting to the server you are returned a socket upon which you can emit events or listen for events. Like on the server, these are done using functions called on and emit. For an example of listening for an event, look at line 13 in index.js and for an example of emitting a client side event, look at line 9 in admin.js. The entire solution can be found on GitHub.

I realize that I could have stuck with the .NET stack and used ASP.NET SignalR to achieve the same results, but I feel that trying something new in a different stack can bring new insights that can help to make you a better developer. Each stack has its good points and its bad, however, if you only stick with the same stack, you will only ever experience the same pluses and the same minuses. By trying different programming languages, web-frameworks, databases, and so on, you can expand your horizons to new and different ways of doing something. You may even find a new solution for a pain-point that's been nagging you since you can’t remember when. I plan to step outside of the box whenever the opportunity presents itself and try something new. And maybe you should too!

Wednesday, March 4, 2015

Sharpening the JavaScript Saw by Building a Promise API

I’ve been working with JavaScript a lot lately and wanted to set myself a small challenge where I would aim to build something small, but meaningful within 60 minutes. One thing that I had wondered about how they actually worked was JavaScript promises. I’ve used them with Angular.js and node.js and thought that building my own basic implementation of a promise would be a suitable challenge. With the task decided, I felt that I needed to put together a few constraints that would drive my implementation and give me a set of criteria for the challenge. These I derived from my experience with using promises and what I had read about them. Here are the constraints that I decided on:

-    The promise can only be resolved once--be this keeping or breaking it
-    An optional callback for failure can be supplied with a success callback
-    Multiple callbacks can be supplied and they will be executed in the same order when resolving the promise


With everything laid out, I started my timer and began coding. It didn’t take long to get something up and running that allowed a single set of success and failure callbacks to be queued but the requirement to be able to supply multiple callbacks was a bit more of a challenge. It took a little bit of a design change and some refactoring before I ended up with a solution that I was happy with. This is what I came up with:

(function (promiseApi) {

    promiseApi.Promise = function () {
        
        var isResolved = false;
        var successCallbacks = [];
        var failureCallbacks = [];
        
        var keep = function (data) {
            
            resolve(successCallbacks, data);
        };
        
        var abandon = function (error) { // "break" is a keyword unfortunately
            
            resolve(failureCallbacks, error);
        };
        
        var resolve = function (queue, state) {
            
            if (!isResolved) {
                isResolved = true;
                
                queue.forEach(function (callback) {
                    
                    state = callback(state);
                });
                
                successCallbacks = [];
                failureCallbacks = [];
            }
        };
        
        var when = function (success, failure) {
            
            if (success !== undefined) {
                successCallbacks.push(success);
            }
            
            if (failure !== undefined) {
                failureCallbacks.push(failure);
            }
            
            return Object.freeze({ when : when });
        };

        return Object.freeze({
            keep: keep,
            abandon: abandon,
            promise: Object.freeze({ when: when })
        });
    };

}(module.exports));

Here are some notes about my solution:

-    I decided to include an “isResolved” Boolean even though I am emptying the arrays as a guard against the promise being resolved again before all the callbacks in the appropriate queue have been invoked. This ensures that any additional calls to resolve the promise will result in no further action.
-    The arrays are being re-initialized as a housekeeping measure to release any resources that they are consuming. As a promise can only be resolved once, it doesn’t make sense to hold on to any of the callbacks in its queues. Originally, I was setting the length of the array to 0, but I learned that this actually blocks the garbage collector until the items in the array are overwritten by new items. In normal use of a promise, you wouldn't add additional success and failure callbacks after the promise had been resolved, so the original callbacks would remain in memory.
-    The use of the “setTimeout” function with a timeout of 0 is to ensure that the callbacks are invoked immediately. However, as this is a node.js project it probably would be more efficient to use process.nextTick().
-    To prevent the behavior of a promise being changed, I have used Object.freeze() to make it immutable.
-    In an attempt to keep things clean, I used the revealing module pattern.


This is a very basic implementation of a promise API. I’m sure that there is much that doesn’t adhere to the promise specification, but as I mentioned above, this was just a challenge that I set myself to exercise my JavaScript muscles. I wouldn’t recommend that anyone use this code in production even though—technically—it does work. For one, there’s no error handling and if anything were to go wrong when calling a callback, it would continue to bubble up the call stack. The start of a solution would be to wrap the callback’s invocation in a try-catch block, but what would the appropriate course of action be once an exception has been caught? I think I’d have to refer to the specification for guidance on that. Below is a simple example of how to use the promise API:

carService.js:
(function (carService) {
    
    var promiseApi = require('./promise.js');
    
    carService.get = function (id) {
        
        var promise = new promiseApi.Promise();        

        setTimeout(function () {
            
            var data =  {
                id: id,
                model: 'Ford Mustang ' + id,
                year: 2014
            };

            promise.keep(data);
            //promise.abandon({ message: "Something went wrong" });
        }, 1000);
        
        return promise.promise;
    };

}(module.exports));

app.js:
(function () {

    var carService = require('./fakeCarService.js');

    carService.get(1)
    .when(function (data) {

        console.log(data.model);

        return data.model;
    }, function (error) {

        console.log("Error: " + error.message);

        return error;
    })
    .when(function (data) {

        console.log("Second CB: " + data);

        return data;
    })
    .when(function (data) {

        console.log("Third CB: " + data);
    }, function (error) {

        console.log("Second Error CB: " + error.message);
    });

}()); 


As a challenge to help me practice JavaScript, this was a good problem to solve. The complete node.js project can be found here.