Webpack: Error: configuration.resolve.extensions[0] should not be empty

The problem

You just started a new webpack project and happily copied over an old webpack configuration to make a few tweaks to get the project set up. Or, maybe you decided suddenly to upgrade our webpack package. Suddenly, when you run webpack, you see the following error:

configuration.resolve.extensions[0] should not be empty

The solution

If you encounter this error, then it is more than likely you are using webpack version 2 and haven’t migrated your webpack version 1 configuration over yet.

In webpack, we use the resolve section of the configuration file to declare how to resolve files, as well as what file types/extensions we can process without explicitly giving the file extension in the imports. (e.g. require(“./login”) rather than require(“./login.js”)) This hasn’t changed in webpack version 2, but what has changed is that we no longer use the empty string ('') to represent files with no extension. Instead, we have to use an asterisk ('*').

For example, instead of this:

resolve: {
	extensions: ['', '.js', '.es6']
}

In webpack version 2, we do this:

resolve: {
	extensions: ['*', '.js', '.es6']
}

Background

Lots of things changed with webpack version 2, which means that we need to make some updates to get up to speed with the new version.

For a more detailed migration guide for webpack version 1 to webpack version 2, check here: https://webpack.js.org/guides/migrating/.

Additional Resources

Webpack: Error: configuration.module has an unknown property ‘preloaders’

I have a lot of entries now in my debug log, from all the random errors and bugs that I encounter during my regular work. I figure I might as well start sharing some of it on here as well. Who knows it might just save some poor soul out there a few hours of tearing their hair out! 😉

The problem

You just started a new webpack project and happily copied over an old webpack configuration to make a few tweaks to get the project set up. Or, maybe you decided suddenly to upgrade our webpack package. Suddenly, when you run webpack, you see the following error:

configuration.module has an unknown property ‘preloaders'

The solution

If you encounter this error, then it is more than likely you are using webpack version 2 and haven’t migrated your webpack version 1 configuration over yet.

In webpack version 2, there’s two gotchas related to this problem:

  1. The “loaders” section is now renamed to “rules”.
  2. The “preloaders” section is no more. Instead of a separate preloaders section, we need to move the preloading rules into the “rules” section with an enforce property set to “pre”.

Here’s an example of what the module section of the webpack configuration should like to fix this error message:

module: {
	rules: [
		{
			enforce: 'pre',
			test: /\.js$/,
			exclude: 'node_modules',
			loader: 'jshint-loader'
		},
		{
			test: /\.css$/,
			loader: "style!css!postcss",
		},
		// other loaders
	]
}

Background

I encountered this error last month, when I was trying to set up webpack in a new project. I innocently ran npm install webpack…but alas, inadvertently installed webpack version 2, which meant that lots of things were breaking with my old webpack v1 configuration file.  Lots of things changed with webpack version 2, which means that we need to make some updates to get up to speed with the new version.

For a more detailed migration guide for webpack version 1 to webpack version 2, check here: https://webpack.js.org/guides/migrating/.

Additional Resources

 

Algorithms: Javascript Array indexOf vs Binary Search vs Hash Access

I’ve been getting into algorithms lately, and I wanted to try out adding binary search to Simply Is, a simple type testing javascript utility I wrote a while back. But, surprisingly, it ended up being slower than the native Javascript array indexOf. Less surprisingly though, hash access was the fastest. Actually, creating a hash from the array then accessing it was actually still faster than the binary search (though slower than the native array indexOf).

My theory is that this result probably has to do with how Javascript works under the hood. Something worth looking into would be how Array indexOf is implemented in the Javascript source. It might be possible that since it’s built-in/operating at a lower level, there’s less overhead and thus performs better.


Binary search – 216,774 ops/sec

function binary_search(x,arr){
    if( typeof arr[0] === 'number' ){
        arr = arr.sort(function(x,y){ return Number(x) - Number(y) })
    }else{
        arr = arr.sort()
    }

    var min = 0,
        max = arr.length - 1,
        current_guess = Math.floor( (min + max)/2 )
        
    var found = false

    if( x === arr[current_guess] ){
        found = true
    }else if( x < arr[current_guess] ){ found = binary_search(x, arr.slice(min, current_guess) ) }else if( x > arr[current_guess] ){
        found = binary_search(x, arr.slice(current_guess + 1, max + 1))
    }

    return found
}

Array indexOf = 43,314,557 ops/second

var TEST_ARRAY = [2, 3, 17, 18, 22, 74, 25, 93, 43, 47, 48, 56, 59, 61, 64, 52, 71, 73, 75,37, 76, 77, 88, 21]
TEST_ARRAY.indexOf(73) > 0

Creating a hash from the array then accessing it = 809,269 ops/sec

   var TEST_HASH = {}
    TEST_ARRAY.forEach(function(value){
        TEST_HASH[value] = true
    })
    TEST_HASH[73]

