Skip to content

Commit 45f6592

Browse files
fix: empty and multiple entries support (#2920)
1 parent 4b48017 commit 45f6592

12 files changed

+246
-533
lines changed

lib/utils/DevServerPlugin.js

+23-21
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class DevServerPlugin {
3737
: '';
3838
/** @type {string} */
3939
let path = '';
40+
4041
// only add the path if it is not default
4142
if (
4243
options.client &&
@@ -45,11 +46,13 @@ class DevServerPlugin {
4546
) {
4647
path = `&path=${options.client.path}`;
4748
}
49+
4850
/** @type {string} */
4951
const port =
5052
options.client && options.client.port
5153
? `&port=${options.client.port}`
5254
: '';
55+
5356
/** @type {string} */
5457
const clientEntry = `${require.resolve(
5558
'../../client/default/'
@@ -119,14 +122,22 @@ class DevServerPlugin {
119122
*/
120123
// eslint-disable-next-line no-shadow
121124
const checkInject = (option, _config, defaultValue) => {
122-
if (typeof option === 'boolean') return option;
123-
if (typeof option === 'function') return option(_config);
125+
if (typeof option === 'boolean') {
126+
return option;
127+
}
128+
129+
if (typeof option === 'function') {
130+
return option(_config);
131+
}
132+
124133
return defaultValue;
125134
};
126135

127136
const compilerOptions = compiler.options;
137+
128138
compilerOptions.plugins = compilerOptions.plugins || [];
129-
/** @type {Boolean} */
139+
140+
/** @type {boolean} */
130141
const isWebTarget = compilerOptions.externalsPresets
131142
? compilerOptions.externalsPresets.web
132143
: [
@@ -138,6 +149,7 @@ class DevServerPlugin {
138149
undefined,
139150
null,
140151
].includes(compilerOptions.target);
152+
141153
/** @type {Entry} */
142154
const additionalEntries = checkInject(
143155
options.injectClient,
@@ -153,24 +165,12 @@ class DevServerPlugin {
153165

154166
// use a hook to add entries if available
155167
if (EntryPlugin) {
156-
compiler.hooks.make.tapPromise('DevServerPlugin', (compilation) =>
157-
Promise.all(
158-
additionalEntries.map(
159-
(entry) =>
160-
new Promise((resolve, reject) => {
161-
compilation.addEntry(
162-
compiler.context,
163-
EntryPlugin.createDependency(entry, {}),
164-
{}, // global entry
165-
(err) => {
166-
if (err) return reject(err);
167-
resolve();
168-
}
169-
);
170-
})
171-
)
172-
)
173-
);
168+
for (const additionalEntry of additionalEntries) {
169+
new EntryPlugin(compiler.context, additionalEntry, {
170+
// eslint-disable-next-line no-undefined
171+
name: undefined,
172+
}).apply(compiler);
173+
}
174174
} else {
175175
compilerOptions.entry = prependEntry(
176176
compilerOptions.entry || './src',
@@ -185,6 +185,7 @@ class DevServerPlugin {
185185
const providePlugin = new webpack.ProvidePlugin({
186186
__webpack_dev_server_client__: getSocketClientPath(options),
187187
});
188+
188189
providePlugin.apply(compiler);
189190

190191
if (
@@ -195,6 +196,7 @@ class DevServerPlugin {
195196
) {
196197
// apply the HMR plugin, if it didn't exist before.
197198
const plugin = new webpack.HotModuleReplacementPlugin();
199+
198200
plugin.apply(compiler);
199201
}
200202
}

lib/utils/updateCompiler.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const DevServerPlugin = require('./DevServerPlugin');
44

55
function updateCompiler(compiler, options) {
66
const compilers = compiler.compilers || [compiler];
7+
78
// eslint-disable-next-line no-shadow
89
compilers.forEach((compiler) => {
910
new DevServerPlugin(options).apply(compiler);

test/e2e/DevServer.test.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
3+
const testBin = require('../helpers/test-bin');
4+
const isWebpack5 = require('../helpers/isWebpack5');
5+
6+
describe('DevServer', () => {
7+
const webpack5Test = isWebpack5 ? it : it.skip;
8+
9+
it('should add devServer entry points to a single entry point', (done) => {
10+
testBin('--config ./test/fixtures/dev-server/default-config.js')
11+
.then((output) => {
12+
expect(output.exitCode).toEqual(0);
13+
expect(output.stderr).toContain('client/default/index.js?');
14+
done();
15+
})
16+
.catch(done);
17+
});
18+
19+
it('should add devServer entry points to a multi entry point object', (done) => {
20+
testBin(
21+
'--config ./test/fixtures/dev-server/multi-entry.js --stats=verbose'
22+
)
23+
.then((output) => {
24+
expect(output.exitCode).toEqual(0);
25+
expect(output.stderr).toContain('client/default/index.js?');
26+
expect(output.stderr).toContain('foo.js');
27+
done();
28+
})
29+
.catch(done);
30+
});
31+
32+
webpack5Test('should supports entry as descriptor', (done) => {
33+
testBin(
34+
'--config ./test/fixtures/entry-as-descriptor/webpack.config --stats detailed'
35+
)
36+
.then((output) => {
37+
expect(output.exitCode).toEqual(0);
38+
expect(output.stderr).toContain('foo.js');
39+
done();
40+
})
41+
.catch(done);
42+
});
43+
44+
it('should only prepends devServer entry points to "web" target', (done) => {
45+
testBin(
46+
'--config ./test/fixtures/dev-server/default-config.js --target web'
47+
)
48+
.then((output) => {
49+
expect(output.exitCode).toEqual(0);
50+
expect(output.stderr).toContain('client/default/index.js?');
51+
expect(output.stderr).toContain('foo.js');
52+
done();
53+
})
54+
.catch(done);
55+
});
56+
57+
it('should not prepend devServer entry points to "node" target', (done) => {
58+
testBin(
59+
'--config ./test/fixtures/dev-server/default-config.js --target node'
60+
)
61+
.then((output) => {
62+
expect(output.exitCode).toEqual(0);
63+
expect(output.stderr).not.toContain('client/default/index.js?');
64+
expect(output.stderr).toContain('foo.js');
65+
done();
66+
})
67+
.catch(done);
68+
});
69+
70+
it('should prepends the hot runtime to "node" target as well', (done) => {
71+
testBin(
72+
'--config ./test/fixtures/dev-server/default-config.js --target node --hot'
73+
)
74+
.then((output) => {
75+
expect(output.exitCode).toEqual(0);
76+
expect(output.stderr).toContain('webpack/hot/dev-server');
77+
done();
78+
})
79+
.catch(done);
80+
});
81+
82+
it('does not use client.path when default', (done) => {
83+
testBin('--config ./test/fixtures/dev-server/client-default-path-config.js')
84+
.then((output) => {
85+
expect(output.exitCode).toEqual(0);
86+
expect(output.stderr).not.toContain('&path=/ws');
87+
done();
88+
})
89+
.catch(done);
90+
});
91+
92+
it('should use client.path when custom', (done) => {
93+
testBin('--config ./test/fixtures/dev-server/client-custom-path-config.js')
94+
.then((output) => {
95+
expect(output.exitCode).toEqual(0);
96+
expect(output.stderr).toContain('&path=/custom/path');
97+
done();
98+
})
99+
.catch(done);
100+
});
101+
102+
webpack5Test(
103+
'should prepend devServer entry points depending on targetProperties',
104+
(done) => {
105+
testBin('--config ./test/fixtures/dev-server/target-config.js')
106+
.then((output) => {
107+
expect(output.exitCode).toEqual(0);
108+
expect(output.stderr).toContain('client/default/index.js');
109+
done();
110+
})
111+
.catch(done);
112+
}
113+
);
114+
});

test/fixtures/dev-server/bar.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
console.log('I am bar');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const { resolve } = require('path');
4+
5+
module.exports = {
6+
mode: 'development',
7+
stats: 'detailed',
8+
entry: resolve(__dirname, './foo.js'),
9+
devServer: {
10+
client: {
11+
path: '/custom/path',
12+
},
13+
transportMode: {
14+
server: 'sockjs',
15+
client: 'sockjs',
16+
},
17+
},
18+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const { resolve } = require('path');
4+
5+
module.exports = {
6+
mode: 'development',
7+
stats: 'detailed',
8+
entry: resolve(__dirname, './foo.js'),
9+
devServer: {
10+
client: {
11+
path: '/ws',
12+
},
13+
transportMode: {
14+
server: 'sockjs',
15+
client: 'sockjs',
16+
},
17+
},
18+
};
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const { resolve } = require('path');
4+
5+
module.exports = {
6+
mode: 'development',
7+
stats: 'detailed',
8+
entry: resolve(__dirname, './foo.js'),
9+
devServer: {
10+
client: {
11+
path: '/custom/path',
12+
},
13+
transportMode: {
14+
server: 'sockjs',
15+
client: 'sockjs',
16+
},
17+
},
18+
};

test/fixtures/dev-server/foo.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
console.log('I am foo');
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
const { resolve } = require('path');
4+
5+
module.exports = {
6+
mode: 'development',
7+
stats: 'detailed',
8+
context: __dirname,
9+
entry: {
10+
foo: resolve(__dirname, './foo.js'),
11+
bar: resolve(__dirname, './bar.js'),
12+
},
13+
devServer: {
14+
transportMode: {
15+
server: 'sockjs',
16+
client: 'sockjs',
17+
},
18+
},
19+
};
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
const { resolve } = require('path');
4+
5+
module.exports = {
6+
mode: 'development',
7+
stats: 'detailed',
8+
entry: resolve(__dirname, './foo.js'),
9+
target: ['web', 'webworker'],
10+
output: {
11+
chunkLoading: false,
12+
wasmLoading: false,
13+
workerChunkLoading: false,
14+
},
15+
devServer: {
16+
client: {
17+
path: '/custom/path',
18+
},
19+
transportMode: {
20+
server: 'sockjs',
21+
client: 'sockjs',
22+
},
23+
},
24+
};

0 commit comments

Comments
 (0)