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

Make chunking consistent when emitting files #3055

Merged
merged 1 commit into from Aug 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
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
22 changes: 17 additions & 5 deletions src/ModuleLoader.ts
Expand Up @@ -90,13 +90,14 @@ function getHasModuleSideEffects(

export class ModuleLoader {
readonly isExternal: IsExternal;
private readonly entryModules: Module[] = [];
private readonly getManualChunk: GetManualChunk;
private readonly graph: Graph;
private readonly hasModuleSideEffects: (id: string, external: boolean) => boolean;
private readonly indexedEntryModules: { index: number; module: Module }[] = [];
private latestLoadModulesPromise: Promise<any> = Promise.resolve();
private readonly manualChunkModules: Record<string, Module[]> = {};
private readonly modulesById: Map<string, Module | ExternalModule>;
private nextEntryModuleIndex = 0;
private readonly pluginDriver: PluginDriver;

constructor(
Expand Down Expand Up @@ -128,6 +129,8 @@ export class ModuleLoader {
manualChunkModulesByAlias: Record<string, Module[]>;
newEntryModules: Module[];
}> {
const firstEntryModuleIndex = this.nextEntryModuleIndex;
this.nextEntryModuleIndex += unresolvedEntryModules.length;
const loadNewEntryModulesPromise = Promise.all(
unresolvedEntryModules.map(({ fileName, id, name }) =>
this.loadEntryModule(id, true).then(module => {
Expand All @@ -145,17 +148,26 @@ export class ModuleLoader {
})
)
).then(entryModules => {
let moduleIndex = firstEntryModuleIndex;
for (const entryModule of entryModules) {
entryModule.isUserDefinedEntryPoint = entryModule.isUserDefinedEntryPoint || isUserDefined;
const existingEntryModule = this.entryModules.find(module => module.id === entryModule.id);
if (!existingEntryModule) {
this.entryModules.push(entryModule);
const existingIndexModule = this.indexedEntryModules.find(
indexedModule => indexedModule.module.id === entryModule.id
);
if (!existingIndexModule) {
this.indexedEntryModules.push({ module: entryModule, index: moduleIndex });
} else {
existingIndexModule.index = Math.min(existingIndexModule.index, moduleIndex);
}
moduleIndex++;
}
this.indexedEntryModules.sort(({ index: indexA }, { index: indexB }) =>
indexA > indexB ? 1 : -1
);
return entryModules;
});
return this.awaitLoadModulesPromise(loadNewEntryModulesPromise).then(newEntryModules => ({
entryModules: this.entryModules,
entryModules: this.indexedEntryModules.map(({ module }) => module),
manualChunkModulesByAlias: this.manualChunkModules,
newEntryModules
}));
Expand Down
37 changes: 37 additions & 0 deletions test/chunking-form/samples/emit-file/emit-chunk-order1/_config.js
@@ -0,0 +1,37 @@
const assert = require('assert');

module.exports = {
description:
'creates a consistent chunking order (needs to be consistent with the other test of this kind)',
options: {
input: 'main',
plugins: {
resolveId(id) {
if (id === 'emitted') {
return id;
}
},
load(id) {
if (id === 'emitted') {
return `import value from './dep.js';
export const id = 'emitted';
console.log(id, value);
`;
}
},
buildStart() {
this.emitFile({
type: 'chunk',
id: 'emitted'
});
},
generateBundle(options, bundle) {
assert.deepStrictEqual(Object.keys(bundle).map(key => bundle[key].name), [
'main',
'dep',
'emitted'
]);
}
}
}
};
@@ -0,0 +1,7 @@
define(['exports'], function (exports) { 'use strict';

var value = 42;

exports.value = value;

});
@@ -0,0 +1,10 @@
define(['exports', './generated-dep'], function (exports, dep) { 'use strict';

const id = 'emitted';
console.log(id, dep.value);

exports.id = id;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,7 @@
define(['./generated-dep', './generated-emitted'], function (dep, emitted) { 'use strict';

console.log(emitted.id);

console.log('main', dep.value);

});
@@ -0,0 +1,5 @@
'use strict';

var value = 42;

exports.value = value;
@@ -0,0 +1,10 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var dep = require('./generated-dep.js');

const id = 'emitted';
console.log(id, dep.value);

exports.id = id;
@@ -0,0 +1,8 @@
'use strict';

var dep = require('./generated-dep.js');
var emitted = require('./generated-emitted.js');

console.log(emitted.id);

console.log('main', dep.value);
@@ -0,0 +1,3 @@
var value = 42;

export { value as v };
@@ -0,0 +1,6 @@
import { v as value } from './generated-dep.js';

const id = 'emitted';
console.log(id, value);

export { id };
@@ -0,0 +1,6 @@
import { v as value } from './generated-dep.js';
import { id } from './generated-emitted.js';

console.log(id);

console.log('main', value);
@@ -0,0 +1,10 @@
System.register([], function (exports) {
'use strict';
return {
execute: function () {

var value = exports('v', 42);

}
};
});
@@ -0,0 +1,15 @@
System.register(['./generated-dep.js'], function (exports) {
'use strict';
var value;
return {
setters: [function (module) {
value = module.v;
}],
execute: function () {

const id = exports('id', 'emitted');
console.log(id, value);

}
};
});
@@ -0,0 +1,18 @@
System.register(['./generated-dep.js', './generated-emitted.js'], function () {
'use strict';
var value, id;
return {
setters: [function (module) {
value = module.v;
}, function (module) {
id = module.id;
}],
execute: function () {

console.log(id);

console.log('main', value);

}
};
});
@@ -0,0 +1 @@
export default 42;
@@ -0,0 +1,3 @@
import { id } from 'emitted';

console.log(id);
@@ -0,0 +1,3 @@
import value from './dep.js';
import './dep2.js';
console.log('main', value);
43 changes: 43 additions & 0 deletions test/chunking-form/samples/emit-file/emit-chunk-order2/_config.js
@@ -0,0 +1,43 @@
const assert = require('assert');

module.exports = {
description:
'creates a consistent chunking order (needs to be consistent with the other test of this kind)',
options: {
input: 'main',
plugins: {
resolveId(id) {
if (id === 'emitted') {
return id;
}
},
load(id) {
if (id === 'emitted') {
return new Promise(resolve =>
setTimeout(
() =>
resolve(`import value from './dep.js';
export const id = 'emitted';
console.log(id, value);
`),
200
)
);
}
},
buildStart() {
this.emitFile({
type: 'chunk',
id: 'emitted'
});
},
generateBundle(options, bundle) {
assert.deepStrictEqual(Object.keys(bundle).map(key => bundle[key].name), [
'main',
'dep',
'emitted'
]);
}
}
}
};
@@ -0,0 +1,7 @@
define(['exports'], function (exports) { 'use strict';

var value = 42;

exports.value = value;

});
@@ -0,0 +1,10 @@
define(['exports', './generated-dep'], function (exports, dep) { 'use strict';

const id = 'emitted';
console.log(id, dep.value);

exports.id = id;

Object.defineProperty(exports, '__esModule', { value: true });

});
@@ -0,0 +1,7 @@
define(['./generated-dep', './generated-emitted'], function (dep, emitted) { 'use strict';

console.log(emitted.id);

console.log('main', dep.value);

});
@@ -0,0 +1,5 @@
'use strict';

var value = 42;

exports.value = value;
@@ -0,0 +1,10 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var dep = require('./generated-dep.js');

const id = 'emitted';
console.log(id, dep.value);

exports.id = id;
@@ -0,0 +1,8 @@
'use strict';

var dep = require('./generated-dep.js');
var emitted = require('./generated-emitted.js');

console.log(emitted.id);

console.log('main', dep.value);
@@ -0,0 +1,3 @@
var value = 42;

export { value as v };
@@ -0,0 +1,6 @@
import { v as value } from './generated-dep.js';

const id = 'emitted';
console.log(id, value);

export { id };
@@ -0,0 +1,6 @@
import { v as value } from './generated-dep.js';
import { id } from './generated-emitted.js';

console.log(id);

console.log('main', value);
@@ -0,0 +1,10 @@
System.register([], function (exports) {
'use strict';
return {
execute: function () {

var value = exports('v', 42);

}
};
});
@@ -0,0 +1,15 @@
System.register(['./generated-dep.js'], function (exports) {
'use strict';
var value;
return {
setters: [function (module) {
value = module.v;
}],
execute: function () {

const id = exports('id', 'emitted');
console.log(id, value);

}
};
});
@@ -0,0 +1,18 @@
System.register(['./generated-dep.js', './generated-emitted.js'], function () {
'use strict';
var value, id;
return {
setters: [function (module) {
value = module.v;
}, function (module) {
id = module.id;
}],
execute: function () {

console.log(id);

console.log('main', value);

}
};
});
@@ -0,0 +1 @@
export default 42;
@@ -0,0 +1,3 @@
import { id } from 'emitted';

console.log(id);
@@ -0,0 +1,3 @@
import value from './dep.js';
import './dep2.js';
console.log('main', value);