Last active
November 15, 2016 16:46
-
-
Save felixSchl/940a1a7aa10a7cf4240e72f448ea2376 to your computer and use it in GitHub Desktop.
Typescript 2 -> ES6 -> Babel -> ES5 (+ watchable / NO gulpfile! - just unix pipes) https://asciinema.org/a/20h1t61ky43xvszkrcl8h24jo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Task wrapper. Runs various chores in a cross platform manner. | |
# | |
# Usage: run [-h] <command> | |
# | |
# Available commands are: | |
# build: Build the project | |
# <other>: Run any other command available in the NPM path | |
# | |
# Options: | |
# -h, --help Show this help and exit | |
################################################################################ | |
# Automatic configuration | |
################################################################################ | |
TSC_CMD=tsc | |
BABEL_CMD=babel | |
PATH=./node_modules/.bin:$PATH | |
IS_WINDOWS=false | |
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
SCRIPT_DIR_LEN=${#SCRIPT_DIR} | |
# check if we're operating under windows (under mingw / git bash) | |
# on windows, the symlinked script files have an obnoxious .cmd file extension. | |
if [[ $(uname) == MINGW* ]]; then | |
IS_WINDOWS=true | |
TSC_CMD=tsc.cmd | |
BABEL_CMD=babel.cmd | |
fi | |
################################################################################ | |
# Build scripts | |
################################################################################ | |
# Typescript wrapper | |
# | |
# Typescript 2 ships with a flag to emit compiled files to stdout | |
# (`-listEmittedFiles`). This makes it possible to convert the emitted | |
# files from ES7+ to ES5 using, for example, the babel transpiler. | |
# | |
# The problem, however, is that these emitted files may be mangled with | |
# other output of the compiler, since it emits everything to the same fd. | |
# This script contains a `tsc` wrapper (`_tsc`) that addresses this issue | |
# by filtering out the lines that describe an emitted file and those that | |
# do not and re-emitting them to stdout and stderr respectively. Further, | |
# it emits "sets" of changed files, not just single files which is help- | |
# ful, for example, in the case of babel which seems to perform much better | |
# given multiple files in one go, rather than performing a cold start for | |
# each. It does so by interspering a null-byte after each set of files: | |
# | |
# file 1\nfile2\nfile3\n\0file4\nfile | |
# | |
# This script has been tested to run on git-bash under Windows as well as | |
# Bash 3 on OSX (default). | |
function _tsc { | |
local IFS=$'\n' | |
$TSC_CMD "$@" --listEmittedFiles | awk ' | |
function flush() { | |
if (files != "") { | |
printf "%s%c", files, 0 | |
files = "" | |
} | |
fflush() | |
} | |
BEGIN { files = "" } | |
/.*Compilation complete.*/ { | |
print $0 > "/dev/stderr" | |
flush() | |
next | |
} | |
/^TSFILE:.*\.js$/ { | |
if (files != "") { | |
files = files "\n" | |
} | |
files = files substr($0, 9) | |
} | |
{ print $0 > "/dev/stderr" } | |
END { flush() } | |
' | |
} | |
# Read filepaths on stdin and remove their common leading path to the root of | |
# the project, taking into account Windows pathing. | |
function mk_relpath { | |
while IFS=$'\n' read -r file; do | |
if $IS_WINDOWS; then | |
file=/$(echo "$file" | sed 's/\\/\//g' | sed 's/://') | |
fi | |
eval "echo .${file:$SCRIPT_DIR_LEN}" | |
done | |
} | |
# Build the project from start to finish. All typescript source files are | |
# compiled and the output is run through the babel compiler: | |
# | |
# Typescript -> ES6 -> Babel -> ES5 | |
# | |
# Any adhoc options are passed to the typescript compiler only. Configure babel | |
# behavior using the .babelrc file. Likewise, prefer tsconfig.json to configure | |
# typescript and only use the adhoc options for e.g. watching (-w|--watch). | |
function build { | |
local IFS=$'\n' | |
local -r outdir=$SCRIPT_DIR | |
local relfiles | |
_tsc "$@" |\ | |
while read -d '' -r files; do | |
relfiles=($(mk_relpath <<< "$files")) | |
echo >&2 "babel: compiling ${#relfiles[@]} files" | |
"$BABEL_CMD" >&2 --out-dir "$outdir" "${relfiles[@]}" | |
done | |
} | |
################################################################################ | |
# Command line interface | |
################################################################################ | |
# derive the help text from the first comment in a shell script | |
function derive_help { | |
awk ' | |
f && !NF { exit } | |
/^#/ && NR>2 { f=1; sub("^# ?", "", $0); print $0 } | |
' < "$1" | |
} | |
# print the help text, derived from this file | |
function help { | |
derive_help "${BASH_SOURCE[0]}" | |
} | |
case "${1:-build}" in | |
-h|--help) help ;; | |
build) shift; build "$@" ;; | |
-*) echo >&2 "unknown option: $1"; exit 1 ;; | |
*) cmd=$1; shift; "$cmd" "$@"; ;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am desperate not to rely on gulp anymore as it has cost me an incredible amount of time:
gulp.watch
falls over on every error in a pipeline, making it essentially useless to keep running to find compile errors (gulpjs/gulp#71) (and I had just as little luck with gulp 4).gulp.watch
also has this annoying behavior that the project won't build initially, only after triggering a change (#1372). Also gulp takes half a decade to boot up, which is worse when relying onnpm run
scripts, since node has to do multiple cold starts. But the worst part is the resentful behavior of one of the gulp members, telling people essentially to get fucked. In summary, I have spent too much of my lifetime trying to work around theses issues. Then you wonder why. The script above presents a way to use typescript and babel w/o any JS intervention: simply pipe the output of typescript into babel using ordinary unix pipes (works under git-bash also).