Skip to content

Instantly share code, notes, and snippets.

@hallettj
Last active December 10, 2023 13:32
Show Gist options
  • Save hallettj/29b8e7815b264c88a0a0ee9dcddb6210 to your computer and use it in GitHub Desktop.
Save hallettj/29b8e7815b264c88a0a0ee9dcddb6210 to your computer and use it in GitHub Desktop.
Makefile for transpiling with Babel & Flow in a Node app, or in a client- or server-side shared library
# Makefile for transpiling with Babel in a Node app, or in a client- or
# server-side shared library.
.PHONY: all clean
# Install `babel-cli` in a project to get the transpiler.
babel := node_modules/.bin/babel
# Identify modules to be transpiled by recursively searching the `src/`
# directory.
src_files := $(shell find src/ -name '*.js')
# Building will involve copying every `.js` file from `src/` to a corresponding
# file in `lib/` with a `.js.flow` extension. Then we will run `babel` to
# transpile copied files, where the transpiled file will get a `.js` extension.
# This assignment computes the list of transpiled `.js` that we expect to end up;
# and we will work backward from there to figure out how to build them.
transpiled_files := $(patsubst src/%,lib/%,$(src_files))
# Putting each generated file in the same directory with its corresponding
# source file is important when working with Flow: during type-checking Flow
# will look in npm packages for `.js.flow` files to find type definitions. So
# putting `.js` and `.js.flow` files side-by-side is how you export type
# definitions from a shared library.
# Compute the list of type-definition source files that we want to end up with.
# This is done by replacing the `.js` extension from every value in the
# `transpiled_files` list with a `.js.flow` extension.
flow_files := $(patsubst %.js,%.js.flow,$(transpiled_files))
# Ask `make` to build all of the transpiled `.js` and `.js.flow` files that we
# want to end up with in `lib/`.
#
# This target also depends on the `node_modules/` directory, so that `make`
# automatically runs `yarn install` if `package.json` has changed.
all: node_modules $(flow_files) $(transpiled_files)
# This rule tells `make` how to transpile a source file using `babel`.
# Transpiled files will be written to `lib/`
lib/%: src/%
mkdir -p $(dir $@)
$(babel) $< --out-file $@ --source-maps
# Transpiling one file at a time makes incremental transpilation faster:
# `make` will only transpile source files that have changed since the last
# invocation.
# This rule tells `make` how to produce a `.js.flow` file. It is just a copy of
# a source file - the rule copies a file from `src/` to `lib/` and changes the
# extension.
lib/%.js.flow: src/%.js
mkdir -p $(dir $@)
cp $< $@
clean:
rm -rf lib
# This rule informs `make` that the `node_modules/` directory is out-of-date
# after changes to `package.json` or `yarn.lock`, and instructs `make` on how to
# install modules to get back up-to-date.
node_modules: package.json yarn.lock
yarn install
@gibatronic
Copy link

gibatronic commented Mar 3, 2018

I've been also using Makefile for some time, the only downside is not being able to list available targets.

So for that I wrote the make-help project, all you have to do is to decorate the target with a comment and make-help will pick it up and list.

@tbartels
Copy link

tbartels commented Mar 4, 2018

@gibatronic depending on your shell you should be able to use tab completion, just type make <tab> to get a list of all make targets with partial autocomplete make cl<tab> becomes make clean, hunt down your shell completion script for more details, or a little googling should reveal how to use the complete builtin to generate autocomplete rules.

@simon-movio
Copy link

@gibatronic, I have been using the following post for help with listing available make targets
https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html

Hope it is of some value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment