-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
refactor(utils): addEntries to DevServerPlugin #2844
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
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
fcb690e
refactor(utils): move adding plugin to addEntries
ylemkimon d9ae811
refactor(utils): remove DevServerEntryPlugin
ylemkimon 87f6ae5
refactor(utils): addEntries to DevServerPlugin
ylemkimon f85b5d5
fix: remove addDevServerEntrypoints export
ylemkimon 8b66868
refactor: rename file and variables
ylemkimon ac40767
fix: add type declaration for getSocketClientPath
ylemkimon 0f27c53
refactor: rearrange conditionals
ylemkimon 3938aad
fix(utils): use targetProperties to detect web target
ylemkimon 7c4af08
fix: do not modify compiler.options
ylemkimon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
'use strict'; | ||
|
||
const webpack = require('webpack'); | ||
const createDomain = require('./createDomain'); | ||
const getSocketClientPath = require('./getSocketClientPath'); | ||
|
||
// @ts-ignore | ||
const EntryPlugin = webpack.EntryPlugin; | ||
|
||
class DevServerPlugin { | ||
/** | ||
* @param {?Object} options - Dev-Server options | ||
*/ | ||
constructor(options) { | ||
this.options = options; | ||
} | ||
|
||
/** | ||
* A 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} | ||
*/ | ||
apply(compiler) { | ||
const { options } = this; | ||
|
||
// we're stubbing the app in this method as it's static and doesn't require | ||
// a server to be supplied. createDomain requires an app with the | ||
// address() signature. | ||
/** @type {string} */ | ||
const domain = createDomain(options, { | ||
address() { | ||
return { port: options.port }; | ||
}, | ||
}); | ||
/** @type {string} */ | ||
const host = | ||
options.client && options.client.host | ||
? `&host=${options.client.host}` | ||
: ''; | ||
/** @type {string} */ | ||
let path = ''; | ||
// only add the path if it is not default | ||
if ( | ||
options.client && | ||
options.client.path && | ||
options.client.path !== '/ws' | ||
) { | ||
path = `&path=${options.client.path}`; | ||
} | ||
/** @type {string} */ | ||
const port = | ||
options.client && options.client.port | ||
? `&port=${options.client.port}` | ||
: ''; | ||
/** @type {string} */ | ||
const clientEntry = `${require.resolve( | ||
'../../client/default/' | ||
)}?${domain}${host}${path}${port}`; | ||
|
||
/** @type {(string[] | string)} */ | ||
let hotEntry; | ||
|
||
if (options.hot === 'only') { | ||
hotEntry = require.resolve('webpack/hot/only-dev-server'); | ||
} 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 entriesClone; | ||
}; | ||
|
||
/** | ||
* | ||
* Description of the option for checkInject method | ||
* @typedef {Function} checkInjectOptionsParam | ||
* @param {Object} _config - compilerConfig | ||
* @return {Boolean} | ||
*/ | ||
|
||
/** | ||
* | ||
* @param {Boolean | checkInjectOptionsParam} option - inject(Hot|Client) it is Boolean | fn => Boolean | ||
* @param {Object} _config | ||
* @param {Boolean} defaultValue | ||
* @return {Boolean} | ||
*/ | ||
// eslint-disable-next-line no-shadow | ||
const checkInject = (option, _config, defaultValue) => { | ||
if (typeof option === 'boolean') return option; | ||
if (typeof option === 'function') return option(_config); | ||
return defaultValue; | ||
}; | ||
|
||
const compilerOptions = compiler.options; | ||
compilerOptions.plugins = compilerOptions.plugins || []; | ||
/** @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); | ||
/** @type {Entry} */ | ||
const additionalEntries = checkInject( | ||
options.injectClient, | ||
compilerOptions, | ||
isWebTarget | ||
) | ||
? [clientEntry] | ||
: []; | ||
|
||
if (hotEntry && checkInject(options.injectHot, compilerOptions, true)) { | ||
additionalEntries.push(hotEntry); | ||
} | ||
|
||
// use a hook to add entries if available | ||
if (EntryPlugin) { | ||
compiler.hooks.make.tapPromise('DevServerPlugin', (compilation) => | ||
Promise.all( | ||
additionalEntries.map( | ||
(entry) => | ||
new Promise((resolve, reject) => { | ||
compilation.addEntry( | ||
compiler.context, | ||
EntryPlugin.createDependency(entry, {}), | ||
{}, // global entry | ||
(err) => { | ||
if (err) return reject(err); | ||
resolve(); | ||
} | ||
); | ||
}) | ||
) | ||
) | ||
); | ||
} else { | ||
compilerOptions.entry = prependEntry( | ||
compilerOptions.entry || './src', | ||
additionalEntries | ||
); | ||
compiler.hooks.entryOption.call( | ||
compilerOptions.context, | ||
compilerOptions.entry | ||
); | ||
} | ||
|
||
const providePlugin = new webpack.ProvidePlugin({ | ||
__webpack_dev_server_client__: getSocketClientPath(options), | ||
}); | ||
providePlugin.apply(compiler); | ||
|
||
if ( | ||
hotEntry && | ||
!compilerOptions.plugins.find( | ||
(p) => p.constructor === webpack.HotModuleReplacementPlugin | ||
) | ||
) { | ||
// apply the HMR plugin, if it didn't exist before. | ||
const plugin = new webpack.HotModuleReplacementPlugin(); | ||
plugin.apply(compiler); | ||
} | ||
} | ||
} | ||
|
||
module.exports = DevServerPlugin; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.