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: support of injectHot and injectClient on specific chunks #2998

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
18 changes: 16 additions & 2 deletions lib/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
{
"instanceof": "Function"
}
Expand All @@ -238,6 +245,13 @@
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
{
"instanceof": "Function"
}
Expand Down Expand Up @@ -395,8 +409,8 @@
"hot": "should be {Boolean|String} (https://webpack.js.org/configuration/dev-server/#devserverhot)",
"http2": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttp2)",
"https": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttps)",
"injectClient": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjectclient)",
"injectHot": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjecthot)",
"injectClient": "should be {Boolean|String[]|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjectclient)",
"injectHot": "should be {Boolean|String[]|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjecthot)",
"liveReload": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlivereload)",
"onAfterSetupMiddleware": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserverafter)",
"onBeforeSetupMiddleware": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserverbefore)",
Expand Down
129 changes: 90 additions & 39 deletions lib/utils/DevServerPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@ class DevServerPlugin {
}

/**
* An Entry, it can be of type string or string[] or Object<string | string[],string>
* A Entry, it can be of type string or string[] or Object<string | string[],string>
* @typedef {(string[] | string | Object<string | string[],string>)} Entry
*/

/**
* Additional entry to add to specific chunk
* @typedef {Object} AdditionalChunkEntry
* @property {Entry} entry
* @property {string[]} [chunks]
*/

/**
* Apply the plugin
* @param {Object} compiler the compiler instance
Expand Down Expand Up @@ -69,7 +76,7 @@ class DevServerPlugin {
/**
* prependEntry Method for webpack 4
* @param {Entry} originalEntry
* @param {Entry} additionalEntries
* @param {AdditionalChunkEntry[]} additionalEntries
* @returns {Entry}
*/
const prependEntry = (originalEntry, additionalEntries) => {
Expand All @@ -86,8 +93,13 @@ class DevServerPlugin {

Object.keys(originalEntry).forEach((key) => {
// entry[key] should be a string here
const chunkAdditionalEntries = additionalEntries.filter(
(additionalEntry) =>
!additionalEntry.chunks || additionalEntry.chunks.includes(key)
);

const entryDescription = originalEntry[key];
clone[key] = prependEntry(entryDescription, additionalEntries);
clone[key] = prependEntry(entryDescription, chunkAdditionalEntries);
});

return clone;
Expand All @@ -96,13 +108,15 @@ class DevServerPlugin {
// in this case, entry is a string or an array.
// make sure that we do not add duplicates.
/** @type {Entry} */
const entriesClone = additionalEntries.slice(0);
const newEntries = additionalEntries.map(
(additionalEntry) => additionalEntry.entry
);
[].concat(originalEntry).forEach((newEntry) => {
if (!entriesClone.includes(newEntry)) {
entriesClone.push(newEntry);
if (!newEntries.includes(newEntry)) {
newEntries.push(newEntry);
}
});
return entriesClone;
return newEntries;
};

/**
Expand All @@ -115,23 +129,27 @@ class DevServerPlugin {

/**
*
* @param {Boolean | checkInjectOptionsParam} option - inject(Hot|Client) it is Boolean | fn => Boolean
* @param {Boolean | string[] | checkInjectOptionsParam} option - inject(Hot|Client) it is Boolean | fn => Boolean
* @param {Object} _config
* @param {Boolean} defaultValue
* @return {Boolean}
* @return {Boolean | string[]}
*/
// eslint-disable-next-line no-shadow
// eslint-disable-next-line no-shadow
const checkInject = (option, _config, defaultValue) => {
if (typeof option === 'boolean') {
return option;
}
if (typeof option === 'boolean') {
return option;
}

if (typeof option === 'function') {
return option(_config);
}
if (Array.isArray(option)) {
return option;
}

return defaultValue;
};
if (typeof option === 'function') {
return option(_config);
}

return defaultValue;
};

const compilerOptions = compiler.options;

Expand All @@ -141,35 +159,68 @@ class DevServerPlugin {
const isWebTarget = compilerOptions.externalsPresets
? compilerOptions.externalsPresets.web
: [
'web',
'webworker',
'electron-renderer',
'node-webkit',
// eslint-disable-next-line no-undefined
undefined,
null,
].includes(compilerOptions.target);

/** @type {Entry} */
const additionalEntries = checkInject(
'web',
'webworker',
'electron-renderer',
'node-webkit',
// eslint-disable-next-line no-undefined
undefined,
null,
].includes(compilerOptions.target);

/** @type {AdditionalChunkEntry[]} */
const additionalEntries = [];

const checkInjectClientResult = checkInject(
options.injectClient,
compilerOptions,
isWebTarget
)
? [clientEntry]
: [];
);
if (checkInjectClientResult) {
additionalEntries.push({
entry: clientEntry,
chunks: Array.isArray(checkInjectClientResult)
? checkInjectClientResult
: null,
});
}

if (hotEntry && checkInject(options.injectHot, compilerOptions, true)) {
additionalEntries.push(hotEntry);
if (hotEntry) {
const checkInjectHotResult = checkInject(
options.injectHot,
compilerOptions,
true
);
if (checkInjectHotResult) {
additionalEntries.push({
entry: hotEntry,
chunks: Array.isArray(checkInjectHotResult)
? checkInjectHotResult
: null,
});
}
}

// use a hook to add entries if available
if (EntryPlugin) {
for (const additionalEntry of additionalEntries) {
new EntryPlugin(compiler.context, additionalEntry, {
// eslint-disable-next-line no-undefined
name: undefined,
}).apply(compiler);
for (const additionalChunkEntry of additionalEntries) {
// add entry to existing chunks
if (
additionalChunkEntry.chunks &&
Array.isArray(additionalChunkEntry.chunks)
) {
additionalChunkEntry.chunks.forEach((chunkName) => {
new EntryPlugin(compiler.context, additionalChunkEntry.entry, {
// eslint-disable-next-line no-undefined
name: chunkName,
}).apply(compiler);
});
} else {
new EntryPlugin(compiler.context, additionalChunkEntry.entry, {
// eslint-disable-next-line no-undefined
name: undefined,
}).apply(compiler);
}
}
} else {
compilerOptions.entry = prependEntry(
Expand Down
4 changes: 3 additions & 1 deletion test/__snapshots__/Validation.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ exports[`Validation validation should fail validation for invalid \`hot\` config
exports[`Validation validation should fail validation for invalid \`injectHot\` configuration 1`] = `
"Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.injectHot should be one of these:
boolean | function
boolean | [string, ...] (should not have fewer than 1 item) | function
Details:
* configuration.injectHot should be a boolean.
* configuration.injectHot should be an array:
[string, ...] (should not have fewer than 1 item)
* configuration.injectHot should be an instance of function."
`;

Expand Down
4 changes: 2 additions & 2 deletions test/options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,11 @@ describe('options', () => {
],
},
injectClient: {
success: [true, () => {}],
success: [true, ['a'], () => {}],
failure: [''],
},
injectHot: {
success: [true, () => {}],
success: [true, ['a'], () => {}],
failure: [''],
},
onListening: {
Expand Down