-
Notifications
You must be signed in to change notification settings - Fork 334
Source Map Usage
The source map options can be a little hairy and confusing, so here's a quick guide to help ease the pain.
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.
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.
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:
- Use an HTTP header when serving the JS file (
X-SourceMap: /path/to/file.js.map
) - Append a comment to the JS file (
//# sourceMappingUrl=/path/to/file.js.map
)
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.