alangpierce / sucrase
- среда, 30 мая 2018 г. в 00:16:10
TypeScript
Super-fast alternative to Babel for when you can target modern JS runtimes
Sucrase is an alternative to Babel that allows super-fast development builds. Instead of compiling a large range of JS features down to ES5, Sucrase assumes that you're targeting a modern JS runtime (e.g. Node.js 8 or latest Chrome) and focuses on compiling non-standard language extensions: JSX, TypeScript, and Flow. Because of this smaller scope, Sucrase can get away with an architecture that is much more performant but less extensible and maintainable. Sucrase's parser is forked from Babel's parser (so Sucrase is indebted to Babel and wouldn't be possible without it) and trims it down to focus on a small subset of what Babel solves. If it fits your use case, hopefully Sucrase can speed up your development experience!
Current state: The project is in active development. It is about 20x faster than Babel and about 8x faster than TypeScript, and it has been tested on hundreds of thousands of lines of code. Still, you may find correctness issues when running on a large codebase. Feel free to file issues!
Sucrase can build the following codebases with all tests passing:
The main configuration option in Sucrase is an array of transform names. There are four main transforms that you may want to enable:
React.createElement
, e.g. <div a={b} />
becomes React.createElement('div', {a: b})
. Behaves like Babel 7's
babel-preset-react,
including adding createReactClass
display names and JSX context information.import
/export
) to CommonJS
(require
/module.exports
) using the same approach as Babel 6 and TypeScript
with --esModuleInterop
. Also includes dynamic import
.The following proposed JS features are built-in and always transformed:
class C { x = 1; }
.
This includes static fields but not the #x
private field syntax.export * as a from 'a';
const n = 1_234;
try { doThing(); } catch { }
.Like Babel, Sucrase compiles JSX to React functions by default, but can be configured for any JSX use case.
React.createElement
.React.Fragment
.Two legacy modes can be used with the import
tranform:
--esModuleInterop
flag is enabled. For example, if a CJS module exports a function, legacy
TypeScript interop requires you to write import * as add from './add';
,
while Babel, Webpack, Node.js, and TypeScript with --esModuleInterop
require
you to write import add from './add';
. As mentioned in the
docs,
the TypeScript team recommends you always use --esModuleInterop
.require('./MyModule')
instead of
require('./MyModule').default
. Analogous to
babel-plugin-add-module-exports.Installation:
yarn add --dev sucrase # Or npm install --save-dev sucrase
Run on a directory:
sucrase ./srcDir -d ./outDir --transforms typescript,imports
Register a require hook with some reasonable defaults:
// Register just one extension.
import "sucrase/register/ts";
// Or register all at once.
import "sucrase/register";
Call from JS directly:
import {transform} from "sucrase";
const compiledCode = transform(code, {transforms: ["typescript", "imports"]});
There are also integrations for Webpack, Gulp, Jest and Rollup.
Sucrase is intended to be useful for the most common cases, but it does not aim to have nearly the scope and versatility of Babel. Some specific examples:
const enum
s are treated as regular
enum
s rather than inlining across files.As JavaScript implementations mature, it becomes more and more reasonable to disable Babel transforms, especially in development when you know that you're targeting a modern runtime. You might hope that you could simplify and speed up the build step by eventually disabling Babel entirely, but this isn't possible if you're using a non-standard language extension like JSX, TypeScript, or Flow. Unfortunately, disabling most transforms in Babel doesn't speed it up as much as you might expect. To understand, let's take a look at how Babel works:
Only step 4 gets faster when disabling plugins, so there's always a fixed cost to running Babel regardless of how many transforms are enabled.
Sucrase bypasses most of these steps, and works like this:
<Foo
with
React.createElement(Foo
.Because Sucrase works on a lower level and uses a custom parser for its use case, it is much faster than Babel.
Currently, Sucrase runs about 20x faster than Babel (even when Babel only runs
the relevant transforms) and 8x faster than TypeScript. Here's the output of
one run of npm run benchmark
:
Simulating transpilation of 100,000 lines of code:
Sucrase: 469.672ms
TypeScript: 3782.414ms
Babel: 9591.515ms
Sucrase is MIT-licensed. A large part of Sucrase is based on a fork of the Babel parser, which is also MIT-licensed.
Sucrase is an enzyme that processes sugar. Get it?