Skip to content

Commit 68cdff5

Browse files
committed
renderChunk hook to replace transformChunk
1 parent 4d491a4 commit 68cdff5

File tree

6 files changed

+155
-129
lines changed

6 files changed

+155
-129
lines changed

src/Chunk.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,24 @@ import ExternalModule from './ExternalModule';
1212
import finalisers from './finalisers/index';
1313
import Graph from './Graph';
1414
import Module from './Module';
15-
import { GlobalsOption, OutputOptions, RawSourceMap, RenderedModule } from './rollup/types';
15+
import {
16+
GlobalsOption,
17+
OutputOptions,
18+
RawSourceMap,
19+
RenderChunk,
20+
RenderedModule
21+
} from './rollup/types';
1622
import { Addons } from './utils/addons';
1723
import { toBase64 } from './utils/base64';
1824
import collapseSourcemaps from './utils/collapseSourcemaps';
1925
import error from './utils/error';
2026
import getIndentString from './utils/getIndentString';
2127
import { makeLegal } from './utils/identifierHelpers';
2228
import { basename, dirname, normalize, relative, resolve } from './utils/path';
29+
import renderChunk from './utils/renderChunk';
2330
import { RenderOptions } from './utils/renderHelpers';
2431
import { makeUnique, renderNamePattern } from './utils/renderNamePattern';
2532
import { timeEnd, timeStart } from './utils/timers';
26-
import transformChunk from './utils/transformChunk';
2733

