Espree JavaScript Parser
Espree is a high-performance, Esprima-compatible JavaScript parser built upon the modular Acorn parsing library. It is the default parser used by ESLint and is designed to produce Abstract Syntax Trees (ASTs) that are highly consistent with the Esprima API, making it a drop-in replacement in many scenarios. The package is currently at stable version 11.2.0 and receives active maintenance with frequent updates, typically on a monthly or bi-monthly schedule for minor and patch releases. Key differentiators include its robust support for all modern ECMAScript features up to ES2026 (ECMAScript 17), comprehensive parsing options for fine-grained control over AST output (including ranges, locations, comments, and tokens), and official TypeScript type definitions since v11.1.0, enhancing developer experience for TypeScript projects.
Common errors
-
SyntaxError: The keyword 'await' is reserved (or similar for other modern syntax features)
cause The `ecmaVersion` option was not set correctly or is too old to support the JavaScript syntax being parsed.fixSet `ecmaVersion: 'latest'` or specify a modern year (e.g., `ecmaVersion: 2024`) in the parse options object. -
ReferenceError: require is not defined in ES module scope
cause Attempting to use CommonJS `require()` syntax in an ECMAScript Module (ESM) file.fixIf your project uses ESM, use `import * as espree from "espree";` to import the library. Ensure your `package.json` has `"type": "module"` or files end with `.mjs`. -
TypeError: espree.parse is not a function
cause Incorrect ESM import style. Espree is exported as a namespace object, not with named exports for its functions.fixFor ESM, correctly import the module as a namespace: `import * as espree from "espree";`. Then, call `espree.parse(code)`.
Warnings
- breaking Espree v11.0.0 and later require specific Node.js versions. Older Node.js runtimes will fail.
- breaking Starting with v11.0.0, the `Program` node's `range` property now spans the entire source text, including any leading or trailing whitespace/comments.
- gotcha The `espree.parse()` and `espree.tokenize()` methods handle the `tokens` and `comment` options differently. For `parse()`, you must explicitly set `tokens: true` and `comment: true` in the options to receive `tokens` and `comments` properties on the resulting AST. However, `tokenize()` implicitly enables `tokens: true` regardless of the option's value to ensure tokens are always returned.
Install
-
npm install espree -
yarn add espree -
pnpm add espree
Imports
- espree
import espree from 'espree';
import * as espree from 'espree';
- espree.parse
import { parse } from 'espree'; const ast = parse(code, options);import * as espree from 'espree'; const ast = espree.parse(code, options);
- CommonJS require
import * as espree from 'espree';
const espree = require('espree'); const ast = espree.parse(code, options);
Quickstart
import * as espree from "espree";
const code = `
// This is a comment
function greet(name: string) {
console.log(`Hello, ${name}!`);
}
greet("World");
`;
try {
// Parse with options for range, location, comments, and tokens
const ast = espree.parse(code, {
ecmaVersion: "latest", // Use the latest supported ECMAScript version
sourceType: "module", // Or "script"
range: true, // Include start/end indices for each node
loc: true, // Include line/column for each node
comment: true, // Include comments in the AST
tokens: true // Include tokens in the AST
});
console.log("--- AST (truncated) ---");
// Only log a portion for brevity, the full AST can be very large
console.log(JSON.stringify(ast.body.slice(0, 1), null, 2));
console.log("\n--- First 3 Tokens ---");
if (ast.tokens) {
ast.tokens.slice(0, 3).forEach(token => console.log(token));
} else {
console.log("Tokens not generated. Ensure 'tokens: true' option is set.");
}
console.log("\n--- Comments ---");
if (ast.comments) {
ast.comments.forEach(comment => console.log(comment));
} else {
console.log("Comments not generated. Ensure 'comment: true' option is set.");
}
} catch (e: any) {
console.error("Error parsing code:", e.message);
}