gulp-sourcemaps: the two calls that make a gulp pipeline debuggable again
Sourcemap support for gulpjs.
At a glance
- What is it?
- gulp-sourcemaps wraps a gulp stream between a sourcemaps.init and a sourcemaps.write call so that transformed code keeps pointing back at the original source, with options for inline maps, external map files, loading existing maps, rewriting source paths and generating an identity map when the mappings come out wrong. The package is ISC licensed, its newest release is from 2020, and its contribution policy bans LLM generated issues and pull requests.
- Who is it for?
- Adopt gulp-sourcemaps if your gulp pipeline transforms JavaScript or CSS in ways that break debugging, since the init and write pair is a two line change that restores the mapping between the built file and the source you actually wrote. Do not adopt it for a new project that is moving to another build tool, because the package is specific to gulp and its ecosystem, and do not expect the option set to have grown, since the last release was in 2020.
- Can I use it commercially?
- Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 32 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
init at the start, write at the end
gulp-sourcemaps adds source map support to a gulp pipeline, and the whole API is two calls. The inline case looks like this:
var gulp = require('gulp');
var plugin1 = require('gulp-plugin1');
var plugin2 = require('gulp-plugin2');
var sourcemaps = require('gulp-sourcemaps');
function javascript() {
gulp.src('src/**/*.js')
.pipe(sourcemaps.init())
.pipe(plugin1())
.pipe(plugin2())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dist'));
};
exports.javascript = javascript;The `init` call opens the mapping before your transformations run, and the `write` call closes it after, writing the map into the source file itself when no path is given. The indentation is not decorative in the original examples, since the transformed plugins are visually nested inside the init and write pair, which is a readable way of showing that everything between them participates in the mapping.
The examples in the README all work with Gulp 4, and the Gulp 3 versions live in the README of the v2.6.5 tag, which is a reasonable archival arrangement for a package whose current major targets Gulp 4.
The package itself is a small wrapper rather than a monolith. Its `index.js` exposes the public API and the `src/` directory holds the implementation, and the published files are exactly `index.js` and `src`. The heavy lifting is delegated to two sibling packages, `@gulp-sourcemaps/identity-map` and `@gulp-sourcemaps/map-sources`, alongside the `source-map`, `convert-source-map` and `acorn` libraries.
External map files are a path relative to the destination
The alternative to inlining is writing the map as its own file, and the mechanism is a path passed to `write()`:
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('dist'));The path is relative to the destination, which is the detail that catches people out. With `gulp.dest('dist')` and a write path of `../maps`, the map files land outside the destination directory, in `maps` beside `dist`, rather than inside it. That is the shape you want when the built assets are served from a path where the map has to sit next to the file it describes, and it is a shape that surprises you once if you assume the path is relative to the current working directory.
The difference between the two modes matters more than it first appears. An inline map embeds the mapping in the JavaScript file itself, which means the browser can find it without any extra request, and which also means the map is shipped to anyone who loads the page. An external map is a separate request, which keeps the bundle smaller and lets you decide who gets the mapping.
There is also a comment involved. By default a comment containing or referencing the source map is added to the output, and the `addComment` write option turns that off, which the documentation says is for the case where you load the source maps by header instead.
Loading maps that already exist, and the large file option
Two init options address situations where the pipeline is not starting from scratch.
`loadMaps: true` makes the plugin read existing source maps for the source files. The documentation lists the three forms it understands: inline source maps, source map files referenced by a `sourceMappingURL=` comment, and source map files with the same name plus `.map` in the same directory.
gulp.src('src/**/*.js')
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(plugin1())
.pipe(plugin2())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dist'));This is what makes the plugin composable with tools that already emit maps, since the incoming mapping is picked up and carried through your own transformations rather than starting from nothing.
`largeFile: true` is the other option, and it exists because source map generation on a big file is expensive, since the plugin has to parse and walk the source to work out the mappings.
gulp.src('src/**/*.js')
.pipe(sourcemaps.init({largeFile: true}))Neither of these is exotic, and both are the kind of detail that a plugin documents once and then you need three months later when a build gets slow.
identityMap, the option for when mappings come out wrong
The most interesting feature is the identity source map, and the documentation is unusually candid about when to reach for it.
The `identityMap` method generates a full valid source map that encodes no changes, in place of the default empty source map with no mappings. It is slower, and it applies only to JavaScript and CSS. The instruction is to use it if you get missing or incorrect mappings, for example when debugging.
gulp.src('src/**/*.js')
.pipe(sourcemaps.init())
// An identity sourcemap will be generated at this step
.pipe(sourcemaps.identityMap())
.pipe(plugin1())
.pipe(plugin2())
.pipe(sourcemaps.write('../maps')
.pipe(gulp.dest('public/scripts'));The reasoning is sound. The default empty map means the plugin does not have to work out where everything moved, which is fast, and the mappings accumulate from the plugins that report them. The identity map instead records the position of every token before your transformations run, so any transformation that does not report its own movement still leaves you with a usable, if imprecise, mapping. That trades speed for a floor on quality, and it is exactly the right trade when you are stuck.
There is a deprecation note attached to the same idea. The `identityMap` init option is deprecated in favour of the `sourcemap.identityMap` API, so the method form is the current one, and the init option exists only for older code.
includeContent and sourceRoot are a deployment decision
Two write options decide what a deployed source map actually contains, and they are a deployment conversation rather than a build conversation.
By default the source maps include the source code, and the documentation calls including the content the recommended way, because it just works. Setting `includeContent` to `false` uses the original files instead, which means you have to host those source files yourself and set the correct `sourceRoot`.
That is the trade. Embedded content makes the map self contained, at the cost of shipping your source to anyone who loads the page. Excluding it keeps the payload small, and it keeps your source off the public internet, at the cost of a hosting arrangement and a source root that has to be right.
`sourceRoot` sets the location where the source files are hosted, and the documentation is precise about what it should be: usually a URL, or an absolute URL path, not a local file system path. By default it is empty, or, when `destPath` is set, the relative path from the source map to the source base directory, which the documentation says should work for many development environments. If a relative path is used, an empty string or one starting with a `.`, it is interpreted as relative to the destination, and the plugin rewrites it to a path relative to each source map.
That rewriting is what makes the relative form usable at all, since one map file can be referenced by several built files at different depths.
The compatibility rule for everything in between
There is one constraint that determines whether a pipeline works with this plugin, and it is stated right after the first example: all plugins between `sourcemaps.init()` and `sourcemaps.write()` need to have support for gulp-sourcemaps. The project keeps a list of such plugins in its wiki.
That is the real cost of the design. The plugin is a contract, not a transformer, and the quality of the mapping you get is the quality that the plugins in your stream report. A stream with one plugin that does not participate will produce a map that is silently incomplete for the part it touched, which is the failure mode that is hardest to notice and easiest to blame on the wrong tool.
So the practical workflow when you add a new transform is to check the wiki list, and if your plugin is not on it, to look for a `gulp-sourcemaps` aware alternative or to accept the gap. There is also the `mapSources` method, which gives full control over the source paths by taking a function called for every source with the default source path and the original vinyl file:
.pipe(sourcemaps.mapSources(function(sourcePath, file) {
// source paths are prefixed with '../src/'
return '../src/' + sourcePath;
}))The comment in the example is a warning worth heeding, since it says to be careful with the sources returned or the contents might not be loaded properly.
The state of the package, and its unusual contribution policy
The version numbers need reading carefully. The `package.json` declares version 3.0.0 and requires Node 6 or later, with a dependency on `source-map` at 0.6.0 and a dev dependency on ESLint 5, Mocha 3 and gulp 4. Those are old versions, and the release history explains the shape: v1.5.2 in 2015, v1.7.1 in 2016 with a note about fixing 1.X semver and 0.X Node compatibility, and v3.0.0 on 2020-11-17 with the release name `Security Fixes`.
So the last tagged release is from 2020, while the last push to the repository was on 2026-09-21, and the repository is not archived. That gap means the master branch is moving but the published package is not, and a project deciding between the two has to check what has actually changed.
The other thing to know before you engage with the project is its contribution policy, which is unusual enough to be worth quoting in substance. There are no LLMs for issues, no LLMs for patches or pull requests, and no LLMs for comments on the bug tracker, including translation. English is encouraged but not required, and you are welcome to post in your native language and rely on others to interpret the words with their own translation tools.
That last sentence is a good summary of the project's temperament. It is a maintained package with a clear stance on how contributions should be made, and the policy is a filter you should know about before you spend an evening writing an issue that gets closed.
Editorial conclusion
Adopt gulp-sourcemaps if your gulp pipeline transforms JavaScript or CSS in ways that break debugging, since the init and write pair is a two line change that restores the mapping between the built file and the source you actually wrote. Do not adopt it for a new project that is moving to another build tool, because the package is specific to gulp and its ecosystem, and do not expect the option set to have grown, since the last release was in 2020. Verify first that every plugin in your stream between init and write supports gulp-sourcemaps, that your deployment can serve the external map files if you choose to exclude the source content, and that you read the project's no-LLM contribution policy before opening an issue.
Frequently asked questions
How do I add source map support to a gulp pipeline?
Pipe your stream through `sourcemaps.init()` before the transformations and `sourcemaps.write()` after them. Calling `write()` with no argument embeds the map inline in the source file, while passing a path relative to the destination writes an external map file.
Do all my gulp plugins need to support gulp-sourcemaps?
Yes. The documentation states that all plugins between `sourcemaps.init()` and `sourcemaps.write()` need to have support for gulp-sourcemaps, and the project keeps a list of plugins that do in its wiki.
What does the identityMap option do?
The `sourcemaps.identityMap()` method generates a full valid source map that encodes no changes, instead of the default empty map with no mappings. It is slower and works only for JavaScript and CSS, and the documentation recommends it when you get missing or incorrect mappings while debugging. The `identityMap` init option is deprecated in favour of this method.
How do I stop shipping my source code to the browser?
Pass `includeContent: false` to `sourcemaps.write()` and set `sourceRoot` to the URL where the original files are hosted, which is usually a URL rather than a local file system path. Including the content is the recommended default because it just works, and excluding it means you have to host the sources yourself.
Can gulp-sourcemaps read source maps that already exist?
Yes, with `loadMaps: true` on `sourcemaps.init()`. It supports inline source maps, source map files referenced by a `sourceMappingURL=` comment, and source map files with the same name plus `.map` in the same directory.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gulp-sourcemaps-gulp-sourcemaps)Was this useful?