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

fix(Server): disable page reload when hot is not specified (options.hot) #1276

Closed
wants to merge 1 commit into from

Conversation

byzyk
Copy link
Member

@byzyk byzyk commented Jan 15, 2018

  • This is a bugfix
  • This is a code refactor
  • This is a test update
  • This is a typo fix
  • This is a metadata update

For Bugs and Features; did you add new tests?

No

Motivation / Use-Case

Aimed to fix #1251. As per the issue, the page keeps reloading even if hot option is not specified or false. This PR contains fix which disables page reload when hot: false or not specified or hotOnly: true. To enable page refresh along with HMR one has to explicitly set hot: true.

Breaking Changes

No

Additional Info

I think we can consider adding one more option, something like livereload for use-cases when people don't wanna use HMR but instead prefer to go with a regular page refresh. I didn't do it as I feel it's more like a new feature while I tried to keep this PR as simple as possible.

@codecov
Copy link

codecov bot commented Jan 15, 2018

Codecov Report

Merging #1276 into master will increase coverage by 0.05%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1276      +/-   ##
==========================================
+ Coverage   75.72%   75.77%   +0.05%     
==========================================
  Files           5        5              
  Lines         482      483       +1     
  Branches      156      155       -1     
==========================================
+ Hits          365      366       +1     
  Misses        117      117
