Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Rollup's inline sourcemaps to work?

I am doing a rather strange thing where I am having express directly compile Javascript on every request (please pretend, for the moment, that this is a reasonable thing to do; needless to say, it is for internal development use only).

Unfortunately, though I have tried in several configurations, I cannot get sourcemaps to work.

My express route looks like this:

app.get(`/js/${f.script}`, async (req, res) => {
  try {
    const bundle = await rollup.rollup({
      input: `./examples/src/${f.script}`,
      external: ['React', 'ReactDOM'],
      treeshake: false,
      plugins: [
        resolvePlugin({ jsnext: true, extensions: ['.js', '.jsx'] }),
        commonjsPlugin({ include: 'node_modules/**' }),
        babelPlugin({
          babelrc: false,
          presets: [
            [
              'env',
              { modules: false, targets: { browsers: ['last 2 versions'] } },
            ],
            'react',
          ],
          plugins: ['external-helpers', 'transform-class-properties'],
          exclude: 'node_modules/**',
        }),
      ],
    });

    const { code, map } = await bundle.generate({
      format: 'iife',
      sourcemap: 'inline',
      intro: `var process = {
        env : {
          NODE_ENV : 'development',
        }
      }`,
    });

    res.set('Content-Type', 'text/javascript');
    res.send(
      `${code}\n//@ sourceMappingURL=data:application/json;charset=utf-8,${map}`,
    );
    // eslint-disable-next-line no-console
    console.log(`Served ${f.script}`);
  } catch (e) {
    // eslint-disable-next-line no-console
    console.log('oh bad no no', e);
    res.sendStatus(500);
  }
});

This gets me a script, followed by:

//@ sourceMappingURL=data:application/json;charset=utf-8,{"version":3,"file":...

It's long, but it looks to my relatively untrained eye like a sourcemap. The browser completely ignores it.

I have tried this by just using sourcemap: 'inline' and none of the other bits, which appends no sourcemap to the end. I have now made several goes at manually 'tacking on' the generated sourcemap to the end of the script, but Chrome won't recognize it. Is there a simple syntax error here, or is my entire approach wrong?

like image 946
futuraprime Avatar asked Oct 20 '25 21:10

futuraprime


1 Answers

You're almost there — you're correct that you need to manually append a comment when using bundle.generate (it's done for you automatically if you use bundle.write instead, but that doesn't make sense here).

Most likely, the JSON is causing the data URI to be invalid, so it needs to be rendered as base64. There's a method attached to the map object that lets you do this easily:

res.send(
  `${code}\n//# sourceMappingURL=${map.toUrl()}`,
);

The implementation of toUrl can be seen here.

Note that I'm using //# instead of //@ — both work, but //# is officially 'preferred' (the //@ is a legacy artifact, according to the spec).

like image 76
Rich Harris Avatar answered Oct 26 '25 17:10

Rich Harris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!