How to code like playing LEGO™
Tags: javascript, showdev, modules, lego
Published: 2018-03-09 22:01:13

---
title: How to code like playing LEGO™
published: true
description: Using the power of ES6 vanilla JS to build code block by block.
tags: javascript, showdev, modules, lego
cover_image: https://thepracticaldev.s3.amazonaws.com/i/r7jrch86o46r3q8zo66g.jpg
---

Modularity is a big trend and I'm not the first to hop on this train. Today, I'm going to show you how easy you can build a multi-module app with vanilla Javascript and some awesome tools.

# Recipe

## Ingredients

First of all, I'm going to assume you know a few things beforehand :

 1. Object Oriented Programming
 2. How to write JS
 3. Basics of NPM

## Steps

### The ground

Lets start with an empty directory for your project (we'll name it unicorn) and initialize it

```
npm init
```

and create the main file `index.js` with an old-school JS class

```js
function Unicorn(name) {
    this.name = name;
}
Unicorn.prototype = {
    shine: function() {
        // All kind of good stuff here 🦄
    }
}

var dazzle = new Unicorn("Dazzle");
dazzle.shine();
```

### Decoupling

Now image that you want to use the `Unicorn` class in another project, or just open-source it to the Humanity. You could create another directory with another repo, but let's be smarter. The `Unicorn` class is so linked to the Unicorn project that we'll use NPM scoped package name for clarity.

All that reduce `index.js` to 3 lines of codes.

```js
import Unicorn from "@unicorn/model";

var dazzle = new Unicorn("Dazzle");
dazzle.shine();
```

Next, we create a sub-directory for our module.

```sh
mkdir packages/model
cd packages/model
npm init # and name it @unicorn/model
```

Which will have an `index.js` too with the class inside it. Since we left the plain browser JS with import/export statement, why not use the beautiful ES6 class syntax.

```js
export default class Unicorn {
    constructor(name) {
        this.name = name;
    }

    shine () {
        // All kind of good stuff here 🦄
    }
}
```

At that point, the `import` statement is targeted at a package name that should be installed under the `node_modules` sub-directory. We could use a relative path like `import Unicorn from "./packages/model/index.js";`. What could be better is to create a link between packages.

Thankfully, npm can do that for you with the [link command](//docs.npmjs.com/cli/link). Here's what it looks in our case.

```sh
cd packages/model
npm link
cd ..
npm link @unicorn/model
```

Perfect !
![Perfect](//thepracticaldev.s3.amazonaws.com/i/alhu7wrnie4rlrzbevgy.gif)

### Wrapping

> Ok nice one, but now I can't use it in my browser, you dumbo !

First, how are you calling me ?
Then yeah, I know, for now it's all experimental syntax and stuff, but there's tools to handle it for you. I like to use webpack with babel, of course, it's not the only solution.

Adding some package on project's root.

```
npm install --save-dev babel-loader babel-core babel-preset-env webpack
```

The whole webpack configuration could fill another article, so I'll just show one that work. Set a new file called `webpack.config.js` with some instructions inside.

```js
module.exports = {
    entry: "./index.js", // Main file to read
    module: {
        rules: [{
            test: /\.js$/, // For all file ending with ".js"
            use: {
                loader: "babel-loader", // Use babel
                options: {
                    presets: ["babel-preset-env"],
                },
            },
        }],
    },
    output: {
        filename: "dist/unicorn.js", // Output the result in another file
        library: "Unicorn", // Under "Unicorn" namespace
        libraryTarget: "this",
        libraryExport: "default",
    },
};

```

Then, if you run `npx webpack` it will build all your sources into one file usable by plain web browser.

### Managing

You can now create lots of sub-modules and wrap them all in one file. You can even have sub-sub-modules and so on. Just put them all in the `modules` directory.
As your project grows, it'll be harder and harder to manage all this menagerie.

That where [lerna](https://lernajs.io/) come into play.


```
npm install -save-dev lerna
```

Think of it as a `npm link` on steroids.
Check out the full documentation on the project page, but here's a few useful commands.


```bash
npx lerna clean # Remove all node_modules directories
npx lerna bootstrap # Install remote dependencies and link local ones
npx lerna add package # Install a package to all sub-modules
npx lerna add package --scope=sub-module # Install a package to a specific sub-module
npx lerna publish # Bump, tag and publish all your modules over NPM
```

---

# Enjoy

You should now be on track to write the most elegant project possible. I'm counting on you ;)

If you want more in-depth examples, I'm currently building ~~yet another~~ [JS drawing library](https://github.com/GMartigny/pencil.js) using the very same techniques.

Next time, we'll talk about automated tests and how to catch lots of bugs and ensure consistency over time.