Skip to content

Commit a22b00e

Browse files
nkzawaTheLarkInn
authored andcommitted
Dynamic entry support (webpack#3634)
* enable to set a function to entry option * add tests for entry function * fix style * fix identifier and readableIdentifier of MultiModule * use arrow functions * use arrow function * remove incorrect new operators * fix Validation tests
1 parent 42b95d9 commit a22b00e

15 files changed

Lines changed: 153 additions & 17 deletions

‎lib/DynamicEntryPlugin.js‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
MIT License http://www.opensource.org/licenses/mit-license.php
3+
Author Naoyuki Kanezawa @nkzawa
4+
*/
5+
"use strict";
6+
7+
const MultiEntryDependency = require("./dependencies/MultiEntryDependency");
8+
const SingleEntryDependency = require("./dependencies/SingleEntryDependency");
9+
const MultiModuleFactory = require("./MultiModuleFactory");
10+
const MultiEntryPlugin = require("./MultiEntryPlugin");
11+
const SingleEntryPlugin = require("./SingleEntryPlugin");
12+
13+
class DynamicEntryPlugin {
14+
constructor(context, entry) {
15+
this.context = context;
16+
this.entry = entry;
17+
}
18+
19+
apply(compiler) {
20+
compiler.plugin("compilation", (compilation, params) => {
21+
const multiModuleFactory = new MultiModuleFactory();
22+
const normalModuleFactory = params.normalModuleFactory;
23+
24+
compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory);
25+
compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory);
26+
});
27+
28+
compiler.plugin("make", (compilation, callback) => {
29+
const addEntry = (entry, name) => {
30+
const dep = DynamicEntryPlugin.createDependency(entry, name);
31+
return new Promise((resolve, reject) => {
32+
compilation.addEntry(this.context, dep, name, (err) => {
33+
if(err) return reject(err);
34+
resolve();
35+
});
36+
})
37+
};
38+
39+
Promise.resolve(this.entry()).then((entry) => {
40+
if(typeof entry === "string" || Array.isArray(entry)) {
41+
addEntry(entry, "main").then(() => callback(), callback);
42+
} else if(typeof entry === "object") {
43+
Promise.all(Object.keys(entry).map((name) => {
44+
return addEntry(entry[name], name);
45+
})).then(() => callback(), callback);
46+
}
47+
})
48+
});
49+
}
50+
}
51+
52+
module.exports = DynamicEntryPlugin;
53+
54+
DynamicEntryPlugin.createDependency = function(entry, name) {
55+
if(Array.isArray(entry))
56+
return MultiEntryPlugin.createDependency(entry, name);
57+
else
58+
return SingleEntryPlugin.createDependency(entry, name);
59+
};

‎lib/EntryOptionPlugin.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
const SingleEntryPlugin = require("./SingleEntryPlugin");
88
const MultiEntryPlugin = require("./MultiEntryPlugin");
9+
const DynamicEntryPlugin = require("./DynamicEntryPlugin");
910

1011
module.exports = class EntryOptionPlugin {
1112
apply(compiler) {
@@ -21,6 +22,8 @@ module.exports = class EntryOptionPlugin {
2122
compiler.apply(itemToPlugin(entry, "main"));
2223
} else if(typeof entry === "object") {
2324
Object.keys(entry).forEach(name => compiler.apply(itemToPlugin(entry[name], name)));
25+
} else if(typeof entry === "function") {
26+
compiler.apply(new DynamicEntryPlugin(context, entry));
2427
}
2528
return true;
2629
});

‎lib/MultiEntryPlugin.js‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@ module.exports = class MultiEntryPlugin {
2424
compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory);
2525
});
2626
compiler.plugin("make", (compilation, callback) => {
27-
compilation.addEntry(this.context, new MultiEntryDependency(this.entries.map((e, idx) => {
28-
const dep = new SingleEntryDependency(e);
29-
dep.loc = `${this.name}:${(100000 + idx)}`;
30-
return dep;
31-
}, this), this.name), this.name, callback);
27+
const dep = MultiEntryPlugin.createDependency(this.entries, this.name);
28+
compilation.addEntry(this.context, dep, this.name, callback);
3229
});
3330
}
31+
32+
static createDependency(entries, name) {
33+
return new MultiEntryDependency(entries.map((e, idx) => {
34+
const dep = new SingleEntryDependency(e);
35+
dep.loc = name + ":" + (100000 + idx);
36+
return dep;
37+
}), name);
38+
}
3439
}

‎lib/MultiModule.js‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ MultiModule.prototype = Object.create(Module.prototype);
1919
MultiModule.prototype.constructor = MultiModule;
2020

