webpack-contrib / webpack-hot-client Goto Github PK
View Code? Open in Web Editor NEWwebpack HMR Client
License: MIT License
webpack HMR Client
License: MIT License
// webpack.config.js
n/a
n/a
n/a
n/a
Much of the time compilation errors and warnings in the client/browser console are just noise. Introduce options that allow for preventing compilation errors and warnings in the browser console.
Page doesn't reload.
Page should reload.
app.js
(page has not been reloaded, because initial: true
-> https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/client/index.js#L30 and https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/client/index.js#L78)app.js
(page has not been reloaded, because after reload page initial
was setted in true
https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/client/index.js#L30)Related problem with css
(style-loader
and css-loader
) - first change not applied because initial: true
.
I've been witnessing this with a more complex setup, but just created a simple usecase:
https://github.com/mcjfunk/hot-output-issue
Error output in browser is legible.
Error output contains ANSI escape codes as if for the terminal. It looks like the colors that the error uses are the culprit. They look nice in the terminal, but not the browser:
Here's the error, in all its glory, within the mac terminal:
In the repo above...
npm start
src/index.js
remove a (
from the ReactDOM.render
line creating a syntax error.Please note, I'm not entirely sure the fix for this resides in webpack-hot-client
. Logging takes place here, but it's unclear if cleansing the error that is delivered is its responsibility. But I thought I'd start the conversation here.
I'd love for there to be a magic config option that I've missed, but I've searched and tried many things without luck.
Thanks!
Was using the API for setting up middleware and was not seeing hot reloading and getting a maximum callstack error. I had to omit HotModuleReplacementPlugin
from my plugins and all worked. Might be worth a mention in the README. It's great that webpack is working towards zero config, without having to add the entry scripts etc. but I had to dig through source code to see that you were already including HotModuleReplacementPlugin
webpack's stats.warningsFilter
should be honoured in the log output of webpack-hot-client
.
webpack's stats.warningsFilter
is not honoured in the log output of webpack-hot-client
.
{
stats: {
warningsFilter: /export .* was not found in/
}
}
Define a stats.warningsFilter
and observe the log output.
This issue is moved from webpack/webpack#6276
// webpack.config.js
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import webpack from 'webpack'
const NODE_ENV = process.env.NODE_ENV || 'development'
const isProd = NODE_ENV === 'production'
export default {
mode: NODE_ENV,
output: {
filename: `[name].[${isProd ? 'chunkhash' : 'hash'}].js`,
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html',
minify: {
collapseWhitespace: isProd,
},
}),
],
}
// src/index.js
if (module.hot) {
console.log('This will never be called')
}
log 'This will never be called'
module.hot
is replaced by false
, and log will never be called
https://github.com/JounQin/webpack-next-study/tree/module.hot
branch module.hot
, simply run yarn dev
and open http://localhost:4000
Webpack supports filtering warnings by default using the stats field in the configuration object, which is very neat on some use-cases. It would be nice if the webpack-hot-client would also support this pattern and not just a flag for enabling/disabling warnings and errors in general.
Documentation for stats describing : https://webpack.js.org/configuration/stats/
Implementation in webpack: https://github.com/webpack/webpack/blob/949890acdf1d00d9e53054b56ad3e7215215416d/lib/Stats.js#L26
Run well with babel 7, @babel/preset-env
,etc
Error: Couldn't find preset "@babel/env" relative to directory "/local/GitHub/react-hackernews"
babel
is not needed after published for this module.
Linux desmas-l.desmas 4.15.0-1-amd64 #1 SMP Debian 4.15.4-1 (2018-02-18) x86_64 GNU/Linux
buster/sid
v9.6.0
5.6.0
4.1.1
2.0.0
// webpack.config.js
It's conceivable that the client will be configured to connect to the server via a different host/port. This can be accommodated with minimal code change, simply by allowing to specify a different host/port for the client.
For example, imagine the server (webpack-hot-client
, and thus webpack
proper) is running on a hypervisor guest ("inside a virtual machine"; Vagrant, etc.), or contained inside an LXC container (Docker), or behind a reverse proxy, or even on a remote machine. As it stands, the codes assume the client environment is the same as the server and forces the use of the server options (https://github.com/webpack-contrib/webpack-hot-client/blob/master/index.js#L55).
Trivially, this could be done by allowing a webSocket.host
/webSocket.port
option
(https://github.com/webpack-contrib/webpack-hot-client#clientcompiler-options). This could be improved/normalized however appropriate.
Less trivially, and more generally, the codes could check for a webpack-hot-client/client
entry before augmenting and skip the step if it exists. This would allow a user-in-the-know to manually configure all of the client options (if I understand the code correctly, that is).
My particular use-case is "containerized build via Docker," and using 0.0.0.0
as the host
option gets me what I need, but is a real hack (as the client connects to the socket on ws://0.0.0.0
, and 0.0.0.0
is not required to resolve, though implementations tend to allow it: https://unix.stackexchange.com/questions/419880/connecting-to-ip-0-0-0-0-succeeds-how-why)
It's conceivable that the client will be configured to connect to the server via a different host/port. This can be accommodated with minimal code change, simply by allowing to specify a different host/port for the client.
For example, imagine the server (webpack-hot-client
, and thus webpack
proper) is running on a hypervisor guest ("inside a virtual machine"; Vagrant, etc.), or contained inside an LXC container (Docker), or behind a reverse proxy, or even on a remote machine. As it stands, the codes assume the client environment is the same as the server and forces the use of the server options (https://github.com/webpack-contrib/webpack-hot-client/blob/master/index.js#L55).
Trivially, this could be done by allowing a webSocket.host
/webSocket.port
option
(https://github.com/webpack-contrib/webpack-hot-client#clientcompiler-options). This could be improved/normalized however appropriate.
Less trivially, and more generally, the codes could check for a webpack-hot-client/client
entry before augmenting and skip the step if it exists. This would allow a user-in-the-know to manually configure all of the client options (if I understand the code correctly, that is).
My particular use-case is "containerized build via Docker," and using 0.0.0.0
as the host
option gets me what I need, but is a real hack (as the client connects to the socket on ws://0.0.0.0
, and 0.0.0.0
is not required to resolve, though implementations tend to allow it: https://unix.stackexchange.com/questions/419880/connecting-to-ip-0-0-0-0-succeeds-how-why)
When optimization.runtimeChunk
is single
the client script should be injected in the runtime only.
The client script is injected in the runtime then the runtime is injected in the entrypoint. Also HMR doesn't work without allEntries: true
; not sure if it's normal.
EDIT: it's normal I just didn't understand I needed it in my case.
https://gist.github.com/MatTheCat/2e11f1ddbdf8bee2663fa2a5d2a227a2
module.exports = {
clipboard: false,
devMiddleware: {
publicPath: '/pattern-library/dist/'
},
hotClient: {
host: {
client: '*',
server: 'webpack'
},
port: {
client: +process.env.WEBPACK_HOT_PORT,
server: 8081
}
},
host: '0.0.0.0'
}
Enable webpack-hot-client with optimization.runtimeChunk = 'single'
.
Run well with Docker
connection closed before receiving a handshake response connect @ socket.js:19 (anonymous) @ socket.js:47
https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/client/socket.js#L12
How to manually set webSocket.port
?
I'm using koa-webpack
which uses koa-hot-client
actually, webSocket server port in Docker should be 0.0.0.0
so that we can connect it outside Docker container, but then websock in client side uses 0.0.0.0
also, it that possible to set them separately?
https://github.com/JounQin/docker-study/tree/bug/koa-hot-client
Install Docker first, then run yarn dev:build
and yarn dev
, open http://localhost:7000.
You can change the code above to hostname: window.location.hostname,
then it will work correctly.
// Suggested Configuration:
{
host: {
client: "my.website.com",
server: "0.0.0.0"
},
https: true,
port:{
client: false, // number or false
server: 8081
}
}
This would allow users who have a proxy configuration set up to allow the default port 443 for wss:// connections to work as intended. The issue I'm having is that the address the websocket tries to listen over is wss://my.website.com:8081
which means I have to set my nginx server running on docker to also listen to port 8081 as well as 443. The ideal way this would work for me would be that the client just tries to connect to wss://my.website.com
without any port information added. Then it would route correctly through 443
See https://github.com/joshunger/bugrepro
A user can read the logs.
Can't read the logs because of the text color.
Clone https://github.com/joshunger/bugrepro
cd bugrepro
yarn
yarn start
Open browser.
Change devtools to Dark Theme in Chrome or FireFox.
Load URL.
Looks like dynamic compilation, while slick, is causing more issues that it was supposed to prevent.
I am using webpack-hot-client
together with webpack-serve
. Now with version 3.0.0 being out and #53 and #58 merged, how can one configure webpack-hot-client to have a client per entry as opposed to only one client per all entries? Would be great to have it mentioned somewhere in the README
// webpack.config.js
import * as Koa from "koa";
import * as koaWebpack from "koa-webpack";
function hmr(app, server) {
// server parameter is a Node.js https.Server instance
app.use(koaWebpack({
compiler,
hot: {
https: true,
host: "localhost",
// Pass in the server instance so it can be used by hot module replacement
server,
// Reload page if modules can't be patched
reload: true
} as any
}));
}
Since server
is https.Server
, it uses a certificate, which is tied to a host name (localhost
in my case). However, server.address()
returns the resolved address 127.0.0.1
. webpack-hot-client
should use host
option (which contains value localhost
) in client entry code.
The resolved address 127.0.0.1
is used in client entry code, causing this error:
WebSocket connection to 'wss://127.0.0.1:8081/' failed: Error in connection establishment: net::ERR_CERT_COMMON_NAME_INVALID
If I manually create a secure WebSocket in browser console like this: var wsc = new WebSocket("wss://localhost:8081")
, it works fine.
Using https.Server as the server option.
I am investigating webpack-contrib/webpack-serve#289. After adding console logs, I can see the logLevel
is passed through to this module. I can also see that we assign the logLevel
option value to the client log
:
webpack-hot-client/lib/client/index.js
Line 18 in feeb8de
However, in my testing, this doesn't seem to actually effect the log level in my browser console. I still get warnings
even when logLevel
is set to error
, for example.
Sorry I couldn't provide a small test case to reproduce the exact issue. It's not easy to do when you're trying to navigate between lots of small modules, as is the case with webpack-serve
et al.
I also skimmed the docs of loglevelnext
, which this module uses, to see if I could find documentation demonstrating the behaviour of re-assigning the level
property to effect the log level—to no avail.
This can be reproduced using the webpack-hot-client
project itself. Refer to the "How to Reproduce" section.
webpack-hot-client
should initialize without an error when supplying a Koa server
instance, as the docs mention Koa
as a valid source to provide a server instance.
webpack-hot-client
throws this error:
TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at modifyCompiler (/Volumes/foo/work/webpack-hot-client/lib/util.js:7:95)
at module.exports (/Volumes/foo/work/webpack-hot-client/index.js:3:157)
at Context.it (/Volumes/foo/work/webpack-hot-client/test/tests/init.js:47:23)
I've been able to reproduce this error with the webpack-hot-client
project itself.
webpack-hot-client
repo. I tested with the project at revision cfca82eb1e1
.koa
:npm i [email protected]
test/tests/init.js
, to test this scenario:const Koa = require('koa');
it('should allow passing koa server instance', () => {
const app = new Koa();
const server = app.listen(8081);
const config = require('../fixtures/webpack.config.js');
const compiler = webpack(config);
const options = { hot: true, logLevel: 'info', test: true, server: server };
const { close } = client(compiler, options);
assert(true);
});
Documentation Is:
I'd like to see more examples; possibly and actual working project, so I could replicate exactly what you've done. I've implemented the small example into my own project, but I haven't seen it work yet. It might be a timing issue where Express loads before hotClient
and that's causing the .use
statement in .on('listening')
to not work properly. Either way, this isn't described in the docs. Even copy-pasting that example doesn't give any working code.
Another example is the server
prop. I don't know what this does. What if I already have a WebSocket instance running on that port? Will I still be able to use the server
prop?
I think it'd be best to have a full example in there with the various options like passing in a server
prop so we know what everything does and how to use it.
Hi, I have gone away from the template a little to make it more clear, feel free to close if it was out of line.
The current implementation logs everything in the console in a really nice way and it would be sweet to also have the option to use an overlay similar to the one used in create-react-app
#1101 and like what can be enabled in Webpack Hot Middleware using the overlay
option.
This can probably be supported in one of two ways.
Or maybe this is out of scope entirely?
// webpack.config.js
// additional code, remove if not needed.
modifyCompiler(compiler, options) {
for (const comp of [].concat(compiler.compilers || compiler)) {
// since there's a baffling lack of means to un-tap a hook, we have to
// keep track of a flag, per compiler indicating whether or not we should
// add a DefinePlugin before each compile.
comp.hotClient = { optionsDefined: false };
comp.hooks.beforeCompile.tap('WebpackHotClient', () => {
if (!comp.hotClient.optionsDefined) {
comp.hotClient.optionsDefined = true;
Looking at this code, it creates a brand new array, then tries to do comp.hooks.beforeCompile
on that array. Since there's no null-propagation, it will error because hooks
hasn't yet been defined on that array.
I can run Express without this erroring.
I receive an error:
TypeError: Cannot read property 'beforeCompile' of undefined
at modifyCompiler (webpack-hot-client\lib\compiler.js:136:18)
at module.exports (webpack-hot-client\lib\index.js:22:3)
at Object.<anonymous> (scripts\server\develop\getHttpServerConfig.js:20:1)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (scripts\server\develop\index.js:1:91)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
i 「hot」: WebSocket Server Listening on localhost:56699
Call webpackHotClient
and pass the webpackCompiler
object.
webpackHotClient(webpackCompiler)
N/A
Hi, I have gone away from the template a little to make it more clear, feel free to close if it was out of line.
Would be nice if the documentation could state what the difference between this project and Webpack Hot Middleware. Does not need to be a list of features or anything like that, could just be the goals of this project made clear. My assumption is that this will be recommended way going forward since it's part of the webpack-contrib
organization but maybe they both are good alternatives for different use cases.
I'm struggling on build a development envirement with Electron and HMR enabled, so the config.target
was set to "electron-renderer"
. The dev-server.js
below aims to start server with hot reload, so I chose webpack-serve
. However when I create Electron BorwserWindow
points to that server address, not-reload not presented as expected.
webpack-hot-client/lib/util.js
Lines 9 to 11 in 0d409f4
code above seems to provide hot-client to target "web"
only. After deleted those lines in my local node_modules, hot-reload seems to work.
so why "electron-renderer"
is not accepted by default? Is it by design, or just other reasons?
'use strict';
const webpack = require('webpack');
const packageJson = require('../package.json');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { absPath, DefaultEnv } = require('./util');
let cfg = {
mode: DefaultEnv,
context: absPath('src/renderer'),
target: 'electron-renderer',
entry: {
renderer: ['./index.tsx']
},
output: {
path: absPath('dist/static'),
filename: '[name].js'
},
resolve: {
extensions: ['.js', '.ts', '.tsx', '.json'],
},
performance: {
hints: false
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'less-loader']
})
},
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.tsx$/,
use: [
{
loader: 'babel-loader',
options: {
babelrc: false,
plugins: [
"babel-plugin-syntax-jsx",
["babel-plugin-inferno", { imports: true }]
]
}
},
'ts-loader'
],
exclude: /node_modules/
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'file-loader',
query: {
name: 'imgs/[name].[ext]'
}
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'file-loader',
query: {
name: 'fonts/[name].[ext]'
}
}
}
]
},
plugins: [
new ExtractTextPlugin('styles.css')
]
};
'use strict';
const { join } = require('path');
const DefaultEnv = process.env.NODE_ENV || 'development';
const ProjectRoot = join(__dirname, '..');
function absPath(...paths) {
return join(ProjectRoot, ...paths);
}
module.exports = {
DefaultEnv,
absPath
};
const rendererCfg = require('./webpack.config.renderer');
const serve = { host: '127.0.0.1', port: 5146 };
const hot = { host: '127.0.0.1', port: 5147 };
WebpackServe({
config: rendererCfg,
clipboard: false,
hot: hot,
...serve
});
hot-client should also work with target "electron-renderer"
there won't be hot-reload with target "electron-renderer"
Just read a little bit code of webpack-hot-client, in lib/client/hot.js
, unaccepted module has been handled like this:
onUnaccepted(data) {
const chain = [].concat(data.chain);
const last = chain[chain.length - 1];
if (last === 0) {
chain.pop();
}
log.warn(`Ignored an update to unaccepted module ${chain.join(' ➭ ')}`);
}
just warnings no refresh. and what I saw in my project is no refresh.
I suppose there should be a refresh here for:
If true, instructs the browser to physically refresh the entire page if / when
webpack indicates that a hot patch cannot be applied and a full refresh is needed.
or maybe I can do a pull request.
sorry for my poor english😄
i think not required
We implement allEntries
option (but not released). After spend a lot of time on migration from webpack-dev-server
to webpack-serve
in many projects (i use git version and build script, because i needed add hot client not only first entry point) i found this option is misleading and unnecessary.
We already have autoConfigure
option and we can implement more universal solution:
autoConfigure: true
(maybe add alias first
) - mean modify only first entry (as works right now).autoConfigure: 'all
- modify all entries
.autoConfigure: ['list', 'of', 'entries']
- modify only entries which in array.This values of option are enough in 99% use case. Also no new option and more universal solution.
allEntries
configure only all entry points. Also no easy solution to configure list of entries
.
not the bug
not the feature
// webpack.config.js
entry: {
app: ['./client/app'],
admin: ['./client/admin']
}
// ...
// Using webpack-serve
serve({
config: require('./webpack.config.js'),
host: 'localhost',
port: '3000',
logLevel: 'debug',
// options passed to webpack-hot-client
hot: {
allEntries: true,
autoConfigure: true
},
dev: {
publicPath: '/',
headers: { 'Access-Control-Allow-Origin': '*' },
stats: {
colors: true,
children: false
}
}
});
webpack-hot-client
is configured with both entry points, app
and admin
.
webpack-hot-client
is only configured with the first entry:
[0] multi ./client/app 28 bytes {app} [built]
[14] multi ./client/admin 28 bytes {admin} [built]
[17] multi webpack-hot-client/client?b068869c-deaf-4240-811a-b153750bcbd8 ./client/app 40 bytes {app} [built]
If I switch the entry points around, like so:
// webpack.config.js
entry: {
admin: ['./client/admin'],
app: ['./client/app']
}
// ...
Then only the admin entry point is enabled:
[0] multi ./client/admin 28 bytes {admin} [built]
[9] multi ./client/app 28 bytes {app} [built]
[17] multi webpack-hot-client/client?5b77d4a2-d4cd-490c-aa0a-9f704bf2f2be ./client/admin 40 bytes {admin} [built]
See above?
To have HMR enabled on both entry points (main app and admin app).
// webpack.config.js
// nothing to display
// additional code, remove if not needed.
// same...
Webpack hot client websocket connects once
Webpack hot client websocket connects twice
I've in the console of chrome dev tools:
log.js:48 「hot」 Hot Module Replacement Enabled. Waiting for signal.
log.js:48 「hot」 WebSocket connected
log.js:48 「hot」 Hot Module Replacement Enabled. Waiting for signal.
log.js:48 「hot」 WebSocket connected
log.js:48 「hot」 App Updated, Reloading Modules
I have two websocket connections.
Use webpack 4.
Webpack hot client should be able to work without requiring an 'unsafe-eval'
CSP.
I think that requiring the "dist" version of loglevelnext
like this results in bundling code with eval()
'd modules:
webpack-hot-client/lib/client/log.js
Line 2 in 0ac0673
Snippet from the resulting bundle:
/***/ "./lib/LogLevel.js":
/*!*************************!*\
!*** ./lib/LogLevel.js ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n/* global window: true */\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar PrefixFactory = __webpack_require__(/*! ../factory/PrefixFactory */ \"./factory/PrefixFactory.js\");\n\nvar MethodFactory = __webpack_require__(/*! ./MethodFactory */ \"./lib/MethodFactory.js\");\n\nvar defaults = {\n factory: null,\n level: 'warn',\n name: +new Date(),\n prefix: null\n};\n\nmodule.exports =\n/*#__PURE__*/\nfunction () {\n function LogLevel(options) {\n _classCallCheck(this, LogLevel);\n\n // implement for some _very_ loose type checking. avoids getting into a\n // circular require between MethodFactory and LogLevel\n this.type = 'LogLevel';\n this.options = Object.assign({}, defaults, options);\n this.methodFactory = options.factory;\n\n if (!this.methodFactory) {\n var factory = options.prefix ? new PrefixFactory(this, options.prefix) : new MethodFactory(this);\n this.methodFactory = factory;\n }\n\n if (!this.methodFactory.logger) {\n this.methodFactory.logger = this;\n }\n\n this.name = options.name || '<unknown>'; // this.level is a setter, do this after setting up the factory\n\n this.level = this.options.level;\n }\n\n _createClass(LogLevel, [{\n key: \"disable\",\n value: function disable() {\n this.level = this.levels.SILENT;\n }\n }, {\n key: \"enable\",\n value: function enable() {\n this.level = this.levels.TRACE;\n }\n }, {\n key: \"factory\",\n get: function get() {\n return this.methodFactory;\n },\n set: function set(factory) {\n factory.logger = this;\n this.methodFactory = factory;\n this.methodFactory.replaceMethods(this.level);\n }\n }, {\n key: \"level\",\n get: function get() {\n return this.currentLevel;\n },\n set: function set(logLevel) {\n var level = this.methodFactory.distillLevel(logLevel);\n\n if (level == null) {\n throw new Error(\"loglevelnext: setLevel() called with invalid level: \".concat(logLevel));\n }\n\n this.currentLevel = level;\n this.methodFactory.replaceMethods(level);\n\n if (typeof console === 'undefined' && level < this.levels.SILENT) {\n // eslint-disable-next-line no-console\n console.warn('loglevelnext: console is undefined. The log will produce no output.');\n }\n }\n }, {\n key: \"levels\",\n get: function get() {\n // eslint-disable-line class-methods-use-this\n return this.methodFactory.levels;\n }\n }]);\n\n return LogLevel;\n}();\n\n//# sourceURL=webpack://log/./lib/LogLevel.js?");
/***/ }),
I'm not sure off the top of my head why the dist specifically is being require'd instead of require("loglevelnext")
(which I don't think would have this problem).
I know it's probably a little unusual to set a CSP like this in development, but it reflects the way that the code is run in production.
Set a CSP that prohibits 'unsafe-eval'
.
I'm attempting to set config options for webpack-hot-client in koa-webpack
.
It'd be useful to see an example in the readme of passing in a server
object, so that the WebSockets port used can sync with the main HTTP server.
There are two things that are unclear from the current readme.
Should server
be an instance of Express/Koa, or the instance returned by Node's http.createServer()
?
If it's the latter (and it seems to be, given the calls to .address().address/port
here, then how should a server
object be passed to Express/Koa middleware before the server has been created, either by a call to koa.listen()
or by creating a separate server with http.createServer(koa.callback())
?
My suggestion is therefore is to either:
a) Add an example to the readme to show how this can be done manually
or (and this is probably an issue for koa-webpack
, but I'll suggest it here for now to avoid redundancy)
b) Automatically set the server
option when using koa-webpack
, since that's more likely to be able to set it automatically through the Koa ctx
object.
I apologise in advance if I'm missing anything obvious - on initial glance, this seems to be a circular dependency (middleware needs a server, but the server won't be created until the middleware has already been set up) that the readme doesn't address.
// webpack.config.js
n/a
n/a
n/a
n/a
Client WebSockets that originate from hot-client should use channels to specify that they're intended for HMR purposes and are not third-party sockets. Log message should be updated to include the channel. Broadcast should be updated to be able to target a channel.
Webpack-Hot-Client loads as usual.
ERROR in multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch ./app/entrypoints/client
Module not found: Error: Can't resolve 'webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e' in '[FULL PROJECT PATH]'
@ multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch ./app/entrypoints/client app[0]
ERROR in multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch [NODE_MODULES_PATH]/app/entrypoints/clientTests
Module not found: Error: Can't resolve 'webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e' in '[FULL PROJECT PATH]'
@ multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch ../apps-client-packages/app/entrypoints/clientTests tests[0]
ERROR in multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch ./app/entrypoints/angularJs
Module not found: Error: Can't resolve 'webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e' in '[FULL PROJECT PATH]'
@ multi webpack-hot-client/client?4fabb837-9d08-4ee3-a3c2-5a114dfd758e react-hot-loader/patch ./app/entrypoints/angularJs angularJs[0]
I receive this error probably because the app I'm in brings in another package which itself has webpack-hot-client pulled in. It's looking in ./app
instead of app
. None of these files are in the relative root of the config file ./
. For whatever reason, this works in the package, but not when the package is running from node_modules/
.
Outputting the entrypoint paths, I'm seeing this:
client [FULL PROJECT PATH]\app\entrypoints\client
clientTests [NODE_MODULES PATH]\app\entrypoints\clientTests
angularJs [FULL PROJECT PATH]\app\entrypoints\angularJs
I don't exactly know what's going on here.
require('app-module-path/register')
require('package-in-node-modules')
require('app-module-path/register')
require('scripts/runWebpack')()
entry: {
app: [
'react-hot-loader/patch',
'[FULL PROJECT PATH]\app\entrypoints\client',
],
tests: [
'react-hot-loader/patch',
'[NODE_MODULES PATH]\app\entrypoints\clientTests',
],
angularJs: [
'react-hot-loader/patch',
'[FULL PROJECT PATH]\app\entrypoints\angularJs',
],
},
Create an npm package that contains the webpack code and run that code from an app that uses that npm package. That's how I'm doing it at least. Seems to be the only difference between the two.
diff --git a/lib/client/socket.js b/lib/client/socket.js
index aec287c..7182107 100644
--- a/lib/client/socket.js
+++ b/lib/client/socket.js
@@ -8,8 +8,8 @@ let retry = maxRetries;
module.exports = function connect(options, handler) {
const socketUrl = url.format({
- protocol: options.https ? 'wss' : 'ws',
- hostname: options.webSocket.host,
+ protocol: window.location.protocol === 'https:' ? 'wss' : 'ws',
+ hostname: window.location.hostname,
port: options.webSocket.port,
slashes: true
});
(It should of course not look like this since the normal ways of specifying the socket url should still work. This is just to relay the idea.)
Instead of having to specify the client host for the websocket server, it would be nice if it was possible to use the window.location host (and perhaps the protocol, https/http) instead of having to hardcode that before the server is run.
In some setups it is possible to access a host with many different ip addresses that are isolatet from each other. Our current setup runs the webpack hot client on the host machine and then uses multiple virtual machines running different os and web browser for testing purposes. In this setup each of the virtual machines could have a different ip address for this machine.
It would also make it easier to test this in a setup where your computer is connected to multiple networks, with multiple network cards. This is another setup that we have as well.
Is this something that you would conciser adding? If so I'll write up a better patch for this. Perhaps specifying a function to the host field or adding a new setting for this?
Operating System: MacOS Sierra
Node Version: 8.11.1
NPM Version: 5.6.0
webpack Version: 4.5.0
webpack-hot-client Version: 2.2.2
For application development, since the browser console is the go-to area for debugging, it is distracting to have webpack-hot-client
to be so chatty. But by setting logLevel to "error" silences everything. Since HMR can feel like voodoo at times with the developer thinking, "did that update?", we don't want it to be completely silent.
Ideas:
1) logLevel: "info"
「hot」 App updated at 3:32:13 PM
2) logLevel: "debug"
webpack-serve
or webpack-hot-client
, which, once things are working, isn't very often at all.Thanks for considering this. I'm digging these new libs and want to see them succeed.
Operating System: MacOS Sierra
Node Version: 8.11.1
NPM Version: 5.6.0
webpack Version: 4.5.0
webpack-hot-client Version: 2.2.2
// webpack.config.js (webpack 4)
entry: {
vendor: [
'react',
'react-dom'
]
},
optimization: {
splitChunks: {
name: 'vendor',
minChunks: Infinity
}
}
...
Browser output messages once.
Each log line it output twice:
It gets really messy with errors. Each error is repeated twice.
I'm curious what happens with code splitting but haven't setup a test with it yet.
Setup webpack to create a vendor or common bundle, or I bet multiple entrypoints. Start things up, look at browser console.
Thanks again!
When two/more websocket clients connected all should get messages (hash
, ok
and etc).
When you have two websocket clients, only first connected get information, second don't get nothing (i.e. hot doesn't work es expected) on connection.
Now
Example from webpack-serve
https://github.com/webpack-contrib/webpack-serve/blob/master/docs/addons/watch-content.config.js
WS
messages in dev tools.After run example above websocket client from example (https://github.com/webpack-contrib/webpack-serve/blob/master/docs/addons/watch-content.config.js#L25) connected first and websocket server send messages, when i open development site, websocket client from hot client (https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/client/socket.js#L18) connected to websocket server, but don't get messages due in server.clients.size === 1
(https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/socket-server.js#L71) and hot doesn't work as expected.
It is regression, because in webpack-hot-client@3
all works fine:
webpack-hot-client@3
(https://github.com/webpack-contrib/webpack-hot-client/blob/v3.0.0/index.js#L186)webpack-hot-client@4
(https://github.com/webpack-contrib/webpack-hot-client/blob/master/lib/socket-server.js#L71)webpack-hot-client@3
net.Server
from (https://github.com/webpack-contrib/webpack-serve#listening) should contain websocker server (server.wss
property) to allow send messages without additional websocket clients (in some cases developers can use more when one websocket client, looks it is bad solution) // webpack.config.js
// additional code, remove if not needed.
Websocket client uses client port.
Websocket client try using server port.
$ webpack-serve docs/webpack.config.js
module.exports = {
clipboard: false,
devMiddleware: {
publicPath: '/pattern-library/dist/'
},
hotClient: {
allEntries: true,
host: {
client: '*',
server: '127.0.0.1'
},
port: {
client: 8082,
server: 8081
}
},
host: '0.0.0.0'
}
Set hotClient.port
as an object with different ports for client
and server
.
I tracked the issue until modifyCompiler. options.webSocket
changes between the function call and beforeCompile
event. No idea why.
Repo is available at https://github.com/eddiesholl/webpack-timing-bug
Continuing discussion from webpack-contrib/webpack-serve#152.
The build time reported by webpack should be correct.
When webpack runs inside webpack-serve
, the build time reported by webpack is 11 seconds longer than it should be, because react-hot-client
is pushing the startTime back by 11 seconds at
Line 112 in 5cc12b7
This is a fix/hack to try to avoid issues when watching files that have been created recently. There is a solution in place in webpack-serve
to use time-fix-plugin
to roll this time back and then forward again, which should hopefully end up with the correct startTime in place. But this explicit rollback here in react-hot-client
will always push the value out, it is not cleaned up anywhere. It needs a symmetrical roll forward of the startTime.
Repo linked above with simple reproduction steps.
// webpack.config.js
module.exports = {
entry: [
'babel-polyfill', // Support promise for IE browser (for dev)
'react-hot-loader/patch',
'webpack-hot-middleware/client?reload=true',
'./src/client.js'
]
Should not throw above error since entry
is an array.
Throws TypeError: webpack-hot-client:
entry Object values must be an Array
Just try using an array in the entry section.
This is a bad check. const type = typeof entry
will report object
for arrays.
Doing a console.log
immediately after that line (I modified local node_modules) produces this which only confirms my assertion:
console.log(entry, type, Array.isArray(entry))
// outputs
[ 'babel-polyfill',
'react-hot-loader/patch',
'webpack-hot-middleware/client?reload=true',
'./src/client.js' ] object true
Because of that L#132 gets executed which causes this error.
I expect that webpack hot client updates normally.
After functioning correctly for a while, it crashes semi-randomly. The crash is produced because the function invalid in webpack-hot-client/lib/index.js
expects filePath to be a string, but it was the number 1552056541813
at the time of crash.
<path>/node_modules/webpack-hot-client/lib/index.js:49
.replace(context, '')
^
TypeError: (filePath || "<unknown>").replace is not a function
at invalid (<path>/node_modules/webpack-hot-client/lib/index.js:49:8)
at comp.hooks.invalid.tap (<path>/node_modules/webpack-hot-client/lib/index.js:65:7)
at SyncHook.eval [as call] (eval at create (<path>/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
at Watchpack.watcher.compiler.watchFileSystem.watch (<path>/node_modules/webpack/lib/Watching.js:139:33)
at Object.onceWrapper (events.js:317:30)
at emitTwo (events.js:126:13)
at Watchpack.emit (events.js:214:7)
at Watchpack._onChange (<path>/node_modules/watchpack/lib/watchpack.js:118:7)
at Watchpack.<anonymous> (<path>/node_modules/watchpack/lib/watchpack.js:109:8)
at emitOne (events.js:116:13)
at Watcher.emit (events.js:211:7)
at DirectoryWatcher.<anonymous> (<path>/node_modules/watchpack/lib/DirectoryWatcher.js:238:13)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickCallback (internal/process/next_tick.js:181:9)
Why does webpack return a number as filePath? I don't know, perhaps it is due to:
module.exports = function createWebpackHotCompiler (config) {
Object.keys(config.entry).forEach(entryName => {
if (! Array.isArray(config.entry[entryName])) {
config.entry[entryName] = [config.entry[entryName]];
}
});
const compiler = webpack(config);
webpackHotClient(compiler, { port: 9090 });
const middleware = webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
});
return {
compiler,
middleware,
};
};
// webpack-config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
const HTMLPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './app/entry-client.js'
},
output: {
filename: '../ssr/bundle.json',
path: './assets',
publicPath: '/assets',
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.s?css$/,
use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ]
},
{
test: /\.styl(us)?$/,
use: [ 'vue-style-loader', 'css-loader', 'stylus-loader' ]
},
],
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin(),
new VueSSRClientPlugin({
filename: '../ssr/clientManifest.json',
}),
new HTMLPlugin({
template: '../template-no-ssr.html',
filename: 'index.html',
inject: 'body',
showErrors: false,
}),
],
};
// webpack.config.js
{
entry: {
main: ['zone.js/dist/zone', './src/main.ts'],
styles: ['./src/styles.scss', './src/theme.scss'],
polyfills: ['./src/polyfills.ts'],
scripts: ['./node_modules/hammerjs/hammer.min.js'],
},
}
In this scenario, hot-client is applying the client
entry to each of the entries listed here. In a multi-page scenario, where only one entry per page is being loaded, this is acceptable. In a MultiCompiler scenario this is acceptable.
In a scenario where html-webpack-plugin is being used to combine all entries into a single html file for single-page applications, this will cause unwanted side effects:
client
entries is applied to all entry compilations, resulting in each entry script on the same page vying for control of the page.We need some kind of mechanism to combat this and configure things correctly for each scenario. There are also going to be exceptions, where for some reason someone will want what is normally incorrect behavior. We also need to be opinionated on what the default behavior is.
This will be a breaking change.
Default
The client
entry should only be added to the first config entry of any type of compilation - single or multi.
For a MultiCompiler config the Not sure in which scenarios this is needed.client
should only be added to the first entry of the first compilation config.
Introduce autoEntry: false
option to disable automatic injection of the client
and HotModuleReplacementPlugin
so users can manually configure their compilers as needed.
Webpack-Hot-Client runs on all entrypoints on all routes.
Webpack-Hot-Client only runs on routes that reference back to /
and not any other routes using differing entrypoints.
Client
entry: {
app: [
'react-hot-loader/patch',
'/app/entrypoints/client.js',
],
tests: [
'react-hot-loader/patch',
'/app/entrypoints/clientTests.js',
],
},
Server
entry: {
app: '/app/entrypoints/server.js',
tests: '/app/entrypoints/serverTests.js',
},
.get('/tests', '/bundles/serverTests.js')
.all('*', '/bundles/server.js')
/
<script defer src="/app.client.js" />
/tests
<script defer src="/tests.client.js" />
Setup a path in Express on /
to run one entrypoint and set another path on /something
to run a different entrypoint. Only the entrypoint at /
will get Webpack-Hot-Client.
hi, i'm currently running fullstack project. is there any way to delay automatic reload for about 0.5s? i want to load server before client. for now client loads before server and that forces me to refresh page manually (server resources aren't ready for client)
You can clone the repo at mgoggin/react-app for an example.
When a project file is changed and that module is unaccepted by webpack-hot-client and reload
is configured as true
, the browser should reload to pull down the newest changes.
Webpack compiles the project and the update is sent to the browser, but nothing changes since the module is unaccepted, even though reload
is explicitly set to true
.
npm install
|| yarn install
npm run start
|| yarn start
components/Hi/index.js
This issue is for a:
This the webpack-serve
API code.
const config = require('webpack.config')
serve({
config,
logLevel: 'trace',
dev: {
publichPath: '/'
},
add: (app, middleware) => {
middleware.webpack();
middleware.content({
index: 'index.html'
});
}
});
module.exports = [
{
entry: {
index: [path.resolve(__dirname, 'app.js')],
},
mode: 'development',
output: {
filename: 'output.js',
}
}
{
entry: {
index: [path.resolve(__dirname, 'iframe-app.js')],
},
mode: 'development',
output: {
filename: 'iframe-bundle.js',
}
}
]
<!-- index.html from where I serve my bundles -->
<html>
<body>
<iframe src="http://localhost:8080/iframe.html">
</iframe>
<script src="output.js"></script>
</body>
</html>
<!-- iframe.html where I load the second bundle -->
<div>
<script src="iframe-bundle.js"></script>
</div>
It should serve both bundles without refreshing the whole web page.
The browsers keeps refreshing every time the iframe gets rendered and loads the second output.
I managed to have the same 'refreshing loop' by having two entry points that are loaded in the same page or by recreating a situation like mine (which could take longer).
Using webpack-hot-client under some sort of orchestration system to tie together a bunch of microservers, like an ingress server in minikube or the kubernetes in docker-for-mac
Allow the websocket path to be specified both on the client and the server. I'd prefer they both be set the same so I don't need to use url-rewriting.
setting options:
host: {
server: '0.0.0.0',
client: 'localhost/hot',
},
port: 3002
and useing the ingress:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hot
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/ssl-redirect: "false"
nginx.org/websocket-services: "app"
nginx.ingress.kubernetes.io/rewrite-target: '/'
spec:
rules:
- http:
paths:
- path: /hot:3002
backend:
serviceName: app
servicePort: 3002
It's an ugly hack, but by setting host.client to 'localhost/hot', the resulting url is 'ws://localhost/hot:3002'
When entry is configured as described in the README:
..., or an
Object
who's keys are set to anArray
ofString
.
HMR should detect and handle updates correctly.
HMR does not function as expected. Updates are shown in the console, but always show "No Modules Updated". Sample console log:
「hot」 Hot Module Replacement Enabled. Waiting for signal.
「hot」 WebSocket connected
「hot」 App updated. Recompiling src/style.scss
「hot」 webpack: Compiling (<unnamed compiler>)
「hot」 App Updated, Reloading Modules
「hot」 Checking for updates to the bundle.
「hot」 No Modules Updated.
「hot」 App is up to date.
In addition, this seems to prevent fallback to full-page reload from working. A manual reload is required to pick up the changes.
Webpack config: https://gist.github.com/ezzatron/bb4f0609e513d75fd98d070b99fe83c2#file-webpack-config-js
webpack-hot-client-issue
branchmake run
src/style.scss
, change the color valueI have since "fixed" the issue on the master branch of that same repo, but it required me to use a simple array-of-strings entry configuration, which has flow-on effects for my chunk splitting configuration, which was using the entrypoint name as a way to differentiate chunks.
I'll try to provide a simpler example, meanwhile, here is the full code:
Entry point where the dev middleware is loaded
https://github.com/larriereguichet/universal-react-app/blob/webpack-hot-client/src/server/index.js
Webpack client configuration used by the middleware
https://github.com/larriereguichet/universal-react-app/blob/webpack-hot-client/packages/webpack-config/src/client.js
webpack-hot-client
configuration
https://github.com/larriereguichet/universal-react-app/blob/webpack-hot-client/packages/react-dev-middleware/src/index.js
N/A
ERROR in multi webpack-hot-client/client?main ./src/client/index.js
Module not found: Error: Can't resolve 'webpack-hot-client/client?main' in '...'
git clone [email protected]:larriereguichet/universal-react-app.git
cd universal-react-app
git checkout webpack-hot-client
lerna bootstrap
lerna run build
npm start
N/A
Auto inject mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js
like auto inject HotModuleReplacement code.
Now,I must config webpack entry like:
entry: {
index: ["mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js",path.join(__dirname, "./src/entry-client.js")]
},
I wish to config less, such as:
entry: {
index: [path.join(__dirname, "./src/entry-client.js")]
},
In development,hot replace css
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.