Skip to content

Commit 858b2eb

Browse files
committed
feat: add inlineClient and inlineHot options
1 parent bc2388e commit 858b2eb

File tree

3 files changed

+160
-2
lines changed

3 files changed

+160
-2
lines changed

lib/options.json

+20
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@
172172
"inline": {
173173
"type": "boolean"
174174
},
175+
"injectClient": {
176+
"anyOf": [
177+
{
178+
"type": "boolean"
179+
},
180+
{
181+
"instanceof": "Function"
182+
}
183+
]
184+
},
185+
"injectHot": {
186+
"anyOf": [
187+
{
188+
"type": "boolean"
189+
},
190+
{
191+
"instanceof": "Function"
192+
}
193+
]
194+
},
175195
"disableHostCheck": {
176196
"type": "boolean"
177197
},

lib/utils/addEntries.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,28 @@ function addEntries(config, options, server) {
5959
return entriesClone;
6060
};
6161

62+
// eslint-disable-next-line no-shadow
63+
const checkInject = (option, config, defaultValue) => {
64+
if (typeof option === 'boolean') return option;
65+
if (typeof option === 'function') return option(config);
66+
return defaultValue;
67+
};
68+
6269
// eslint-disable-next-line no-shadow
6370
[].concat(config).forEach((config) => {
6471
const webTarget =
6572
config.target === 'web' ||
6673
config.target === 'webworker' ||
6774
config.target == null;
68-
const additionalEntries = webTarget ? [clientEntry] : [];
75+
const additionalEntries = checkInject(
76+
options.injectClient,
77+
config,
78+
webTarget
79+
)
80+
? [clientEntry]
81+
: [];
6982

70-
if (hotEntry) {
83+
if (hotEntry && checkInject(options.injectHot, config, true)) {
7184
additionalEntries.push(hotEntry);
7285
}
7386

test/Entry.test.js

+125
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,129 @@ describe('Entry', () => {
277277

278278
expect(typeof webpackOptions.entry === 'function').toBe(true);
279279
});
280+
281+
it('only prepends devServer entry points to web targets by default', () => {
282+
const webpackOptions = [
283+
Object.assign({}, config),
284+
Object.assign({ target: 'web' }, config),
285+
Object.assign({ target: 'webworker' }, config),
286+
Object.assign({ target: 'node' }, config) /* index:3 */,
287+
];
288+
289+
const devServerOptions = {};
290+
291+
addEntries(webpackOptions, devServerOptions);
292+
293+
// eslint-disable-next-line no-shadow
294+
webpackOptions.forEach((webpackOptions, index) => {
295+
const expectInline = index !== 3; /* all but the node target */
296+
297+
expect(webpackOptions.entry.length).toEqual(expectInline ? 2 : 1);
298+
299+
if (expectInline) {
300+
expect(
301+
normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1
302+
).toBeTruthy();
303+
}
304+
305+
expect(normalize(webpackOptions.entry[expectInline ? 1 : 0])).toEqual(
306+
'./foo.js'
307+
);
308+
});
309+
});
310+
311+
it('allows selecting compilations to inline the client into', () => {
312+
const webpackOptions = [
313+
Object.assign({}, config),
314+
Object.assign({ target: 'web' }, config),
315+
Object.assign({ name: 'only-include' }, config) /* index:2 */,
316+
Object.assign({ target: 'node' }, config),
317+
];
318+
319+
const devServerOptions = {
320+
injectClient: (compilerConfig) => compilerConfig.name === 'only-include',
321+
};
322+
323+
addEntries(webpackOptions, devServerOptions);
324+
325+
// eslint-disable-next-line no-shadow
326+
webpackOptions.forEach((webpackOptions, index) => {
327+
const expectInline = index === 2; /* only the "only-include" compiler */
328+
329+
expect(webpackOptions.entry.length).toEqual(expectInline ? 2 : 1);
330+
331+
if (expectInline) {
332+
expect(
333+
normalize(webpackOptions.entry[0]).indexOf('client/index.js?') !== -1
334+
).toBeTruthy();
335+
}
336+
337+
expect(normalize(webpackOptions.entry[expectInline ? 1 : 0])).toEqual(
338+
'./foo.js'
339+
);
340+
});
341+
});
342+
343+
it('when hot, prepends the hot runtime to all targets by default', () => {
344+
const webpackOptions = [
345+
Object.assign({ target: 'web' }, config),
346+
Object.assign({ target: 'node' }, config),
347+
];
348+
349+
const devServerOptions = {
350+
// disable inlining the client so entry indexes match up
351+
// and we can use the same assertions for both configs
352+
injectClient: false,
353+
hot: true,
354+
};
355+
356+
addEntries(webpackOptions, devServerOptions);
357+
358+
// eslint-disable-next-line no-shadow
359+
webpackOptions.forEach((webpackOptions) => {
360+
expect(webpackOptions.entry.length).toEqual(2);
361+
362+
expect(
363+
normalize(webpackOptions.entry[0]).includes('webpack/hot/dev-server')
364+
).toBeTruthy();
365+
366+
expect(normalize(webpackOptions.entry[1])).toEqual('./foo.js');
367+
});
368+
});
369+
370+
it('allows selecting which compilations to inject the hot runtime into', () => {
371+
const webpackOptions = [
372+
Object.assign({ target: 'web' }, config),
373+
Object.assign({ target: 'node' }, config),
374+
];
375+
376+
const devServerOptions = {
377+
injectHot: (compilerConfig) => compilerConfig.target === 'node',
378+
hot: true,
379+
};
380+
381+
addEntries(webpackOptions, devServerOptions);
382+
383+
// node target should have the client runtime but not the hot runtime
384+
const webWebpackOptions = webpackOptions[0];
385+
386+
expect(webWebpackOptions.entry.length).toEqual(2);
387+
388+
expect(
389+
normalize(webWebpackOptions.entry[0]).indexOf('client/index.js?') !== -1
390+
).toBeTruthy();
391+
392+
expect(normalize(webWebpackOptions.entry[1])).toEqual('./foo.js');
393+
394+
// node target should have the hot runtime but not the client runtime
395+
const nodeWebpackOptions = webpackOptions[1];
396+
397+
expect(nodeWebpackOptions.entry.length).toEqual(2);
398+
399+
expect(
400+
normalize(nodeWebpackOptions.entry[0]).includes('webpack/hot/dev-server')
401+
).toBeTruthy();
402+
403+
expect(normalize(nodeWebpackOptions.entry[1])).toEqual('./foo.js');
404+
});
280405
});

0 commit comments

Comments
 (0)