Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
remove processChunks hook for generateBundle, include tree-shaking in…
…fo in generateBundle modules
  • Loading branch information
guybedford committed Jun 4, 2018
1 parent 4d4ec4c commit de83598
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 61 deletions.
19 changes: 14 additions & 5 deletions src/Chunk.ts
Expand Up @@ -19,7 +19,7 @@ import { RenderOptions } from './utils/renderHelpers';
import { Addons } from './utils/addons';
import sha256 from 'hash.js/lib/hash/sha/256';
import ExternalVariable from './ast/variables/ExternalVariable';
import { GlobalsOption, OutputOptions, RawSourceMap } from './rollup/types';
import { GlobalsOption, OutputOptions, RawSourceMap, RenderedModule } from './rollup/types';
import { toBase64 } from './utils/base64';
import { renderNamePattern, makeUnique } from './utils/renderNamePattern';

Expand Down Expand Up @@ -91,6 +91,10 @@ export default class Chunk {
orderedModules: Module[];
linked = false;

renderedModules: {
[moduleId: string]: RenderedModule;
};

// this represents the chunk module wrappings
// which form the output dependency graph
private imports = new Map<Variable, Module | ExternalModule>();
Expand Down Expand Up @@ -152,10 +156,6 @@ export default class Chunk {
return Object.keys(this.exportNames);
}

getModuleIds(): string[] {
return this.orderedModules.map(module => module.id);
}

private inlineChunkDependencies(chunk: Chunk, deep: boolean) {
for (let dep of chunk.dependencies) {
if (dep instanceof ExternalModule) {
Expand Down Expand Up @@ -785,6 +785,7 @@ export default class Chunk {

let hoistedSource = '';

this.renderedModules = Object.create(null);
this.renderedModuleSources = [];

for (let i = 0; i < this.orderedModules.length; i++) {
Expand All @@ -794,6 +795,14 @@ export default class Chunk {
if (options.compact && source.lastLine().indexOf('//') !== -1) source.append('\n');
this.renderedModuleSources.push(source);

const { renderedExports, removedExports } = module.getRenderedExports();
this.renderedModules[module.id] = {
renderedExports,
removedExports,
renderedLength: source.toString().length,
originalLength: module.originalCode.length
};

const namespace = module.getOrCreateNamespace();
if (namespace.needsNamespaceBlock || !source.isEmpty()) {
magicString.addSource(source);
Expand Down
4 changes: 3 additions & 1 deletion src/Graph.ts
Expand Up @@ -238,7 +238,9 @@ export default class Graph {

finaliseAssets(assetFileNames: string) {
const outputBundle: OutputBundle = Object.create(null);
this.assetsById.forEach(asset => finaliseAsset(asset, outputBundle, assetFileNames));
this.assetsById.forEach(asset => {
if (asset.source !== undefined) finaliseAsset(asset, outputBundle, assetFileNames);
});
return outputBundle;
}

Expand Down
9 changes: 5 additions & 4 deletions src/Module.ts
Expand Up @@ -680,14 +680,15 @@ export default class Module {
return null;
}

getIncludedExports(): string[] {
getRenderedExports() {
// only direct exports are counted here, not reexports at all
const includedExports = [];
const renderedExports: string[] = [];
const removedExports: string[] = [];
for (let exportName in this.exports) {
const expt = this.exports[exportName];
if (expt.node.included) includedExports.push(exportName);
(expt.node.included ? renderedExports : removedExports).push(exportName);
}
return includedExports;
return { renderedExports, removedExports };
}

traceExport(name: string): Variable {
Expand Down
1 change: 0 additions & 1 deletion src/ast/nodes/MetaProperty.ts
Expand Up @@ -88,7 +88,6 @@ export default class MetaProperty extends NodeBase {

// support import.meta.ROLLUP_ASSET_URL_[ID]
if (importMetaProperty.startsWith('ROLLUP_ASSET_URL_')) {
console.log('mechanism');
const assetFileName = this.context.getAssetFileName(importMetaProperty.substr(17));
const relPath = normalize(relative(dirname(chunkId), assetFileName));
code.overwrite(parent.start, parent.end, relUrlMechanisms[format](relPath, compact));
Expand Down
67 changes: 29 additions & 38 deletions src/rollup/index.ts
Expand Up @@ -20,8 +20,7 @@ import {
OutputBundle,
OutputFile,
RollupSingleFileBuild,
RollupBuild,
ChunkDefinition
RollupBuild
} from './types';
import getExportMode from '../utils/getExportMode';
import Chunk from '../Chunk';
Expand Down Expand Up @@ -79,10 +78,16 @@ function applyOptionHook(inputOptions: InputOptions, plugin: Plugin) {
return inputOptions;
}

function applyBuildStartHook(graph: Graph) {
return Promise.all(
graph.plugins.map(plugin => plugin.buildStart && plugin.buildStart.call(graph.pluginContext))
).then(() => {});
}

function applyBuildEndHook(graph: Graph, err?: any) {
for (let plugin of graph.plugins) {
if (plugin.buildEnd) plugin.buildEnd.call(graph.pluginContext, err);
}
return Promise.all(
graph.plugins.map(plugin => plugin.buildEnd && plugin.buildEnd.call(graph.pluginContext, err))
).then(() => {});
}

function getInputOptions(rawInputOptions: GenericConfigObject): any {
Expand Down Expand Up @@ -110,43 +115,28 @@ export default function rollup(
initialiseTimers(inputOptions);
const graph = new Graph(inputOptions);

for (let plugin of graph.plugins) {
if (plugin.buildStart) plugin.buildStart.call(graph.pluginContext, inputOptions);
}

timeStart('BUILD', 1);

return graph
.build(
inputOptions.input,
inputOptions.manualChunks,
inputOptions.inlineDynamicImports,
inputOptions.experimentalPreserveModules
)
.then(chunks => {
// run generateBundle hook
const processChunksPlugins = graph.plugins.filter(plugin => plugin.processChunks);
if (processChunksPlugins.length === 0) return chunks;
const processChunksChunks: ChunkDefinition[] = chunks.map(chunk => {
const chunkModules: ChunkDefinition = Object.create(null);
for (let module of chunk.orderedModules)
chunkModules[module.id] = module.getIncludedExports();
return chunkModules;
return applyBuildStartHook(graph)
.then(() => {
return graph.build(
inputOptions.input,
inputOptions.manualChunks,
inputOptions.inlineDynamicImports,
inputOptions.experimentalPreserveModules
);
})
.catch(err => {
return applyBuildEndHook(graph, err).then(() => {
throw err;
});
return Promise.all(
processChunksPlugins.map(plugin =>
plugin.processChunks.call(graph.pluginContext, processChunksChunks)
)
).then(() => {
})
.then(chunks => {
return applyBuildEndHook(graph).then(() => {
return chunks;
});
})
.catch(err => {
applyBuildEndHook(graph, err);
throw err;
})
.then(chunks => {
applyBuildEndHook(graph);
timeEnd('BUILD', 1);

// TODO: deprecate legacy single chunk return
Expand Down Expand Up @@ -229,10 +219,11 @@ export default function rollup(
}

// then name all chunks
for (let chunk of chunks) {
for (let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
const imports = chunk.getImportIds();
const exports = chunk.getExportNames();
const modules = chunk.getModuleIds();
const modules = chunk.renderedModules;

if (chunk === singleInputChunk) {
singleInputChunk.id = basename(
Expand All @@ -244,7 +235,7 @@ export default function rollup(
const outputChunk: OutputChunk = {
imports,
exports,
modules: singleInputChunk.getModuleIds(),
modules,
code: undefined,
map: undefined
};
Expand Down
16 changes: 10 additions & 6 deletions src/rollup/types.d.ts
Expand Up @@ -140,12 +140,11 @@ export interface Plugin {
resolveId?: ResolveIdHook;
missingExport?: MissingExportHook;
transform?: TransformHook;
processChunks?: (this: PluginContext, chunks: ChunkDefinition[]) => void | Promise<void>;
// TODO: deprecate
transformBundle?: TransformChunkHook;
transformChunk?: TransformChunkHook;
buildStart?: (this: PluginContext, options: InputOptions) => void;
buildEnd?: (this: PluginContext, err?: any) => void;
buildStart?: (this: PluginContext, options: InputOptions) => Promise<void> | void;
buildEnd?: (this: PluginContext, err?: any) => Promise<void> | void;
// TODO: deprecate
ongenerate?: (
this: PluginContext,
Expand Down Expand Up @@ -306,14 +305,19 @@ export type SerializedTimings = { [label: string]: number };

export type OutputFile = string | Buffer | OutputChunk;

export interface ChunkDefinition {
[moduleId: string]: string[];
export interface RenderedModule {
renderedExports: string[];
removedExports: string[];
renderedLength: number;
originalLength: number;
}

export interface OutputChunk {
imports: string[];
exports: string[];
modules: string[];
modules: {
[id: string]: RenderedModule;
};
code: string;
map?: SourceMap;
}
Expand Down
18 changes: 12 additions & 6 deletions test/hooks/index.js
Expand Up @@ -340,7 +340,7 @@ module.exports = input;
assetId = this.emitAsset('test.ext');
return '';
},
processChunks () {
generateBundle () {
this.setAssetSource(assetId, 'hello world');
}
}
Expand Down Expand Up @@ -539,7 +539,7 @@ module.exports = input;
});


it('supports processBundle hook including reporting tree-shaken exports', () => {
it('supports processBundle hook including reporting rendered exports and source length', () => {
return rollup
.rollup({
input: 'input',
Expand All @@ -550,12 +550,18 @@ module.exports = input;
dep: `export var a = 1; export var b = 2;`
}),
{
processChunks (chunks) {
assert.equal(chunks.length, 1);
generateBundle (options, outputBundle, isWrite) {
const chunk = outputBundle['input.js'];

// can detect that b has been tree-shaken this way
assert.equal(chunks[0]['dep'][0], 'a');
assert.equal(chunks[0]['dep'].length, 1);
assert.equal(chunk.modules['dep'].renderedExports[0], 'a');
assert.equal(chunk.modules['dep'].renderedExports.length, 1);

assert.equal(chunk.modules['dep'].removedExports[0], 'b');
assert.equal(chunk.modules['dep'].removedExports.length, 1);

assert.equal(chunk.modules['dep'].renderedLength, 10);
assert.equal(chunk.modules['dep'].originalLength, 35);
}
}
]
Expand Down

0 comments on commit de83598

Please sign in to comment.