Impacted Files Coverage Δ
lib/Server.js 82.02% <66.66%> (+0.05%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 83c1625...88b89bb. Read the comment docs.

@byzyk byzyk mentioned this pull request Jan 15, 2018
3 tasks
@benstaker
Copy link

benstaker commented Jan 15, 2018

@byzyk I have checked out your fork by defining the following in my package.json:
git+ssh://git@github.com:byzyk/webpack-dev-server.git#88b89bbd4054f94a18a67c4f834a99a3eac5769e

And I am receiving the following error when running webpack-dev-server:

module.js:471
    throw err;
    ^

Error: Cannot find module '../../client/'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.resolve (internal/module.js:27:19)
    at addDevServerEntrypoints (C:\workplace\feefo\feefo-admin-ui\node_modules\webpack-dev-server\lib\util\addDevServerEntrypoints.js:18:35)
    at startDevServer (C:\workplace\feefo\feefo-admin-ui\node_modules\webpack-dev-server\bin\webpack-dev-server.js:363:3)
    at processOptions (C:\workplace\feefo\feefo-admin-ui\node_modules\webpack-dev-server\bin\webpack-dev-server.js:350:5)
    at Object.<anonymous> (C:\workplace\feefo\feefo-admin-ui\node_modules\webpack-dev-server\bin\webpack-dev-server.js:495:1)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:383:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:496:3

Versions (working combinations):

"webpack": "2.7.0"
"webpack-dev-server": "2.11.0" or "2.5.1"

Which webpack-dev-server version did you base your fix from? And which version of webpack do you have?

Update: I have done a clean install of my npm packages, by clearing the cache and deleting node_modules, and the same error appears.

@byzyk
Copy link
Member Author

byzyk commented Jan 15, 2018

@benstaker I tested it with webpack: "3.10.0" and fix is based on the latest WDS release which is 2.11.0.

This might be related to code builds. As per contributing guide, try this step before testing:

Go to the webpack-dev-server module (cd node_modules/webpack-dev-server), and run npm run prepublish.

Let me know if that helped

@happypoulp
Copy link

@benstaker I had the same issue at first.

I then did:

cd node_modules/webpack-dev-server/
yarn
yarn transpile:index

And I was able to test the fix.

@benstaker
Copy link

@byzyk @happypoulp thank you both. I have tried running npm run -s transpile:index instead as I do not have yarn installed, inside of node_modules/webpack-dev-server and I am receiving the following error:

$ npm run -s transpile:index
client-src/default doesn't exist

Side note: The same error is outputted when running npm run prepublish.

It seems that I am having a different result to you both, may be due to the way I have defined and installed byzyk's forked copy (see my previous comment re. package.json). It's missing the client-src/** folder. I will download a zip copy of your changes and report back later.

@happypoulp
Copy link

happypoulp commented Jan 15, 2018

@benstaker did you run npm install after cd node_modules/webpack-dev-server/ (that's what the yarn command does for me)?

I used the URL you provided in my package.json to test this PR on my side, so this part should be fine.

@benstaker
Copy link

@happypoulp I have tried running npm install inside of node_modules/webpack-dev-server and as expected, I am receiving the same error because the client-src/** folder does not exist.

I have now downloaded the zip of branch fix/hmr-disable, deleted the contents of node_modules/webpack-dev-server, then copied the contents of the zip into it. Then ran npm install and npm run prepublish inside of that folder and it no longer errors!

I have tested running webpack-dev-server and it correctly disables HMR however, I am receiving the following errors in the browser console. Do you see the same errors?
image

@happypoulp
Copy link

@benstaker I did not had those error in my JS console. Maybe the webpack config we use to test this PR differs somehow...
FTR here's the webpack config I am using:

const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = (settings) => {
    return {
        entry: {
            app: [
                path.join(process.cwd(), "src/index.js"),
            ],
        },
        output: {
            filename: "[name]-[chunkhash].js",
            path: path.join(process.cwd(), "build"),
            publicPath: "/",
        },
        devServer: {
            contentBase: "./build",
            disableHostCheck: true,
            historyApiFallback: true,
            host: "127.0.0.1",
            port: 8181,
        },
        resolve: {
            symlinks: false,
            modules[path.join(process.cwd(), "src"), "node_modules"],
        },
        module: {},
        plugins: [
            new HtmlWebpackPlugin({
                filename: "index.html",
                template: "index.html",
                inject: true,
                minify: false,
            }),
        ],
    }
}

@benstaker
Copy link

@happypoulp quite possibly, thank you for checking!

This may be due to the v2 webpack and latest webpack-dev-server I am using. We're using this combination because v3 webpack is currently too slow for incremental builds, so have reverted to webpack v2.

It seems that this issue is now solved, so please continue 🥇

@byzyk
Copy link
Member Author

byzyk commented Jan 16, 2018

@shellscape seems like this PR resolved the issue. Would you be able to review and give your feedback? I see that some tests are failing which is weird since overall coverage increased.

@andreyvolokitin
Copy link

andreyvolokitin commented Jan 19, 2018

Note that full page reload ("live reload") and HMR are two distinct features, see here: #1251 (comment). They are used in different scenarios and one can not completely replace another. I.e. you can update JS/CSS/images with HMR, but if you developing static HTML page, you need to update its HTML with a full page reload ("live reload") because this is the only way to do it and HMR will not work in that case. Moreover, currently due to a bug, full page reload on HTML change is actually only works with HMR turned off, see #1271 . So your proposed solution will completely disable HTML refreshing in the described scenario, with HMR turned on or off.

The correct way to proceed on this is to implement a new option for "live reload", like you mentioned. The source files changes need to be delivered to the browser somehow. The simplest way to do it is a "live reload". On top of it you can use HMR, then JS/CSS/images will use it, but HTML changes still will need to be refreshed with "live reload". And if you don't want any of this you just turn off HMR and "live reload", but not turn off "live reload" by turning off HMR which is what you proposing

@byzyk
Copy link
Member Author

byzyk commented Jan 20, 2018

@andreyvolokitin I agree, I also feel like HMR and livereload should be 2 separated features. That's exactly what I stated in PR description. The only reason I haven't implemented it in this PR is that I wanted to confirm this with the project maintainers first.

However, the proposed solution won't disable livereload completely. It'll be still available when hot: true is explicitly set.

@andreyvolokitin
Copy link

Live reload for changes in HTML is currently not working with hot: true (#1271). With the proposed solution it also won't work with hot: false, so for changes in HTML it will completely disable live reload.

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@TheLarkInn would you be able to review and give a feedback whether this PR is ok to merge?

@andreyvolokitin
Copy link

  • why are you calling a "bugfix" what in fact is a feature removal (removal of live reload)? Live reload is a core feature of webpack-dev-server and not a bug, and HMR is a different feature on top of it. Why are you trying to disable live reload by disabling HMR?
  • like you said, the new option is a way to go. Why are you still trying to merge a PR which will break all those using live reload and not HMR?

For additional info, see: https://github.com/webpack/docs/wiki/webpack-dev-server#automatic-refresh

inline: false might be solving your issue already

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@andreyvolokitin please refer to PR description. Suggested changes don't remove so-called live-reload. You'll still have it when explicitly set hot: true, the same way as before.

As per #1251 , the issue was that page kept reloading even when hot: false or not specified (HMR is disabled by default) or even with hotOnly: true, which is clearly a bug, isn't it?

As we already discussed, currently there is no option to explicitly enable livereload only. It's rather a fallback for HMR, but it would be nice to have it as an option as well. That's why I suggested to add it as a standalone feature and think it's out of the scope of this PR, although I will be more than happy to work on that once confirmed with project maintainers.

Does that address your concerns or did I miss something?

@andreyvolokitin
Copy link

Yes, you keep missing the point of live-reload. Live-reload is not an addition to HMR. It is the other way around: HMR is an addition to live-reload. And all in all, they are two separate features. Live-reload is always enabled and can not be disabled currently (again, inline: false might be worth looking at, as it removes page reloading JS from the client and the page itself might also be available at http://«host»:«port»/«path» so that there is no auto-reloading happening at all). HMR can be enabled additionally.

Suggested changes don't remove so-called live-reload. You'll still have it when explicitly set hot: true, the same way as before.

Your changes remove live-reload as a basic page refreshing mechanism, which is currently always enabled and is also active with hot: false (because by design hot option is not controlling live-reload). hot: true is an option which enables HMR, conceptually it has nothing to do with live-reload, and should not control live-reload, but in your changes it does. So it will be not the same way as before: live-reload will stop working for those who are not using HMR.

As per #1251 , the issue was that page kept reloading even when hot: false or not specified (HMR is disabled by default)

This is intended behavior, because by design hot option is not controlling live-reload — there is live-reload always enabled, and on top of it you can enable or disable HMR with hot option. The actual problem in this case is that there is no way to disable live-reload.

or even with hotOnly: true, which is clearly a bug, isn't it?

I think it isn't. hotOnly description states that it «Enables Hot Module Replacement (see devServer.hot) without page refresh as fallback in case of build failures.». I am not sure what build failures means exactly, but I guess hotOnly means "do not reload a page to try to keep it updated if there is no way to apply HMR in case of some build failures or errors". So I guess hotOnly is only about this narrow "build-failure" edge case, and not about "always disable live-reload and only use HMR".

As we already discussed, currently there is no option to explicitly enable livereload only.

Actually, there is: live-reload is always enabled, and if HMR is disabled with hot: false, then live-reload is the only thing enabled. So the thing is that there is no option to explicitly disable livereload

It's rather a fallback for HMR, but it would be nice to have it as an option as well.

As stated in the docs, live-reload is not a fallback for HMR, but HMR is an additional feature on top of live-reload. Live-reload is called "automatic refresh" there and has two modes: "inline" and "iframe".

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@andreyvolokitin thanks for your comment.

Let me clarify a bit. I can't remember that I've ever said livereload being an addition to HMR. From the very beginning, I stated that those should be 2 distinct features. I'm aware of the fact that livereload is enabled by default, and again I know it's not the same as HMR.

Your concern is that this PR is aimed to remove livereload feature while again, it's not true. Check the PR description, it will just disable livereload by default which was requested in #1251 and approved by @shellscape. I agree with you that it's not the best way to enable page refresh by actually specifying hot option as it indeed is not relevant. That's why I expressed the same concern in PR description and feel like this can be added as another option cos some people might find it handy. And that's exactly why I asked for reviews from project maintainers, to see how to approach this issue further or if it makes any sense at all (there is a pretty big chance it isn't, and that's fine).

While I appreciate your input, I don't get it why are you so worried about livereload being removed after this is merged, as this PR is not about removing it. However, it might change some default functionality or expected behavior and thank you for pointing it out. But it's not the same as removing feature as a whole.

Just as a side note, you're referencing docs (which might not be that precise and could be outdated as well), while I'm trying to back up my statements from what I've seen in the source code. Thus, I don't agree with you on hotOnly option, because from code perspective it seemed that livereload was purely meant to be a fallback for HMR. However, I can be wrong on that.

Anyway, let's wait for the webpack maintainers (@sokra @TheLarkInn @shellscape) to jump in and will see how we should proceed with this one. Otherwise, we can keep this argument going on forever while basically saying almost the same stuff just in different words.

Peace ✌🏽

@alexander-akait
Copy link
Member

alexander-akait commented Jan 24, 2018

@byzyk

However, it might change some default functionality or expected behavior and thank you for pointing it out. But it's not the same as removing feature as a whole.

Should have major label (and will be in next branch, not in master).
Also need tests, codecov/patch failed.

@andreyvolokitin
Copy link

andreyvolokitin commented Jan 24, 2018

@byzyk

I don't get it why are you so worried about livereload being removed after this is merged, as this PR is not about removing it

Because of this: #1276 (comment)

Thus, I don't agree with you on hotOnly option, because from code perspective it seemed that livereload was purely meant to be a fallback for HMR.

I also have seen the code. From this code perspective, it seems to me that in case of hot flag it executing HMR logic, and in other case — live-reload logic. As expected. I am not sure how is that making livereload a "pure fallback for HMR".

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@evilebottnawi thanks, will make those amends when I get a chance.

What is your view on the discussion above? Does it make sense for page reload to be a distinct feature with its own option like live or liveReload so users can enable/disable it explicitly?

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@andreyvolokitin I don't see how #1271 is relevant to this. Originally this PR was meant to address #1251

@alexander-akait
Copy link
Member

alexander-akait commented Jan 24, 2018

@byzyk for me yes, i have some project on php and laravel/blade and now use hack for reloading page #1271 (comment), be good have this option in out of box in next branch, in theory i can use browser-sync for this, but for me it is overload tool (perf also decrease, and memory leak, which don't fix a lot of time 😞 ). Also we already have chokidar, just add option for array of glob and refresh page when something changes.

@andreyvolokitin
Copy link

@byzyk PR is disabling live-reload if hot: false. Also currently with hot: true live-reload for HTML changes is not working. So with this PR HTML live-reload will not work with hot: true and with hot: false, though currently it is working with hot: false

@byzyk
Copy link
Member Author

byzyk commented Jan 24, 2018

@andreyvolokitin actually in this PR page refresh should work with hot: true. Have you tested it for your case?

@andreyvolokitin
Copy link

andreyvolokitin commented Jan 24, 2018

@byzyk yep, sorry, it is working, my bad. But now there is no HMR for css and js with hot: true, just a full page reload (but that is what you intended I guess). And with hotOnly: true it is an old story: HMR and no live-reload for HTML.

@andreyvolokitin
Copy link

I saw the code and what you changed from the beginning. I still think that you misinterpreted the meaning and intention of "hot" and "hotOnly" options. In your PR the code is doing 1) HMR with hotEmitter.emit('webpackHotUpdate', currentHash);, and then immediately 2) a full page reload. There is no sense in it if you try to understand this. And it does only HMR without page reload if hotOnly: true — this, on the contrary, is logical, and this is actually the current behavior of webpack-dev-server with hot: true (which causes the problem of not updating HTML changes). So yeah, I guess maintainers could clear this up.

@byzyk byzyk changed the base branch from master to next January 29, 2018 09:41
@byzyk byzyk changed the base branch from next to master January 29, 2018 09:44
Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add test(s)

@byzyk
Copy link
Member Author

byzyk commented Jun 14, 2018

@evilebottnawi do you still think the approach I took here is the right one to move forward with? Based on the discussions above I feel like we should distinguish between livereload and hmr features.

@michael-ciniawsky michael-ciniawsky changed the title Fix: disable page reload when hot is not specified fix(Server): disable page reload when hot is not specified (options.hot) Aug 21, 2018
@michael-ciniawsky michael-ciniawsky added this to the 4.0.0 milestone Aug 25, 2018
@codecov
Copy link

codecov bot commented Sep 18, 2018

Codecov Report

Merging #1276 into master will increase coverage by 0.05%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1276      +/-   ##
==========================================
+ Coverage   75.72%   75.77%   +0.05%     
==========================================
  Files           5        5              
  Lines         482      483       +1     
  Branches      156      155       -1     
==========================================
+ Hits          365      366       +1     
  Misses        117      117
Impacted Files Coverage Δ
lib/Server.js 82.02% <66.66%> (+0.05%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 83c1625...88b89bb. Read the comment docs.

1 similar comment
@codecov
Copy link

codecov bot commented Sep 18, 2018

Codecov Report

Merging #1276 into master will increase coverage by 0.05%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1276      +/-   ##
==========================================
+ Coverage   75.72%   75.77%   +0.05%     
==========================================
  Files           5        5              
  Lines         482      483       +1     
  Branches      156      155       -1     
==========================================
+ Hits          365      366       +1     
  Misses        117      117
Impacted Files Coverage Δ
lib/Server.js 82.02% <66.66%> (+0.05%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 83c1625...88b89bb. Read the comment docs.

@alexander-akait
Copy link
Member

/cc @byzyk sorry for big delay, i think you are right, we need:

  • hot option enable/disable HMR
  • livereload option for enable/disable auto reload page (HMR still works)

Summary:

  • using --no-hot and --no-livereload you disable HMR and livereload
  • using --no-hot you disable only HMR (browser now always reload pages)
  • using --no-livereload you disable livereload (HMR still works)
  • no options HMR and livereload works together

Also we deprecated --hot-only option because it is misleading

What do you think?

@kaiyoma
Copy link

kaiyoma commented Apr 19, 2019

+1 for an option to disable the full page refresh. There's a bit of discussion here too: #1744

tl;dr: Our codebase doesn't work with HMR, so I'd like to disable it, but that enables the full page refresh mechanism. Our UI is expensive to load, so reloading the page on every file change is extremely disruptive. It would be incredibly useful to have webpack build on every change, but I control when the page reloads.

@byzyk
Copy link
Member Author

byzyk commented Apr 27, 2019

Hi @evilebottnawi!

Sorry for a delay, yep that's something I had in mind originally and I guess that's exactly what other folks are asking as well.

Copy link

@wizardofhogwarts wizardofhogwarts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO there is already a huge delay. @evilebottnawi it still appears to be relevant. I have many a times realised that there must be an option to turn page reload off when not using hot.

@alexander-akait
Copy link
Member

Here answer #1276 (comment), this PR is abandoned so feel free to send a new PR

@byzyk
Copy link
Member Author

byzyk commented May 7, 2019

Hi everyone!

Sorry guys but unfortunately I won't be able to finalize this one because of the current workload. I'll try to revisit it in a month or so. In the meanwhile feel free to pick up where I left or simply submit new PR since codebase has evolved a lot.

@alexander-akait
Copy link
Member

Implemented you can disable hot using --no-hot and disable liveReload using --no-live-reload (also supported using devServer options)

@richard-ling
Copy link

richard-ling commented May 7, 2020

One or both of --no-hot and -no-live-reload appear to still be broken (webpack 4.28.3, webpack-dev-server 3.1.14). Running as follows
$ webpack-dev-server --progress --port 8080 --verbose --no-live-reload --no-hot

Running webpack with config from '.build/config.json':
NODE_ENV=webpack-dev
version=dev-c0612f2-20200507003035441
app-url=https://localhost/myapp/
api-endpoint=prod
use-dev-claims=false

 10% building 2/2 modules 0 activeℹ 「wds」: Project is running at http://0.0.0.0:8080/
ℹ 「wds」: webpack output is served from /myapp/
ℹ 「wds」: Content not from webpack is served from ./build
ℹ 「wds」: 404s will fallback to /index.html
ℹ 「wdm」:    3620 modules                                                            
ℹ 「wdm」: Compiled successfully.

[At this point I change and resave a source file...]

ℹ 「wdm」: Compiling...
ℹ 「wdm」:    3620 modules                                                       
ℹ 「wdm」: Compiled successfully.

Then the browser reloads, losing all state. Is that as expected?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

Don't enable HMR by default
9 participants