Skip to content

refactor: code #3429

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

Merged
merged 1 commit into from
Jun 10, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 115 additions & 83 deletions lib/utils/DevServerPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@
const ipaddr = require('ipaddr.js');
const getSocketClientPath = require('./getSocketClientPath');

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

class DevServerPlugin {
/**
* @param {?Object} options - Dev-Server options
* @param {Object} options - Dev-Server options
*/
constructor(options) {
this.options = options;
}

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

/**
* Apply the plugin
* @param {Object} compiler the compiler instance
* @returns {void}
* @returns {string}
*/
apply(compiler) {
getWebSocketURL() {
const { options } = this;

/** @type {"ws:" | "wss:" | "http:" | "https:" | "auto:"} */
Expand Down Expand Up @@ -112,7 +110,7 @@ class DevServerPlugin {
searchParams.logging = options.client.logging;
}

const webSocketURL = encodeURIComponent(
return encodeURIComponent(
new URL(
`${protocol}//${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
port ? `:${port}` : ''
Expand All @@ -128,11 +126,20 @@ class DevServerPlugin {
/[!'()*]/g,
(character) => `%${character.charCodeAt(0).toString(16)}`
);
}

/**
* @returns {string}
*/
getClientEntry() {
const webSocketURL = this.getWebSocketURL();
/** @type {string} */
const clientEntry = `${require.resolve(
'../../client/index.js'
)}?${webSocketURL}`;

return `${require.resolve('../../client/index.js')}?${webSocketURL}`;
}

getHotEntry() {
const { options } = this;

/** @type {(string[] | string)} */
let hotEntry;
Expand All @@ -142,47 +149,35 @@ class DevServerPlugin {
} else if (options.hot) {
hotEntry = require.resolve('webpack/hot/dev-server');
}
/**
* prependEntry Method for webpack 4
* @param {Entry} originalEntry
* @param {Entry} additionalEntries
* @returns {Entry}
*/
const prependEntry = (originalEntry, additionalEntries) => {
if (typeof originalEntry === 'function') {
return () =>
Promise.resolve(originalEntry()).then((entry) =>
prependEntry(entry, additionalEntries)
);
}

if (typeof originalEntry === 'object' && !Array.isArray(originalEntry)) {
/** @type {Object<string,string>} */
const clone = {};

Object.keys(originalEntry).forEach((key) => {
// entry[key] should be a string here
const entryDescription = originalEntry[key];
clone[key] = prependEntry(entryDescription, additionalEntries);
});

return clone;
}

// 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);

[].concat(originalEntry).forEach((newEntry) => {
if (!entriesClone.includes(newEntry)) {
entriesClone.push(newEntry);
}
});
return hotEntry;
}

return entriesClone;
};
/**
* @param {Object} compilerOptions
* @returns {boolean}
*/
// eslint-disable-next-line class-methods-use-this
isWebTarget(compilerOptions) {
return compilerOptions.externalsPresets
? compilerOptions.externalsPresets.web
: [
'web',
'webworker',
'electron-renderer',
'node-webkit',
// eslint-disable-next-line no-undefined
undefined,
null,
].includes(compilerOptions.target);
}

/**
* Apply the plugin
* @param {Object} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
/**
*
* Description of the option for checkInject method
Expand Down Expand Up @@ -211,38 +206,28 @@ class DevServerPlugin {
return defaultValue;
};

const compilerOptions = compiler.options;
const additionalEntries = [];

compilerOptions.plugins = compilerOptions.plugins || [];
const clientEntry = this.getClientEntry();

/** @type {boolean} */
const isWebTarget = compilerOptions.externalsPresets
? compilerOptions.externalsPresets.web
: [
'web',
'webworker',
'electron-renderer',
'node-webkit',
// eslint-disable-next-line no-undefined
undefined,
null,
].includes(compilerOptions.target);
if (
checkInject(
this.options.client ? this.options.client.needClientEntry : null,
compiler.options,
this.isWebTarget(compiler.options)
)
) {
additionalEntries.push(clientEntry);
}

/** @type {Entry} */
const additionalEntries = checkInject(
options.client ? options.client.needClientEntry : null,
compilerOptions,
isWebTarget
)
? [clientEntry]
: [];
const hotEntry = this.getHotEntry();

if (
hotEntry &&
checkInject(
options.client ? options.client.hotEntry : null,
compilerOptions,
true
this.options.client ? this.options.client.hotEntry : null,
compiler.options,
Boolean(this.options.hot)
)
) {
additionalEntries.push(hotEntry);
Expand All @@ -259,25 +244,72 @@ class DevServerPlugin {
}).apply(compiler);
}
} else {
compilerOptions.entry = prependEntry(
compilerOptions.entry || './src',
/**
* prependEntry Method for webpack 4
* @param {Entry} originalEntry
* @param {Entry} newAdditionalEntries
* @returns {Entry}
*/
const prependEntry = (originalEntry, newAdditionalEntries) => {
if (typeof originalEntry === 'function') {
return () =>
Promise.resolve(originalEntry()).then((entry) =>
prependEntry(entry, newAdditionalEntries)
);
}

if (
typeof originalEntry === 'object' &&
!Array.isArray(originalEntry)
) {
/** @type {Object<string,string>} */
const clone = {};

Object.keys(originalEntry).forEach((key) => {
// entry[key] should be a string here
const entryDescription = originalEntry[key];

clone[key] = prependEntry(entryDescription, newAdditionalEntries);
});

return clone;
}

// 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);

[].concat(originalEntry).forEach((newEntry) => {
if (!entriesClone.includes(newEntry)) {
entriesClone.push(newEntry);
}
});

return entriesClone;
};

compiler.options.entry = prependEntry(
compiler.options.entry || './src',
additionalEntries
);
compiler.hooks.entryOption.call(
compilerOptions.context,
compilerOptions.entry
compiler.options.context,
compiler.options.entry
);
}

const providePlugin = new webpack.ProvidePlugin({
__webpack_dev_server_client__: getSocketClientPath(options),
__webpack_dev_server_client__: getSocketClientPath(this.options),
});

providePlugin.apply(compiler);

compiler.options.plugins = compiler.options.plugins || [];

if (
hotEntry &&
!compilerOptions.plugins.find(
!compiler.options.plugins.find(
(p) => p.constructor === webpack.HotModuleReplacementPlugin
)
) {
Expand Down