Skip to content

Commit

Permalink
Emit sourcemaps as assets and add comments before generateBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Aug 13, 2022
1 parent 1e7f339 commit 6f5f74d
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 53 deletions.
13 changes: 1 addition & 12 deletions cli/run/build.ts
Expand Up @@ -5,7 +5,6 @@ import type { MergedRollupOptions } from '../../src/rollup/types';
import { bold, cyan, green } from '../../src/utils/colors';
import { errOnlyInlineSourcemapsForStdout } from '../../src/utils/error';
import relativeId from '../../src/utils/relativeId';
import { SOURCEMAPPING_URL } from '../../src/utils/sourceMappingURL';
import { handleError, stderr } from '../logging';
import type { BatchWarnings } from './batchWarnings';
import { printTimings } from './timings';
Expand Down Expand Up @@ -37,20 +36,10 @@ export default async function build(
if (output.sourcemap && output.sourcemap !== 'inline') {
handleError(errOnlyInlineSourcemapsForStdout());
}

const { output: outputs } = await bundle.generate(output);
for (const file of outputs) {
let source: string | Uint8Array;
if (file.type === 'asset') {
source = file.source;
} else {
source = file.code;
if (output.sourcemap === 'inline') {
source += `\n//# ${SOURCEMAPPING_URL}=${file.map!.toUrl()}\n`;
}
}
if (outputs.length > 1) process.stdout.write(`\n${cyan(bold(`//→ ${file.fileName}:`))}\n`);
process.stdout.write(source as Buffer);
process.stdout.write(file.type === 'asset' ? file.source : file.code);
}
if (!silent) {
warnings.flush();
Expand Down
30 changes: 2 additions & 28 deletions src/rollup/rollup.ts
Expand Up @@ -14,9 +14,8 @@ import { catchUnfinishedHookActions } from '../utils/hookActions';
import { normalizeInputOptions } from '../utils/options/normalizeInputOptions';
import { normalizeOutputOptions } from '../utils/options/normalizeOutputOptions';
import type { GenericConfigObject } from '../utils/options/options';
import { basename, dirname, resolve } from '../utils/path';
import { dirname, resolve } from '../utils/path';
import { ANONYMOUS_OUTPUT_PLUGIN_PREFIX, ANONYMOUS_PLUGIN_PREFIX } from '../utils/pluginUtils';
import { SOURCEMAPPING_URL } from '../utils/sourceMappingURL';
import { getTimings, initialiseTimers, timeEnd, timeStart } from '../utils/timers';
import type {
NormalizedInputOptions,
Expand Down Expand Up @@ -281,32 +280,7 @@ async function writeOutputFile(
// 'recursive: true' does not throw if the folder structure, or parts of it, already exist
await fs.mkdir(dirname(fileName), { recursive: true });

// TODO Lukas move logic before generateBundle
let writeSourceMapPromise: Promise<void> | undefined;
let source: string | Uint8Array;
if (outputFile.type === 'asset') {
source = outputFile.source;
} else {
source = outputFile.code;
if (outputOptions.sourcemap && outputFile.map) {
let url: string;
if (outputOptions.sourcemap === 'inline') {
url = outputFile.map.toUrl();
} else {
const { sourcemapBaseUrl } = outputOptions;
const sourcemapFileName = `${basename(outputFile.fileName)}.map`;
url = sourcemapBaseUrl
? new URL(sourcemapFileName, sourcemapBaseUrl).toString()
: sourcemapFileName;
writeSourceMapPromise = fs.writeFile(`${fileName}.map`, outputFile.map.toString());
}
if (outputOptions.sourcemap !== 'hidden') {
source += `//# ${SOURCEMAPPING_URL}=${url}\n`;
}
}
}

return Promise.all([fs.writeFile(fileName, source), writeSourceMapPromise]);
return fs.writeFile(fileName, outputFile.type === 'asset' ? outputFile.source : outputFile.code);
}

/**
Expand Down
35 changes: 26 additions & 9 deletions src/utils/renderChunks.ts
Expand Up @@ -19,7 +19,7 @@ import {
replacePlaceholdersWithDefaultAndGetContainedPlaceholders,
replaceSinglePlaceholder
} from './hashPlaceholders';
import { normalize, resolve } from './path';
import { basename, normalize, resolve } from './path';
import { SOURCEMAPPING_URL } from './sourceMappingURL';
import { timeEnd, timeStart } from './timers';

Expand Down Expand Up @@ -72,6 +72,7 @@ export async function renderChunks(
hashesByPlaceholder,
outputBundle,
nonHashedChunksWithPlaceholders,
pluginDriver,
outputOptions
);

Expand Down Expand Up @@ -289,28 +290,44 @@ function addChunksToBundle(
hashesByPlaceholder: Map<string, string>,
outputBundle: OutputBundleWithPlaceholders,
nonHashedChunksWithPlaceholders: RenderedChunkWithPlaceholders[],
{ sourcemap }: NormalizedOutputOptions
pluginDriver: PluginDriver,
options: NormalizedOutputOptions
) {
for (const { chunk, code, fileName, map } of renderedChunksByPlaceholder.values()) {
const updatedCode = replacePlaceholders(code, hashesByPlaceholder);
let updatedCode = replacePlaceholders(code, hashesByPlaceholder);
const finalFileName = replacePlaceholders(fileName, hashesByPlaceholder);
if (map) {
map.file = replacePlaceholders(map.file, hashesByPlaceholder);
updatedCode += emitSourceMapAndGetComment(finalFileName, map, pluginDriver, options);
}
outputBundle[finalFileName] = chunk.generateOutputChunk(updatedCode, map, hashesByPlaceholder);
}
for (const { chunk, code, fileName, map } of nonHashedChunksWithPlaceholders) {
let updatedCode = hashesByPlaceholder.size
? replacePlaceholders(code, hashesByPlaceholder)
: code;
// TODO Lukas use shared code for placeholder files above
// TODO Lukas support other sourcemap options
if (map) {
if (sourcemap === 'inline') {
const url = map.toUrl();
updatedCode += `//# ${SOURCEMAPPING_URL}=${url}\n`;
}
updatedCode += emitSourceMapAndGetComment(fileName, map, pluginDriver, options);
}
outputBundle[fileName] = chunk.generateOutputChunk(updatedCode, map, hashesByPlaceholder);
}
}

function emitSourceMapAndGetComment(
fileName: string,
map: SourceMap,
pluginDriver: PluginDriver,
{ sourcemap, sourcemapBaseUrl }: NormalizedOutputOptions
) {
let url: string;
if (sourcemap === 'inline') {
url = map.toUrl();
} else {
const sourcemapFileName = `${basename(fileName)}.map`;
url = sourcemapBaseUrl
? new URL(sourcemapFileName, sourcemapBaseUrl).toString()
: sourcemapFileName;
pluginDriver.emitFile({ fileName: `${fileName}.map`, source: map.toString(), type: 'asset' });
}
return sourcemap === 'hidden' ? '' : `//# ${SOURCEMAPPING_URL}=${url}\n`;
}
1 change: 0 additions & 1 deletion test/cli/samples/stdout-single-input/_expected.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -1,13 +1,13 @@
const assert = require('assert');

module.exports = {
solo: true,
description: 'includes inline sourcemap comments in generateBundle hook',
options: {
plugins: [
{
name: 'test',
generateBundle(options, bundle) {
assert.deepStrictEqual(Object.keys(bundle), ['main.js']);
assert.strictEqual(
bundle['main.js'].code,
`'use strict';
Expand Down
33 changes: 33 additions & 0 deletions test/function/samples/sourcemap-true-generatebundle/_config.js
@@ -0,0 +1,33 @@
const assert = require('assert');

module.exports = {
description: 'emits sourcemaps before generateBundle hook',
options: {
plugins: [
{
name: 'test',
generateBundle(options, bundle) {
assert.deepStrictEqual(Object.keys(bundle), ['main.js', 'main.js.map']);
assert.strictEqual(
bundle['main.js'].code,
`'use strict';
var main = 42;
module.exports = main;
//# sourceMappingURL=main.js.map
`
);
assert.deepStrictEqual(bundle['main.js.map'], {
fileName: 'main.js.map',
name: undefined,
source:
'{"version":3,"file":"main.js","sources":["main.js"],"sourcesContent":["export default 42;\\n"],"names":[],"mappings":";;AAAA,WAAe,EAAE;;;;"}',
type: 'asset'
});
}
}
],
output: { sourcemap: true }
}
};
@@ -0,0 +1 @@
export default 42;
Expand Up @@ -3,6 +3,6 @@ const assert = require('assert');
module.exports = {
description: 'removes sourcemap comments',
async test(code) {
assert.ok(!code.includes('sourceMappingURL'));
assert.ok(!code.includes('sourceMappingURL=main.js.map'));
}
};
Expand Up @@ -3,6 +3,6 @@ const assert = require('assert');
module.exports = {
description: 'removes existing inline sourcemaps',
async test(code) {
assert.ok(!code.includes('sourceMappingURL'));
assert.ok(!code.includes('sourceMappingURL=data'));
}
};

0 comments on commit 6f5f74d

Please sign in to comment.