Skip to content

Commit

Permalink
feat: OutputBundle Tagged union with 'type = chunk|asset'
Browse files Browse the repository at this point in the history
  • Loading branch information
Beknar Askarov committed Sep 7, 2019
1 parent 1429d57 commit 38c3fed
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 29 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1,3 +1,4 @@
test/*/samples/**/*.js
!test/*/samples/**/_config.js
test/leak/index.js
**/*.ts
10 changes: 5 additions & 5 deletions cli/run/build.ts
@@ -1,7 +1,7 @@
import ms from 'pretty-ms';
import tc from 'turbocolor';
import * as rollup from '../../src/node-entry';
import { InputOptions, OutputAsset, OutputChunk, OutputOptions, RollupBuild, SourceMap } from '../../src/rollup/types';
import { InputOptions, OutputOptions, RollupBuild, SourceMap } from '../../src/rollup/types';
import relativeId from '../../src/utils/relativeId';
import { handleError, stderr } from '../logging';
import SOURCEMAPPING_URL from '../sourceMappingUrl';
Expand Down Expand Up @@ -49,12 +49,12 @@ export default function build(
return bundle.generate(output).then(({ output: outputs }) => {
for (const file of outputs) {
let source: string | Buffer;
if ((file as OutputAsset).isAsset) {
source = (file as OutputAsset).source;
if (file.type === 'asset') {
source = file.source;
} else {
source = (file as OutputChunk).code;
source = file.code;
if (output.sourcemap === 'inline') {
source += `\n//# ${SOURCEMAPPING_URL}=${((file as OutputChunk)
source += `\n//# ${SOURCEMAPPING_URL}=${(file
.map as SourceMap).toUrl()}\n`;
}
}
Expand Down
5 changes: 3 additions & 2 deletions docs/02-javascript-api.md
Expand Up @@ -25,12 +25,12 @@ async function build() {
const { output } = await bundle.generate(outputOptions);

for (const chunkOrAsset of output) {
if (chunkOrAsset.isAsset) {
if (chunkOrAsset.type === 'asset') {
// For assets, this contains
// {
// isAsset: true, // signifies that this is an asset
// fileName: string, // the asset file name
// source: string | Buffer // the asset source
// type: 'asset' // signifies that this is an asset
// }
console.log('Asset', chunkOrAsset);
} else {
Expand All @@ -54,6 +54,7 @@ async function build() {
// };
// },
// name: string // the name of this chunk as used in naming patterns
// type: 'chunk', // signifies that this is a chunk
// }
console.log('Chunk', chunkOrAsset.modules);
}
Expand Down
7 changes: 4 additions & 3 deletions docs/05-plugin-development.md
Expand Up @@ -123,8 +123,8 @@ Called at the end of `bundle.generate()` or immediately before the files are wri
// AssetInfo
{
fileName: string,
isAsset: true,
source: string | Buffer
source: string | Buffer,
type: 'asset',
}
// ChunkInfo
Expand All @@ -146,7 +146,8 @@ Called at the end of `bundle.generate()` or immediately before the files are wri
originalLength: number
},
},
name: string
name: string,
type: 'chunk',
}
```

Expand Down
17 changes: 7 additions & 10 deletions src/rollup/index.ts
Expand Up @@ -168,7 +168,8 @@ function assignChunksToBundle(
modules: chunk.renderedModules,
get name() {
return chunk.getChunkName();
}
},
type: 'chunk'
} as OutputChunk;
}
return outputBundle as OutputBundle;
Expand Down Expand Up @@ -301,7 +302,7 @@ export default async function rollup(rawInputOptions: GenericConfigObject): Prom
let chunkCnt = 0;
for (const fileName of Object.keys(bundle)) {
const file = bundle[fileName];
if ((file as OutputAsset).isAsset) continue;
if (file.type === 'asset') continue;
chunkCnt++;
if (chunkCnt > 1) break;
}
Expand Down Expand Up @@ -343,10 +344,10 @@ enum SortingFileType {
}

function getSortingFileType(file: OutputAsset | OutputChunk): SortingFileType {
if ((file as OutputAsset).isAsset) {
if (file.type === 'asset') {
return SortingFileType.ASSET;
}
if ((file as OutputChunk).isEntry) {
if (file.isEntry) {
return SortingFileType.ENTRY_CHUNK;
}
return SortingFileType.SECONDARY_CHUNK;
Expand All @@ -367,10 +368,6 @@ function createOutput(outputBundle: Record<string, OutputChunk | OutputAsset | {
};
}

function isOutputAsset(file: OutputAsset | OutputChunk): file is OutputAsset {
return (file as OutputAsset).isAsset === true;
}

function writeOutputFile(
graph: Graph,
build: RollupBuild,
Expand All @@ -383,7 +380,7 @@ function writeOutputFile(
);
let writeSourceMapPromise: Promise<void>;
let source: string | Buffer;
if (isOutputAsset(outputFile)) {
if (outputFile.type === 'asset') {
source = outputFile.source;
} else {
source = outputFile.code;
Expand All @@ -403,7 +400,7 @@ function writeOutputFile(
.then(() => writeSourceMapPromise)
.then(
(): any =>
!isOutputAsset(outputFile) &&
outputFile.type === 'chunk' &&
graph.pluginDriver.hookSeq('onwrite', [
{
bundle: build,
Expand Down
10 changes: 8 additions & 2 deletions src/rollup/types.d.ts
Expand Up @@ -314,8 +314,12 @@ export interface OutputBundle {
[fileName: string]: OutputAsset | OutputChunk;
}

export interface FilePlaceholder {
type: 'placeholder';
}

export interface OutputBundleWithPlaceholders {
[fileName: string]: OutputAsset | OutputChunk | {};
[fileName: string]: OutputAsset | OutputChunk | FilePlaceholder;
}

interface OnGenerateOptions extends OutputOptions {
Expand Down Expand Up @@ -487,10 +491,11 @@ export interface SerializedTimings {
}

export interface OutputAsset {
code?: undefined;
fileName: string;
/** @deprecated Accessing "isAsset" on files in the bundle is deprecated, please use "type === \'asset\'" instead */
isAsset: true;
source: string | Buffer;
type: 'asset';
}

