The ES6 Development Scheme For React Using GNU Make
And there is, Babel is one of them, and the one I used most in my workflow (and there is another reason that I use Babel as the compiler, the reason is that Babel supports React’s JSX officially, I’ll talk about that later).
The Problems To Face When Using ES6
- Every out file must be compiled, or you won’t get your application run on any browser or nodejs
- Since all the output file are compiled, you’ll face a problem of C, you can’t debug the running code, unless you have some kind of debug data exists, because the result code is quite different(compiled and optimised) than the original one
- For these files, including them or tracking the change is quite complex
For Babel, it can compile the ES6 file and create an Source Map and using main stream browsers(Firefox or Chrome) to debug the original code (yeah!).
And let’s face the problem again:
- Must compile source to dest code
- Must compile and create source map file/data
- Files are stored as trees in directory, must track every file’s change so that, you don’t rebuild the whole directory again when only change a small file
What development scheme do you recall? It’s C!
But how about the problem 3?
For C, it is quite easy, since every file is compied as an object file .o, there will be another process of building, it is called linking.
And is there any tool in JavasScript support linking? Yes, the tool I used is Browserify.
So, the solution that will solve the problem above, should be something like this (exactly same as C, I’ll add the C part as comparation):
- Compile the code and generate the debug information (Babel – GCC)
- Tracking the file change and do the incremental compile (Makefile)
- Complex test and directory operations (Bash)
- Linking the output file and required libraries together to the product (Browserify – Link)
And Beyond That
And the way beyond is that you can make the style files be compiled too(I use Sass to compile the style code)
First, you must have a GNU Make installed on your system.
This should be quite easy, you can use any package manager to install it(including Cygwin), the version that I installed using mac ports, is GNU Make 3.81.
Then you’ll need to setup the compiling environments:
- For ES6 compilation, you’ll need
- NPM: The Package manager of Node, it is bundled with NodeJS’s installation, so you won’t need to install it.
- Babel: The ES6 compiler that I used, this can be installed just using npm like this:
npm install babel
- For the result linking you’ll need:
npm install browserify
And there you go, you can make GNU make to build your project.
The Make patterns
The first thing for compile is to add the compile patterns to do the compliation(just like C, source files are using file extension .c and the output files are using file extension .o).
I’m using this scheme to init the pattern:
- Babel can compile the JSX code for React, so it is very natual
- You can make your JSX editor plugin (for example VIM plugin) to recognise this, and since JSX is a super set of ES6, so you’ll make your editor support your source files automaticly
- All the compiled result are using .js file extension, having the same file name
So, the pattern to compile all the source file is something like this:
%.js: %.jsx $(SILENT) $(BABEL) -s inline -o $@ $<
The meaning of this pattern is like this:
- All the js output file can be compiled using the source code file of jsx, for example, if you want to make a js file named hello.js, make should find the source file named hello.jsx, and compile it using the operations below and make hello.js
$(SILENT)is the make trick to have the debug output, let’s ignore it, suppose it is blank
- Here is the operation
$(BABEL) -s inline -o $@ $<this command means that I want babel to compile the source map into the output and
$@means the output file name
$<means the input file name
The Source Files And How To Build The Dist File
But how can you specify all the source files to let them to be compiled by make, you can use this way(so straight forward, but not wise)
SOURCE_FILES := hello.js world.js bye.js main.js
This is a little stupid, but straight forward.
Is there any better way to handle this? I’m using a macro to do this, it is something like this:
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) SRC_DIR := src SRC_FILES := $(call rwildcard, $(SRC_DIR), *.jsx)
This settings will have all the jsx file in the src folder set as the variable SRC_FILES. Then you can use this variable to add the build task.
build.js: $(SRC_FILES) $(SILENT) $(BROSERIFY) $(SRC_DIR)/app.js -o build.js
And even add the uglified version of the build.js
build.ugly.js: build.js $(SILENT) $(UGLIFY) build.js -o build.ugly.js
How About Unit Testing?
For unit testing, we can just use Jasmine.
And using the variable and tasks like this:
SPEC_DIR := spec SPEC_FILES := $(call rwildcard, $(SPEC_DIR), *.jsx) test: $(SPEC_FILES) $(SILENT) $(JASMINE)
So far, there is an problem using this way, is that the linker of browserify is quite qutie quite quite slow.
For my project, it’ll cost at least 6 seconds on a MacBookPro Retina 2015 to build the result , this is unbareable, so I decide to write a new linker(just the linker, which supports CMD requiring and add the glue code to make it works in a single file) in Go, and that’ll make it faster.
This will take a little time to finish, so, before that, I’ll just using browserify to do the job.
So much for this blog post, I’ll write another blog post about the project setup, and after cleanup the code, I’ll create an project bootstrap on the github.com to let you understand the benifits of this method.