Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OutputBundle Tagged union with 'type = chunk|asset' #3080

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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') {
askbeka marked this conversation as resolved.
Show resolved Hide resolved
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