What is sucrase?
Sucrase is a super-fast alternative to Babel for compiling modern JavaScript into older versions that are more widely supported. It focuses on compiling non-standard syntax like JSX, TypeScript, and Flow into standard JavaScript, offering significant speed improvements over Babel.
What are sucrase's main functionalities?
JSX Compilation
Sucrase can compile JSX syntax used in React applications into standard JavaScript, making it easier to run in environments that do not support JSX natively.
import React from 'react';
const App = () => <div>Hello, Sucrase!</div>;
TypeScript Compilation
Sucrase can compile TypeScript code into plain JavaScript, allowing developers to use TypeScript's type checking features without worrying about compatibility.
import express from 'express';
const app: express.Application = express();
Flow Compilation
Sucrase provides support for Flow, a static type checker for JavaScript. It can strip Flow type annotations and compile the code into standard JavaScript.
/* @flow */
function square(n: number): number {
return n * n;
}
Other packages similar to sucrase
babel
Babel is a widely used compiler for writing next generation JavaScript. It's more flexible and configurable than Sucrase, but generally slower due to its comprehensive feature set.
typescript
The TypeScript compiler not only compiles TypeScript into JavaScript but also provides type checking. It's similar to Sucrase's TypeScript compilation feature but includes type checking, which Sucrase does not.
esbuild
esbuild is an extremely fast JavaScript bundler and minifier. It offers similar compilation features to Sucrase but also includes bundling and minification, making it a more comprehensive tool for building web applications.
Sucrase
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 and compiles non-standard language
extensions (currently JSX, later Flow and TypeScript) down to standard
JavaScript. Because of this smaller scope, Sucrase can get away with an
architecture that is much more performant, but requires more work to implement
and maintain each transform.
Current state: Very early/experimental, but it seems to work!
Usage
Currently Sucrase only implements the JSX to React.createElement
transform and
can only be used as a library. You can use it like this:
yarn add sucrase # Or npm install sucrase
import {transform} from 'sucrase';
const codeWithoutJSX = transform(codeWithJSX);
Motivation
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, Flow, or TypeScript.
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:
- Tokenize the input source code into a token stream.
- Parse the token stream into an AST.
- Walk the AST to compute the scope information for each variable.
- Apply all transform plugins in a single traversal, resulting in a new AST.
- Print the resulting AST.
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:
- Tokenize the input source code into a token stream using Babel's tokenizer.
- Run the transform by doing a pass through the tokens and performing a number
of careful find-and-replace operations, like replacing
<Foo
with
React.createElement(Foo
.
Performance
Currently, Sucrase runs about 10x faster than Babel. Here's the output of one
run of npm run benchmark
:
Simulating transpilation of 100,000 lines of code:
Sucrase: 980.442ms
Buble: 2320.480ms
TypeScript: 2443.063ms
Babel: 9682.259ms
When using a forked version of Babylon that avoids unused parsing work, the
Sucrase running time drops to around 650ms.
Project vision and future work
- Add support for
import
/export
syntax, converting to CommonJS in the same
way as Babel. - Add TypeScript support. One challenge here is implementing enums, but a first
pass may be to fall back to TypeScript/Babel if there are any unsupported
features.
- Add Flow support.
- Fork the Babylon lexer and simplify it to the essentials of what's needed
for this project, with a focus on performance.
- Rewrite the code to be valid AssemblyScript,
which will allow it to be compiled to wasm and hopefully improve performance
even more.
- Explore the idea of doing transforms as a single pass through the source code
without separate tokenize and transform steps.
Why the name?
Sucrase is an enzyme that processes sugar. Get it?