New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

webpack-hot-client

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webpack-hot-client - npm Package Compare versions

Comparing version

to
1.2.0

65

index.js
'use strict';
const weblog = require('webpack-log');
const webpack = require('webpack');
const ParserHelpers = require('webpack/lib/ParserHelpers');
const WebSocket = require('ws');
const uuid = require('uuid/v4');
const { payload, sendStats } = require('./lib/util');
const { modifyCompiler, payload, sendStats, validateEntry } = require('./lib/util');

@@ -28,2 +25,5 @@ const defaults = {

const options = Object.assign({}, defaults, opts);
validateEntry(compiler);
const { host, port, server } = options;

@@ -54,59 +54,4 @@ const wss = new WebSocket.Server(options.server ? { server } : { host, port });

// this is how we pass the options at runtime to the client script
const definePlugin = new webpack.DefinePlugin({
__hotClientOptions__: JSON.stringify(options)
});
modifyCompiler(compiler, options);
for (const comp of [].concat(compiler.compilers || compiler)) {
const hmrPlugin = new webpack.HotModuleReplacementPlugin();
if (comp.options.target === 'web') {
const { entry } = comp.options;
const { name } = comp;
let hotEntry = [`webpack-hot-client/client?${name || uuid()}`];
if (typeof entry === 'string' || Array.isArray(entry)) {
hotEntry = hotEntry.concat(entry);
}
if (comp.hooks) {
compiler.hooks.entryOption.call(comp.options.context, hotEntry);
} else {
comp.applyPluginsBailResult('entry-option', comp.options.context, hotEntry);
}
}
log.debug('Applying DefinePlugin:__hotClientOptions__');
definePlugin.apply(comp);
// fix is only available for webpack@4
if (comp.hooks) {
comp.hooks.compilation.tap('HotModuleReplacementPlugin', (compilation, {
normalModuleFactory
}) => {
const handler = (parser) => {
parser.hooks.evaluateIdentifier.for('module.hot').tap({
name: 'HotModuleReplacementPlugin',
before: 'NodeStuffPlugin'
}, expr => ParserHelpers.evaluateToIdentifier('module.hot', !!parser.state.compilation.hotUpdateChunkTemplate)(expr));
};
normalModuleFactory.hooks.parser.for('javascript/auto').tap('HotModuleReplacementPlugin', handler);
normalModuleFactory.hooks.parser.for('javascript/dynamic').tap('HotModuleReplacementPlugin', handler);
});
hmrPlugin.apply(comp);
} else {
// must come first
hmrPlugin.apply(comp);
compiler.plugin('compilation', (compilation, data) => {
data.normalModuleFactory.plugin('parser', (parser) => {
// eslint-disable-next-line no-underscore-dangle
parser._plugins['evaluate Identifier module.hot'].reverse();
});
});
}
}
compiler.plugin('compile', () => {

@@ -113,0 +58,0 @@ stats = null;

102

lib/util.js
'use strict';
const ParserHelpers = require('webpack/lib/ParserHelpers');
const uuid = require('uuid/v4');
const webpack = require('webpack');
const weblog = require('webpack-log');

@@ -7,4 +10,83 @@

function hotEntry(compiler) {
if (compiler.options.target !== 'web') {
return;
}
const { entry } = compiler.options;
const { name } = compiler;
const clientEntry = [`webpack-hot-client/client?${name || uuid()}`];
let newEntry = {};
if (typeof entry === 'object') {
for (const key of Object.keys(entry)) {
const value = entry[key];
if (Array.isArray(value)) {
newEntry[key] = clientEntry.concat(value);
}
}
} else {
newEntry = clientEntry.concat(entry);
}
if (compiler.hooks) {
compiler.hooks.entryOption.call(compiler.options.context, newEntry);
} else {
compiler.applyPluginsBailResult('entry-option', compiler.options.context, newEntry);
}
}
function hotPlugin(compiler) {
const hmrPlugin = new webpack.HotModuleReplacementPlugin();
if (compiler.hooks) {
// webpack@4
// eslint-disable-next-line no-loop-func
compiler.hooks.compilation.tap('HotModuleReplacementPlugin', (compilation, {
normalModuleFactory
}) => {
const handler = (parser) => {
parser.hooks.evaluateIdentifier.for('module.hot').tap({
name: 'HotModuleReplacementPlugin',
before: 'NodeStuffPlugin'
}, expr => ParserHelpers.evaluateToIdentifier('module.hot', !!parser.state.compilation.hotUpdateChunkTemplate)(expr));
};
normalModuleFactory.hooks.parser.for('javascript/auto').tap('HotModuleReplacementPlugin', handler);
normalModuleFactory.hooks.parser.for('javascript/dynamic').tap('HotModuleReplacementPlugin', handler);
});
hmrPlugin.apply(compiler);
} else {
// webpack < 4
// must come first
hmrPlugin.apply(compiler);
compiler.plugin('compilation', (compilation, data) => {
data.normalModuleFactory.plugin('parser', (parser) => {
// eslint-disable-next-line no-underscore-dangle
parser._plugins['evaluate Identifier module.hot'].reverse();
});
});
}
}
module.exports = {
modifyCompiler(compiler, options) {
// this is how we pass the options at runtime to the client script
const definePlugin = new webpack.DefinePlugin({
__hotClientOptions__: JSON.stringify(options)
});
for (const comp of [].concat(compiler.compilers || compiler)) {
hotEntry(comp);
log.debug('Applying DefinePlugin:__hotClientOptions__');
definePlugin.apply(comp);
hotPlugin(comp);
}
},
payload(type, data) {

@@ -40,3 +122,23 @@ return JSON.stringify({ type, data });

}
},
validateEntry(compiler) {
for (const comp of [].concat(compiler.compilers || compiler)) {
const { entry } = comp.options;
const type = typeof entry;
if (!Array.isArray(entry) && type !== 'object') {
throw new TypeError('webpack-hot-client: The value of `entry` must be an Array or Object. Please check your webpack config.');
}
if (type === 'object') {
for (const key of Object.keys(entry)) {
const value = entry[key];
if (!Array.isArray(value)) {
throw new TypeError('webpack-hot-client: `entry` Object values must be an Array. Please check your webpack config.');
}
}
}
}
}
};
{
"name": "webpack-hot-client",
"version": "1.1.0",
"version": "1.2.0",
"description": "A client for enabling, and interacting with, webpack Hot Module Replacement",

@@ -18,3 +18,3 @@ "license": "MIT",

"cover": "istanbul cover node_modules/mocha/bin/_mocha",
"lint": "eslint index.js client.js client lib test",
"lint": "eslint index.js lib test",
"mocha": "mocha test/test.js --exit",

@@ -21,0 +21,0 @@ "prepublishOnly": "npm run compile:client",