This blog post is my latest attempt at putting together a JavaScript build pipeline to create an application using ES6 and a unit testing framework.
The idea is to create a single page application which will then consume an API. So, I want the output from my build pipeline to be a single JS file, and a single CSS file.
This all seems a very basic to me, and yet building it up from scratch, one piece at a time, has proven to be a challenge.
This time, I am using broccoli.
Links
The following links have been very helpful, but please be aware that the examples shown on these pages don’t seem to be entirely up to date.
https://github.com/givanse/broccoli-babel-examples
https://github.com/jayphelps/broccoli-babel-boilerplate
Start
Just hit enter in response to all the prompts.
Edit src/index.js
Edit Brocfile.js
That’s enough to enable us to do a very basic test and confirm that our build system is working.
The JavaScript ecosystem has an embarrassment of build tools. We could use the package.json
file as the core of our build system, defining tasks in the scripts
section of the file. But, the longer I spend programming, the more I appreciate the value of learning one tool well instead of many tools badly. So, I’m going to use make
to glue all of these pieces together.
Edit Makefile
(If you want to learn more about make, I highly recommend this gist)
Now, we can run a build like this;
Nothing too surprising, but it confirms that broccoli is building dist/index.js
from src/index.js
ES6
Now let’s enable using ES6 javascript syntax. To do that, we’ll have to add a transpiler to convert our ES6 javascript to ES5. I’m going to use babel.
Now, let’s convert our index.js
file to use ES6 syntax. Edit src/index.js
Note: node src/index.js
will still work, because node understands ES6 syntax. But, if we tried to use that javascript in a web page, it wouldn’t work in some browsers. You can see details of exactly which browsers support which ES6 features here
We need to edit the Brocfile.js
to use the transpiler;
Now, run the build again;
To prove that the transpiler is working, look at dist/index.js
Multiple files
Compiling one file isn’t going to get us very far, so let’s extend our build system so that it combines multiple files into dist/index.js
To do that, we need another couple of broccoli plugins;
Create src/another.js
Edit Brocfile.js
ES6 Polyfill
There are a lot of nice features in ES6 that are supported on the server side, but not yet on the client side, e.g. generator functions
If we want to use those in our code, we need to add a polyfill to translate the unsupported functions. Babel has such a polyfill, but we need to jump through a few hoops to get it to work.
First, let’s add some code to src/index.js
which uses one of these unsupported features;
If you try to run make now, you’ll get an error like this; ReferenceError: regeneratorRuntime is not defined
Edit Brocfile.js
Now, we can run our example;
Note: AFAICT, this pull request should mean we can just add a second parameter to our babel call, like this; babel('src', { browserPolyfill: true })
instead of the changes above, but it doesn’t seem to work, for me.
Use classes defined in separate files
We’re going to want to put our classes into separate files, and refer to them in our code. Let’s set that up, now.
Edit src/classes/my_class.js
;
We’ll call our new class from src/index.js
Add these lines at the bottom of the file;
Now we need to tell broccoli to include the files in our new classes
directory.
Edit Brocfile.js
and change the inputFiles
line;
Note: We have to put the classes/*.js
section before the section that includes index.js
so that the combined javascript file will define MyClass
before we try to use it.
Testing
The last thing I want to do for now is to add a test framework. I’m going to use mocha with the chai library;
Edit test/init.js
Edit test/mocha.opts
Let’s add a method to src/classes/my_class.js
which returns a value we can test for;
Now let’s write a test in test/unit/classes/my_class_spec.js
The test framework isn’t going through broccoli, so we need to tell mocha to transpile any code it sees.
Edit Makefile
and add these lines;
Now, we can run our tests;
Note: In the broccoli-babel-boilerplate example I mentioned earlier, the test setup includes jshint, but I couldn’t get this to work in my project - jshint would simply hang and never complete. So, I’m presenting this example without it. If you manage to get it working, please let me know how in the comments.
I’d like to add CSS using SASS and React.js and use this as the starting point for building a real application, but I’m going to leave this here for now. Depending on how far I get, there may be future posts on this subject.
The code for this post is available here