(Existing) hash access = 90,671,807 ops/sec

TEST_HASH[73]

Either way, this result was somewhat surprising to me, since in terms of algorithms, binary search is supposed to be very fast. Then again, the comparison might not be completely fair, since the binary search is implemented at a higher level while the Array indexOf method is built-in. I wonder, though, how will it hold up if the array is very,very large? It’s possible that this result is only the case because the array that’s being searched is pretty small? Or, perhaps it has to do with the way I did the binary search (recursive calls on smaller array slices)? Maybe having to slice/create a new array is slowing it down?

Lots of possibilities for what may have led to this result. I’ll have to look into this a bit more one of these days.

Using Isotope with ReactJS

Isotope is a great layout alternative to Masonry, and recently it has been my preferred choice when going for a Masonry-like grid layout. But when I tried to add it in to a React application I’ve been working on, I encountered some issues with initialization. And things got reaaaally wonky when the grid items were dynamic and changed too. So here’s how I solved it.

I had a component for my product search results that rendered the product results that matched a user query then allowed users to filter them via a search box…as well as re-run the search again with different parameters. Each product result was displayed via the Product component, which essentially renders the product image, detailed specs, and then allows for selection/ordering.

The product data is retrieved from the ProductStore, which has data stored from a previous ajax request to an API server, which returns a JSON response with all the matching products. The product data retrieved is in something like the following format:

[
	{
		item_num: 0,
		name: "Awesome product",
		specs: [...] // an array of specifications
	},
	{
		item_num: 1,
		name: "Another product",
		specs: [...] // an array of specifications
	}
]

However, since we’re filtering the product data and also re-running the search with different search queries, the product data that needs to be displayed is dynamic. So, what we need is for the Isotope grid to adjust its layout accordingly every time the list of visible products changes due to user interaction.

The obvious solution would be to initialize Isotope in componentDidMount, then destroy it in componentWillUnmount. But when the product data changes….everything breaks. So how can we fix this so that even newly updated product results will be in an Isotope grid?

The solution is to remove the existing Isotope instance in componentWillUpdate, then reinitialize it in componentDidUpdate once the component has the new data. This is, of course, in addition to initializing Isotope during componentDidMount and destroying it in componentWillUnmount.

To initialize Isotope on a container element (in my case, .products):

$('.products').isotope({
	itemSelector: '.product',
    	layoutMode: 'masonry'
});

And to destroy/tear it back down:

$('.products').isotope('destroy');

Here’s a simplified version of what the final ProductSearch component looked like (note, JSX is commented out due to limitations of the Syntax highlighter):

var React = require('react');
var _ = require('lodash');
var Product = require('./Product');
var ProductFilters = require('./ProductFilters');
var ProductStore = require('./ProductStore');

var ProductSearch = React.createClass({
	getInitialState: function(){
		return {
			products: [],
			searchString: ""
		}
	},
	componentWillMount: function(){
		ProductStore.addChangeListener(this.handleReceiveData);
		this.setState({
			products: ProductStore.getProducts()
		})
	},
	handleReceiveData: function(){
		this.setState({
			products: ProductStore.getProducts()
		})
		console.log('data received from product store');
	},
	filterItems: function(event){
		this.setState({
			searchString: event.target.value
		});

	},
	render: function(){

		var vehicle = this.state.vehicle;

		// hey, if we have products stored in the state, display them
		if(this.state.products && this.state.products.length){
			var searchString = this.state.searchString.toLowerCase();
			var products = this.state.products.map(function(product){

				// combining the values of each product (e.g. item number, product description, technical details, color, etc into one string for search
				var productString = _.values(product).join("|").toLowerCase();

				// if there is no search string or if the search matches, then show the product
				if( !searchString || productString.match(searchString) ){
					// unfortunately, JSX doesn't play so well with the syntax highlighter. But this is JSX here
					return (
						//<Product product={product} key={product.model.toLowerCase() + product.finish}></Product>
					)
				}else{
					// otherwise, don't show the product in the results
					return "";
				}
			});
	
		}else{
			// no products were found
			var products = (
				//JSX <div>Sorry, nothing here.</div>
			);
		}

		return (
			/* JSX
			<div>
				<section id="products">
					<div>{products}</div>
				</section>
			</div>
			*/
		)
	},
	isDeviceMobile: function(){
		if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
		 return true;
		}
	},
	initIsotope: function(){
		$('.products').isotope({
	        	itemSelector: '.product',
	        	layoutMode: 'masonry'
	    	});
	},
	removeIsotope: function(){
		$('.products').isotope('destroy');
	},
	componentDidMount: function(){
		// initialize isotope only if there are products, and if the device isn't Mobile
		if(this.state.products && this.state.products.length > 0 && !this.isDeviceMobile()){
			this.initIsotope();
		}
	},
	componentWillUpdate: function(){
		this.removeIsotope();
	},
	componentDidUpdate: function(){
		if(this.state.products && this.state.products.length > 0 && !this.isDeviceMobile()){
	   		this.initIsotope();
	    }
	},
	componentWillUnmount: function(){
		this.removeIsotope();
		ProductStore.removeChangeListener(this.handleReceiveData);
	}
});

