Skip to content

Instantly share code, notes, and snippets.

@kvz
Last active November 15, 2017 23:23
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save kvz/259ca7e60bbd5ecc336f to your computer and use it in GitHub Desktop.
Going from CoffeeScript to ES6

These are the steps I took to change a modest project from CoffeeScript to ES6.

My ~2000LoC project took me around 6 hours to port, but I sunk 3 hours into a stupid mistake, and 2 into figuring out these steps, so with these steps & warnings at your disposal already, you should be able to do bigger projects in considerably less time.

Automatic tools only take you so far, there will be some manual fixing. Sometimes the generated code clearly doesn't look like a human wrote it, and sometimes there are bugs.

In this last case, when porting software trips over a particular bit of CoffeeScript, comment this bit out, and try transpiling the file again. If this is successfull, you'll see the commented CoffeeScript inside the JS, and you can port that bit yourself.

Okay let's dive right in!

1. Branching

Make sure you're on latest master, and start a new branch, via for instance git checkout -b es6.

2. ESLint

Install ESLint with standard linting.

ESLint can enforce linting, which helps a lot to brush up the quality of generated code. You can install this into your project as it will be of great use later on as well.

You might have to change a few of these settings, for instance I added to allow it and describe globals for mocha. That may not apply to your project. Or you might develop for the browser instead of node.

npm install --save eslint eslint-config-standard eslint-plugin-standard
echo '{
  "extends": "standard",
  "env": {
    "es6": false,
    "browser": false,
    "node": true
  },
  "globals": {
    "it": true,
    "describe": true,
    "window": true
  }
}
' > .eslintrc
echo 'dist/**
lib/**
coverage/**
node_modules/**
test/lib/**
' > .eslintignore

You probably don't have any JavaScript files yet, but you can already try node_modules/.bin/eslint . to see if you installed it properly.

All good? Commit this already.

3. From CoffeeScript to JavaScript (does ES6, but leaves some to be desired)

npm install -g decaffeinate
find . -name '*.coffee' |grep -v node_modules > todo.sh
$EDITOR todo.sh

Change to decaffeinate x.coffee x.js && rm x.coffee && eslint . --fix

Go over todo items by hand, one by one, so you can open the file in your editor and fix any parse error.

Don't bother fixing ALL the linting yet at this point.

Run your tests. Fix what's broken.

All good? Commit this already.

4. Optimize for ES6 (extra ES6 like const and arrow functions)

npm install -g lebab
find . -name '*.js' |grep -v node_modules > todo.sh
$EDITOR todo.sh

Change to lebab x.js --out-file x.es6 && rm x.js && mv x.es6 x.js && eslint . --fix

Go over todo items by hand, one by one, so you can open the file in your editor and fix any error.

Use these regexes for additional Fixes:

Find any coffee reference:

from: coffee
  to: node --harmony
  or: babel-node

Remove vertical alignment, which is not alled by standard, and not auto-fixable by eslint:

from: ([a-zA-Z])\s+:\s*('|`|[a-zA-Z]|\[|\{|\d)
  to: $1: $2

Change var require to import:

from: (const|var) ([a-zA-Z\_]+) = require\('([\./a-zA-Z\_]+)'\)
  to: import $2 from '$3'

Regexes are imperfect. Check(!) before replacing. Run your tests. Fix what's broken.

All good? Commit this already.

5. Done

Grep the code for iterable and hunt for abominations. CoffeeScript's for/when seems to lead to that. Short of decent ES6 alternatives, I resorted to using lodash's _.find, _.forOwn, etc. instead.

Same goes for undefined. CoffeeScript's results?.first? notation doesn't result in compact ES6 syntax. _.has and _.get to the rescue.

Then there is return. It has been added a few more times than necessary. Doesn't hurt, but to prettify things up, you might want to remove a few superfluous ones.

All good? Commit this already.

6. Done

You have successfully ported your project from CoffeeScript to JavaScript!

Submit a PR for your es6 branch, get it reviewed, and enjoy a nice ☕break 😄

Bonus

Your project now utilizes many ES6 features, such as import, but the latest Node does not support this, even via --harmony. So it's wise to get Transpiling to ES6 going from e.g. ./src to ./lib. If you're shipping node modules via npm, include your lib with source maps, and keep your src only in Git.

These docs are so excellent, that I won't be repeating how to set that up here 😄

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