export interface RenderedModule {
Expand Down Expand Up @@ -520,6 +525,7 @@ export interface RenderedChunk extends PreRenderedChunk {
export interface OutputChunk extends RenderedChunk {
code: string;
map?: SourceMap;
type: 'chunk';
}

export interface SerializablePluginCache {
Expand Down
25 changes: 19 additions & 6 deletions src/utils/FileEmitter.ts
Expand Up @@ -2,7 +2,7 @@ import sha256 from 'hash.js/lib/hash/sha/256';
import Chunk from '../Chunk';
import Graph from '../Graph';
import Module from '../Module';
import { OutputAsset, OutputBundleWithPlaceholders } from '../rollup/types';
import { FilePlaceholder, OutputBundleWithPlaceholders } from '../rollup/types';
import { BuildPhase } from './buildPhase';
import {
errAssetNotFinalisedForFileName,
Expand Down Expand Up @@ -78,8 +78,8 @@ interface EmittedFile {

type ConsumedFile = ConsumedChunk | ConsumedAsset;

export const FILE_PLACEHOLDER = {
isPlaceholder: true
export const FILE_PLACEHOLDER: FilePlaceholder = {
type: 'placeholder'
};

function hasValidType(
Expand Down Expand Up @@ -318,17 +318,30 @@ export class FileEmitter {
// We must not modify the original assets to avoid interaction between outputs
const assetWithFileName = { ...consumedFile, source, fileName };
this.filesByReferenceId.set(referenceId, assetWithFileName);
output.bundle[fileName] = { fileName, isAsset: true, source };
const graph = this.graph;
output.bundle[fileName] = {
fileName,
get isAsset(): true {
graph.warnDeprecation(
'Accessing "isAsset" on files in the bundle is deprecated, please use "type === \'asset\'" instead',
false
);

return true;
},
source,
type: 'asset'
};
}

private findExistingAssetFileNameWithSource(
bundle: OutputBundleWithPlaceholders,
source: string | Buffer
): string | null {
for (const fileName of Object.keys(bundle)) {
const outputFile = bundle[fileName] as OutputAsset;
const outputFile = bundle[fileName];
if (
outputFile.isAsset &&
outputFile.type === 'asset' &&
(Buffer.isBuffer(source) && Buffer.isBuffer(outputFile.source)
? source.equals(outputFile.source)
: source === outputFile.source)
Expand Down
15 changes: 15 additions & 0 deletions test/form/samples/deprecated/emit-asset/_config.js
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
const assert = require('assert');

module.exports = {
description: 'supports emitting assets from plugin hooks',
Expand All @@ -18,6 +19,20 @@ module.exports = {
fs.readFileSync(id)
)};`;
}
},
generateBundle(options, outputBundle) {
const keys = Object.keys(outputBundle);
assert.strictEqual(keys.length, 2);
assert.strictEqual(keys[0], 'assets/logo-25585ac1.svg');
const asset = outputBundle[keys[0]];
assert.strictEqual(asset.fileName, 'assets/logo-25585ac1.svg');
assert.strictEqual(asset.isAsset, true);
assert.strictEqual(asset.type, 'asset');
assert.ok(
asset.source.equals(fs.readFileSync(path.resolve(__dirname, 'logo.svg'))),
'asset has correct source'
);
assert.ok(keys[1].endsWith('.js'), `${keys[1]} ends with ".js"`);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/form/samples/emit-asset-file/_config.js
Expand Up @@ -26,7 +26,7 @@ module.exports = {
assert.strictEqual(keys[0], 'assets/logo-25585ac1.svg');
const asset = outputBundle[keys[0]];
assert.strictEqual(asset.fileName, 'assets/logo-25585ac1.svg');
assert.strictEqual(asset.isAsset, true);
assert.strictEqual(asset.type, 'asset');
assert.ok(
asset.source.equals(fs.readFileSync(path.resolve(__dirname, 'logo.svg'))),
'asset has correct source'
Expand Down

0 comments on commit 38c3fed

Please sign in to comment.