Skip to content

Use es-module-lexer to parse ESM #90

@timfish

Description

@timfish

@AbhiPrasad suggested we use es-module-lexer father than acorn:

  • It's specifically designed for the task of parsing imports and exports
  • 8x smaller than acorn (4KiB vs 32KiB gzipped)
  • 20x faster than acorn

A very small single JS file (4KiB gzipped) that includes inlined Web Assembly for very fast source analysis of ECMAScript module syntax only.

For an example of the performance, Angular 1 (720KiB) is fully parsed in 5ms, in comparison to the fastest JS parser, Acorn which takes over 100ms.

Comprehensively handles the JS language grammar while remaining small and fast. - ~10ms per MB of JS cold and ~5ms per MB of JS warm, see benchmarks for more info.

I gave it a test and the entire getEsmExports can be replaced with this:

const { init, parse } = require('es-module-lexer')

async function getEsmExports (moduleSource) {
  await init
  const srcString = moduleSource.toString()
  const [imports, exports] = parse(srcString)

  const reexports = imports
    .map(i => [srcString.slice(i.s, i.e), srcString.slice(i.ss, i.se)])
    .filter(([, full]) => full.match(/export\s*\*\s*from/))
    .map(([file]) => `* from ${file}`)

  const exportNames = exports.map(e => e.n)
  return [...exportNames, ...reexports]
}

A couple of tests fail due to missing parser features:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions