Skip to content
KATO Kei edited this page Mar 2, 2016 · 4 revisions

The source map options can be a little hairy and confusing, so here's a quick guide to help ease the pain.

Options

Escodegen supports generating source maps via four options, shown here with their defaults:

escodegen.generate(ast, {
  sourceMap: undefined, // true or string
  sourceMapRoot: null, // Root directory for sourceMap
  sourceMapWithCode: false, // Set to true to include code AND source map
  sourceContent: undefined, // If set, embedded in source map as code

  // Other configuration options...
});

sourceMap

Source maps will only be generated if sourceMap is truthy. If it's a string then it's treated as a filename which is then used as the source file in the generated map. If it's true, then the resulting source map will use filenames from the AST's loc.source nodes.

sourceMapRoot

Optional, passed right through to the source map file as "sourceRoot". If set, acts as the root for the source files listed in the source map. For example, with the following config:

{
  sourceMap: 'foo.js',
  sourceRoot: '/static/js'
}

The browser will attempt look for /static/js/foo.js when using the source map.

sourceMapWithCode

When using sourceMap, by default the output will include only the source map. If sourceMapWithCode is set to true, the output will include both source map and the generated code, in the form:

{
  code: ..., // Generated source code as a string
  map: ... // Generated source map, a SourceMapGenerator object
}

sourceContent

When sourceMap is set to a string (e.g. filename), this can be set to a string containing the file's source code, and it will be embedded in the source map itself.

Source Map Output

The outputted source map (regardless of the the sourceMapWithCode option) is a SourceMapGenerator from the Mozilla source-map library. See the readme file for further information on how to use this object.

In most cases, you'll simply want to call .toString() on it, which will generate a valid source map JSON string that you can write to a file.

Gotchas

If using the sourceMapWithCode option, the generated code will not be "linked" to the source map file. You'll have to do that yourself, and you have two different ways of accomplishing it:

  1. Use an HTTP header when serving the JS file (X-SourceMap: /path/to/file.js.map)
  2. Append a comment to the JS file (//# sourceMappingUrl=/path/to/file.js.map)

Examples

Using the Acorn parser

var ast = acorn.parse('var a = 1', {
  locations: true,
  sourceFile: 'my_file.js'
});
var output = escodegen.generate(ast, {
  sourceMap: true, // Setting sourceFile in Acorn's options already
                   // gives us filenames.
  sourceMapWithCode: true // Get both code and source map
});

var code = output.code; // Generated source code
var map = output.map.toString(); // Generated source map JSON

Using the Esprima parser

var ast = esprima.parse('var a = 1', {
  loc: true,
  source: 'my_file.js'
});
var output = escodegen.generate(ast, {
  sourceMap: true, // Settings source in esprima's options gives us
                   // filenames already.
  sourceMapWithCode: true // Get both code and source map
});

var code = output.code; // Generated source code
var map = output.map.toString(); // Generated source map JSON

Manually setting filename

var ast = acorn.parse('var a = 1', {
  locations: true,
  sourceFile: 'foo.js' // This adds loc.source to the AST, but it will
                       // be ignored in the output because we set
                       // sourceMap to a string.
});
var output = escodegen.generate(ast, {
  sourceMap: 'bar.js',
  sourceMapWithCode: true
});

var code = output.code; // Generated source code
var map = output.map.toString(); // Source map JSON, pointing to bar.js
                                 // due to settings sourceMap to a string

Embedding source code in source map

var code = 'var a = 1;\n\n\nvar b = 1;'
var ast = acorn.parse(code, {
  locations: true,
  sourceFile: 'foo.js'
});
var output = escodegen.generate(ast, {
  sourceMap: true,
  sourceMapWithCode: true,
  sourceContent: code
});

var newCode = output.code; // Does not include the extra newlines!
var map = output.map.toString();

// The map will now refer back to code, but the code file doesn't need
// to be publicly accessible because it's included in the output.

Generating only the source map

var ast = acorn.parse('var a = 1', { locations: true });
var map = escodegen.generate(ast, { sourceMap: 'my.js' });
var json = map.toString(); // Convert the map to its JSON representation

Multiple files

var ast1 = acorn.parse('var a = 1', {
  locations: true,
  sourceFile: 'a.js'
});
var ast2 = esprima.parse('var b = 1', {
  loc: true,
  source: 'b.js'
});

var astBoth = {
  type: 'Program',
  body: [].concat(ast1.body).concat(ast2.body)
};

var output = escodegen.generate(astBoth, {
  sourceMap: true,
  sourceMapWithCode: true
});

var code = output.code;
var map = output.map.toString();

// Map will now properly point to both a.js and b.js where
// appropriate.

Further Reading

HTML5 Rocks

Source Maps Rev. 3 Spec

Source Map library

Clone this wiki locally