rollupjs

How to use MagicString to provide a sourcemap with Rollup's `renderChunk` hook?


I need to do a bit of post-processing on Rollup's output, so I have a plugin that uses magic-string and looks like the following:

{
  name: 'postprocessing',
  renderChunk(code, chunk, opts) {
    const s = new MagicString(code);
    s.replace(...);

    return {
      code: s.toString(),
      map: null,
    }
  }
}

The obvious issue here is that the previously generated sourcemaps will be off, as they do not account for the changes made to the code.

However, it's extremely unclear how one is actually supposed to generate a sourcemap that gets merged into the existing one (for all other changes made in the build pipeline). Every attempt I've made results in Rollup spitting out a completely empty final sourcemap, unless I return null, in which it's merely incorrect due to my replace plugin.

{
  name: 'postprocessing',
  renderChunk(code, chunk, opts) {
    const s = new MagicString(code);
    s.replace(...);

    return {
      code: s.toString(),
      map: s.generateMap({ }), // What options am I supposed to use here?
    }
  }
}

Rollup's outputted sourcemap if I don't return null:

{"version":3,"file":"foo.umd.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

Edit: Oddly, if I set the hires option to true (s.generateMap({ hires: true })), I do get a working sourcemap output, but this isn't really desirable. I'd like the default(?) resolution output. I'm not sure why hires: false (or omitted) would result in an empty sourcmap while hires: true won't.


Solution

  • I'm not sure it's 100% working correctly, but after bumping some dependencies (who rely upon magic-string), I seem to be getting correct sourcemaps with hires set. It's still odd to me that I need to do this, as I'm not after (nor getting) higher resolution in my source maps, but seems to be correctly merging.

    {
      name: 'postprocessing',
      renderChunk(code, chunk, opts) {
        const s = new MagicString(code);
        s.replace(...);
    
        return {
          code: s.toString(),
          map: s.generateMap({ hires: true }), // Kinda weird that this is necessary
        }
      }
    }