2121
MultiModule.prototype.identifier = function() {
22-
return "multi " + this.name;
22+
return "multi " + this.dependencies.map((d) => d.request).join(" ");
2323
};
2424

25-
MultiModule.prototype.readableIdentifier = function() {
26-
return "multi " + this.name;
25+
MultiModule.prototype.readableIdentifier = function(requestShortener) {
26+
return "multi " + this.dependencies.map((d) => {
27+
return requestShortener.shorten(d.request);
28+
}).join(" ");
2729
};
2830

2931
MultiModule.prototype.disconnect = function disconnect() {

‎lib/SingleEntryPlugin.js‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ class SingleEntryPlugin {
2020
});
2121

2222
compiler.plugin("make", (compilation, callback) => {
23-
const dep = new SingleEntryDependency(this.entry);
24-
dep.loc = this.name;
23+
const dep = SingleEntryPlugin.createDependency(this.entry, this.name);
2524
compilation.addEntry(this.context, dep, this.name, callback);
2625
});
2726
}
27+
28+
static createDependency(entry, name) {
29+
const dep = new SingleEntryDependency(entry);
30+
dep.loc = name;
31+
return dep;
32+
}
2833
}
2934

3035
module.exports = SingleEntryPlugin

‎schemas/webpackOptionsSchema.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@
6868
}
6969
],
7070
"description": "All modules are loaded upon startup. The last one is exported."
71+
},
72+
{
73+
"description": "function returning an entry object or a promise.",
74+
"instanceof": "Function"
7175
}
7276
]
7377
},

‎test/Validation.test.js‎

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe("Validation", function() {
2020
config: {},
2121
message: [
2222
" - configuration misses the property 'entry'.",
23-
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]",
23+
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function",
2424
" The entry point(s) of the compilation."
2525
]
2626
}, {
@@ -30,13 +30,15 @@ describe("Validation", function() {
3030
},
3131
message: [
3232
" - configuration.entry should be one of these:",
33-
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]",
33+
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function",
3434
" The entry point(s) of the compilation.",
3535
" Details:",
3636
" * configuration.entry should be an object.",
3737
" * configuration.entry should not be empty.",
3838
" * configuration.entry should be an array:",
39-
" [non-empty string]"
39+
" [non-empty string]",
40+
" * configuration.entry should be an instance of function",
41+
" function returning an entry object or a promise.."
4042
]
4143
}, {
4244
name: "empty entry bundle array",
@@ -47,7 +49,7 @@ describe("Validation", function() {
4749
},
4850
message: [
4951
" - configuration.entry should be one of these:",
50-
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]",
52+
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function",
5153
" The entry point(s) of the compilation.",
5254
" Details:",
5355
" * configuration.entry['bundle'] should be a string.",
@@ -56,7 +58,9 @@ describe("Validation", function() {
5658
" non-empty string | [non-empty string]",
5759
" * configuration.entry should be a string.",
5860
" * configuration.entry should be an array:",
59-
" [non-empty string]"
61+
" [non-empty string]",
62+
" * configuration.entry should be an instance of function",
63+
" function returning an entry object or a promise.."
6064
]
6165
}, {
6266
name: "invalid instanceof",
@@ -79,12 +83,14 @@ describe("Validation", function() {
7983
},
8084
message: [
8185
" - configuration.entry should be one of these:",
82-
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]",
86+
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function",
8387
" The entry point(s) of the compilation.",
8488
" Details:",
8589
" * configuration.entry should be an object.",
8690
" * configuration.entry should be a string.",
8791
" * configuration.entry[0] should be a string.",
92+
" * configuration.entry should be an instance of function",
93+
" function returning an entry object or a promise..",
8894
" - configuration.output.filename should be a string."
8995
]
9096
}, {
@@ -99,12 +105,14 @@ describe("Validation", function() {
99105
}],
100106
message: [
101107
" - configuration[0].entry should be one of these:",
102-
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string]",
108+
" object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function",
103109
" The entry point(s) of the compilation.",
104110
" Details:",
105111
" * configuration[0].entry should be an object.",
106112
" * configuration[0].entry should be a string.",
107113
" * configuration[0].entry[0] should be a string.",
114+
" * configuration[0].entry should be an instance of function",
115+
" function returning an entry object or a promise..",
108116
" - configuration[1].output.filename should be a string."
109117
]
110118
}, {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
it("should compile", (done) => {
2+
done()
3+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
it("should compile", (done) => {
2+
done()
3+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
findBundle: function() {
3+
return [
4+
"./a.js",
5+
"./b.js"
6+
]
7+
}
8+
};

0 commit comments

Comments
 (0)