2834
export interface ModuleDeclarations {
2935
exports: ChunkExports;
@@ -1027,7 +1033,7 @@ export default class Chunk {
10271033
this.id = outName;
10281034
}
10291035

1030-
render(options: OutputOptions, addons: Addons) {
1036+
render(options: OutputOptions, addons: Addons, outputChunk: RenderChunk) {
10311037
timeStart('render format', 3);
10321038

10331039
if (!this.renderedSource)
@@ -1105,32 +1111,37 @@ export default class Chunk {
11051111
let map: SourceMap = null;
11061112
const chunkSourcemapChain: RawSourceMap[] = [];
11071113

1108-
return transformChunk(this.graph, this, prevCode, chunkSourcemapChain, options).then(
1109-
(code: string) => {
1110-
if (options.sourcemap) {
1111-
timeStart('sourcemap', 3);
1112-
1113-
let file: string;
1114-
if (options.file) file = resolve(options.sourcemapFile || options.file);
1115-
else if (options.dir) file = resolve(options.dir, this.id);
1116-
else file = resolve(this.id);
1117-
1118-
if (this.graph.pluginDriver.hasLoadersOrTransforms) {
1119-
const decodedMap = magicString.generateDecodedMap({});
1120-
map = collapseSourcemaps(this, file, decodedMap, this.usedModules, chunkSourcemapChain);
1121-
} else {
1122-
map = magicString.generateMap({ file, includeContent: true });
1123-
}
1124-
1125-
map.sources = map.sources.map(normalize);
1126-
1127-
timeEnd('sourcemap', 3);
1114+
return renderChunk({
1115+
graph: this.graph,
1116+
chunk: this,
1117+
renderChunk: outputChunk,
1118+
code: prevCode,
1119+
sourcemapChain: chunkSourcemapChain,
1120+
options
1121+
}).then((code: string) => {
1122+
if (options.sourcemap) {
1123+
timeStart('sourcemap', 3);
1124+
1125+
let file: string;
1126+
if (options.file) file = resolve(options.sourcemapFile || options.file);
1127+
else if (options.dir) file = resolve(options.dir, this.id);
1128+
else file = resolve(this.id);
1129+
1130+
if (this.graph.pluginDriver.hasLoadersOrTransforms) {
1131+
const decodedMap = magicString.generateDecodedMap({});
1132+
map = collapseSourcemaps(this, file, decodedMap, this.usedModules, chunkSourcemapChain);
1133+
} else {
1134+
map = magicString.generateMap({ file, includeContent: true });
11281135
}
11291136

1130-
if (options.compact !== true && code[code.length - 1] !== '\n') code += '\n';
1137+
map.sources = map.sources.map(normalize);
11311138

1132-
return { code, map };
1139+
timeEnd('sourcemap', 3);
11331140
}
1134-
);
1141+
1142+
if (options.compact !== true && code[code.length - 1] !== '\n') code += '\n';
1143+
1144+
return { code, map };
1145+
});
11351146
}
11361147
}

src/rollup/index.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ export default function rollup(
274274
optimized = true;
275275
}
276276

277-
// then name all chunks
277+
// name all chunks
278278
for (let i = 0; i < chunks.length; i++) {
279279
const chunk = chunks[i];
280280
const imports = chunk.getImportIds();
@@ -288,14 +288,6 @@ export default function rollup(
288288
? inputOptions.input[0]
289289
: <string>inputOptions.input)
290290
);
291-
const outputChunk: OutputChunk = {
292-
imports,
293-
exports,
294-
modules,
295-
code: undefined,
296-
map: undefined
297-
};
298-
outputBundle[singleChunk.id] = outputChunk;
299291
} else if (inputOptions.experimentalPreserveModules) {
300292
chunk.generateIdPreserveModules(inputBase);
301293
} else {
@@ -309,7 +301,10 @@ export default function rollup(
309301
}
310302
chunk.generateId(pattern, patternName, addons, outputOptions, outputBundle);
311303
}
304+
312305
outputBundle[chunk.id] = {
306+
fileName: chunk.id,
307+
isEntry: chunk.entryModule !== undefined,
313308
imports,
314309
exports,
315310
modules,
@@ -318,12 +313,10 @@ export default function rollup(
318313
};
319314
}
320315

321-
// render chunk import statements and finalizer wrappers given known names
322316
return Promise.all(
323317
chunks.map(chunk => {
324-
const chunkId = chunk.id;
325-
return chunk.render(outputOptions, addons).then(rendered => {
326-
const outputChunk = <OutputChunk>outputBundle[chunkId];
318+
const outputChunk = <OutputChunk>outputBundle[chunk.id];
319+
return chunk.render(outputOptions, addons, outputChunk).then(rendered => {
327320
outputChunk.code = rendered.code;
328321
outputChunk.map = rendered.map;
329322

src/rollup/types.d.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,25 +129,15 @@ export type TransformHook = (
129129
| void;
130130

131131
export type TransformChunkHook = (
132+
this: PluginContext,
132133
code: string,
133-
options: OutputOptions,
134-
chunk: OutputChunk
134+
options: OutputOptions
135135
) =>
136136
| Promise<{ code: string; map: RawSourceMap } | void>
137137
| { code: string; map: RawSourceMap }
138138
| void
139139
| null;
140140

141-
export type TransformChunkHookBound = (
142-
this: PluginContext,
143-
code: string,
144-
options: OutputOptions,
145-
chunk: OutputChunk
146-
) =>
147-
| Promise<{ code: string; map: RawSourceMap } | void>
148-
| { code: string; map: RawSourceMap }
149-
| void;
150-
151141
export type ResolveDynamicImportHook = (
152142
this: PluginContext,
153143
specifier: string | ESTree.Node,
@@ -354,12 +344,17 @@ export interface RenderedModule {
354344
originalLength: number;
355345
}
356346

357-
export interface OutputChunk {
347+
export interface RenderChunk {
348+
fileName: string;
349+
isEntry: boolean;
358350
imports: string[];
359351
exports: string[];
360352
modules: {
361353
[id: string]: RenderedModule;
362354
};
355+
}
356+
357+
export interface OutputChunk extends RenderChunk {
363358
code: string;
364359
map?: SourceMap;
365360
}

src/utils/renderChunk.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { decode } from 'sourcemap-codec';
2+
import Chunk from '../Chunk';
3+
import Graph from '../Graph';
4+
import { OutputOptions, Plugin, RawSourceMap, RenderChunk } from '../rollup/types';
5+
import error from './error';
6+
7+
export default function renderChunk({
8+
graph,
9+
chunk,
10+
renderChunk,
11+
code,
12+
sourcemapChain,
13+
options
14+
}: {
15+
graph: Graph;
16+
chunk: Chunk;
17+
renderChunk: RenderChunk;
18+
code: string;
19+
sourcemapChain: RawSourceMap[];
20+
options: OutputOptions;
21+
}) {
22+
const renderChunkReducer = (code: string, result: any, plugin: Plugin): string => {
23+
if (result == null) return code;
24+
25+
if (typeof result === 'string')
26+
result = {
27+
code: result,
28+
map: undefined
29+
};
30+
31+
const map = typeof result.map === 'string' ? JSON.parse(result.map) : result.map;
32+
if (map && typeof map.mappings === 'string') map.mappings = decode(map.mappings);
33+
34+
// strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning
35+
if (map !== null) sourcemapChain.push(map || { missing: true, plugin: plugin.name });
36+
37+
return result.code;
38+
};
39+
40+
let inTransformBundle = false;
41+
let inRenderChunk = true;
42+
return graph.pluginDriver
43+
.hookReduceArg0('renderChunk', [code, renderChunk, options], renderChunkReducer)
44+
.then(code => {
45+
inRenderChunk = false;
46+
return graph.pluginDriver.hookReduceArg0(
47+
'transformChunk',
48+
[code, options, chunk],
49+
renderChunkReducer
50+
);
51+
})
52+
.then(code => {
53+
inTransformBundle = true;
54+
return graph.pluginDriver.hookReduceArg0(
55+
'transformBundle',
56+
[code, options, chunk],
57+
renderChunkReducer
58+
);
59+
})
60+
.catch(err => {
61+
if (inRenderChunk) throw err;
62+
error(err, {
63+
code: inTransformBundle ? 'BAD_BUNDLE_TRANSFORMER' : 'BAD_CHUNK_TRANSFORMER',
64+
message: `Error transforming ${(inTransformBundle ? 'bundle' : 'chunk') +
65+
(err.plugin ? ` with '${err.plugin}' plugin` : '')}: ${err.message}`,
66+
plugin: err.plugin
67+
});
68+
});
69+
}

src/utils/transformChunk.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.

test/hooks/index.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,41 @@ module.exports = input;
615615
});
616616
});
617617

618+
it('supports renderChunk in place of transformBundle and transformChunk', () => {
619+
let calledHook = false;
620+
return rollup
621+
.rollup({
622+
input: 'input',
623+
experimentalCodeSplitting: true,
624+
plugins: [
625+
loader({ input: `alert('hello')` }),
626+
{
627+
renderChunk (code, chunk, options) {
628+
calledHook = true;
629+
assert.equal(chunk.fileName, 'input.js');
630+
assert.equal(chunk.isEntry, true);
631+
assert.equal(chunk.exports.length, 0);
632+
assert.ok(chunk.modules['input']);
633+
try {
634+
this.emitAsset('test.ext', 'hello world');
635+
}
636+
catch (e) {
637+
assert.equal(e.code, 'ASSETS_ALREADY_FINALISED');
638+
}
639+
}
640+
}
641+
]
642+
})
643+
.then(bundle => {
644+
return bundle.generate({
645+
format: 'es',
646+
assetFileNames: '[name][extname]'
647+
});
648+
})
649+
.then(() => {
650+
assert.equal(calledHook, true);
651+
});
652+
});
618653

619654
it('passes bundle object to generateBundle hook', () => {
620655
return rollup

0 commit comments

Comments
 (0)