module.exports = ProductSearch;

Enjoy, and happy coding! 🙂

Getting Started with Docker

docker logo

If you’re into DevOps, Docker is one of those tools you’ll encounter sooner or later. It’s pretty awesome. But getting started with it can be a tad difficult, so I’m here to help with that.

I’ve been on a bittersweet honeymoon with Docker, and there are certainly things I wish I’d known about when I first started out. One of the greatest benefits of learning from the Internet is the massive amount of information that is available. One of the greatest downsides? The massive amount of information that is available.

A downside of learning things on your own is that there is just so much content out there, but it’s up to you to organize and process it all into something you can understand….and sometimes, after banging your head against the wall to figure out a strange bug, you realize that the information is outdated!

So in this post, I’ll give a quick and simple introduction of Docker, what it is capable of, and how you can get started with it as of Docker version 1.9.0.

Table of Contents

  1. Applications of Docker
  2. The Problem
    1. Virtualization: Development Environment = Production Environment
    2. Configuration Management: Development Configuration = Production Configuration
  3. Docker: Containerization vs. Virtualization + Configuration Management
    1. Containers
    2. Terminology
  4. Getting Started
    1. Docker Daemon/Server
      1. Linux
      2. Mac/Windows
    2. Images
    3. Containers
    4. Remote API
  5. Wrapping Up
  6. References and Further Reading

Applications of Docker

There is no such thing as a tool that can do everything, and there is no magical panacea that can solve all of our problems. Docker is no different. Like any tool, there are some use cases that better suit it, and other situations when it is ill suited. You wouldn’t use a hammer to dig a hole, or a shovel to screw a nail. Whenever you learn a new tool, instead of thinking, “Hey, I wonder if I can use it to do ____?” a better question to ask would be “What is this tool best suited for?”

Applications of Docker that really make it shine include using it for:

  • Ephemeral (temporary) isolated processes (e.g. Codepen, Codeship)
  • Short running tasks, maintenance scripts, or worker processes that receive then process a workload
  • Running and deploying stateless applications
    • Web frontends
    • Backend APIs
  • Running isolated environments with imposed CPU/memory limits

However, because of the ephemeral nature of Docker containers, it is not a great choice for applications that need to store state/files, though it is possible to mount folders/volumes from the Docker host into the container. Continue reading “Getting Started with Docker”

Endings and New Beginnings

It is nearing the end of the year, a time when darkness and snow veils the world and the activity and bustle of the year winds down into the holiday season. It is the end of another cycle, another year. It is a time of endings and new beginnings.

Everything that has a beginning must some day end.

I feel like this year especially has been a time of closure and conclusions. The scent of change is in the air. I can sense it; I can taste the bittersweet pain of parting and the excitement of a new beginning in the changing winds. It has been a year of partings, and of preparations for partings.

There have been people who have left our side, and there are those who might leave any time. How do we know that today, we won’t die? Or that today, someone we love won’t die?

We’re so often under the illusion of permanence. We take things for granted. We go through our days not really thinking about endings and beginnings, but just riding along assuming that things that have started, will not end. That love will last forever. That we’ll be young forever. That our friends will be with us forever. That our youth and health will last forever.

But nothing lasts forever.

Everything that has a beginning must some day end.

Change is in the air. Change is coming. It’s happening all around us. It’s within us; our cells are dying and replenishing constantly. With every thought, experience, and observation, we change ourselves and our understanding of the world. We are all impermanent. Those around us are impermanent. The world as we see it is impermanent.

Nothing lasts forever.

Much like it is impossible to prevent the year from ending, some endings in our life just cannot be prevented. The final word of a great story will inevitably be written. Lives will be born and lost. Friendships and romance will bloom then wither. Yet with the ending of one phase, another can start. Perhaps it is just time to move on to the next stage in our life. Perhaps the ending is so that we can have a new, better beginning and a new life.

Every ending is also a new beginning.

Lessons from my first hackathon: Fight the Lady Killer Codeathon

fight the lady killer logo

This last weekend, I took part in the Fight The Lady Killer codeathon which went from October 2–4 at Cal State LA. Armed with plenty of sleep and caffeine, I started the codeathon filled with excitement to build an app an three days.

This was my first hackathon, and it was lots of fun; I definitely learned a lot, especially about how to work in a large group to try to make something under pressing deadlines. (Each difficult tasks in and of themselves!) So I wanted to share what I’ve learned from this experience both for my own reference as well as to help others in their hackathon experience. Continue reading “Lessons from my first hackathon: Fight the Lady Killer Codeathon”