-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
🙋 Regular Browser Reload on File Save #289
Comments
Give |
Thanks! But that just turns off reloading altogether... 😆 |
For now, I have a branch with the option https://github.com/mattdesl/parcel/tree/feature/add-js-reload |
Honestly I don’t think this has any practical use cases outside of the one you described. Is there anywhere else where somebody would actually want this option? If so, feel free to submit a PR with your |
You mean, creating a new HTML element and adding it to the body? It's really one of the most basic things you can do with JS... I am genuinely curious how I could change my application to better support HMR. Here is another example: creating a loop with window.requestAnimationFrame(render);
console.log('Starting loop...');
function render (time) {
window.requestAnimationFrame(render);
console.log('Rendering', time);
} If you save the file twice you will end up with two requestAnimationFrame loops running simultaneously. |
Simple, just move the animation logic to a separate module, that way you get hot module replacement :) I didn’t actually try this for myself, but something like this should work: index.js import draw from './draw'
window.requestAnimationFrame(render);
console.log('Starting loop...');
function render (time) {
window.requestAnimationFrame(render);
draw(time)
} draw.js export default function draw(time){
console.log('Rendering', time);
//...
} |
@DeMoorJasper The following doesn't work – nothing changes when saving/editing the import draw from './draw';
document.addEventListener("DOMContentLoaded", function(event) {
window.requestAnimationFrame(render);
console.log('Starting loop...');
function render (time) {
window.requestAnimationFrame(render);
draw(time)
console.log('Rendering', time);
}
}); @davidnagli That doesn't work either, when I save the |
That's why i removed it, i realised it would completely disable HMR @mattdesl |
@mattdesl I was able to reproduce your issue, currently working on figuring it out. |
For the simple use case, you can do a bit of DOM management to replace instead of append on every change: const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
document.body.replaceChild(canvas, document.body.lastElementChild); Saving this will result in the canvas reloading. For the animation frame scenario, you can manage the request id: if (window.currentAnimationFrameId){
window.cancelAnimationFrame(currentAnimationFrameId)
}
window.currentAnimationFrameId = window.requestAnimationFrame(render);
console.log('Starting loop...');
function render (time) {
window.currentAnimationFrameId = window.requestAnimationFrame(render);
console.log('Rendering', time);
} This isn't "automatic", but with a bit of boilerplate it allows the code to be HMR-compatible. |
I like the idea of a |
@thejameskyle Interesting, why do you opt out? Personally I would rather --hmr be opt-in than on by default, since it’s far more magical than just a simple page reload. |
+1 on |
Hi everyone, if you really need regular reload but not HMR, you can try my fork https://github.com/TennyZhuang/parcel just Note that I have not make regular reload as an option now, so you can use it as same as the upstream, and there will always be a browser reload after every change. I will try to make this as an option and make a merge request to the upstream if needed, @devongovett @brandon93s |
@TennyZhuang did you see my fork? It includes a ‘reload’ option. I can submit it as a PR. Personally I think it should be the default, but I guess my goals are a little different than those of the Parcel maintainers. |
HMR is an important feature in parcel and faster than regular reload, I
think HMR as default behavior is reasonable, but i really need regular
reload in my three.js development.
It seems that your fork works, but I didn’t see it before I finish my fork.
…On Sat, 30 Dec 2017 at 23:45 Matt DesLauriers ***@***.***> wrote:
@TennyZhuang <https://github.com/tennyzhuang> did you see my fork? It
includes a ‘reload’ option.
I can submit it as a PR. Personally I think it should be the default, but
I guess my goals are a little different than those of the Parcel
maintainers.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#289 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AIvK3lkRPsE7ID4NQetEjD7a6-wYiuwmks5tFlqPgaJpZM4RDoCb>
.
|
@mattdesl feel free to submit a PR with it, would probably be much appreciated |
It's not really faster – in my own tests I've found parcel reloading to be pretty much comparable to budo, which uses hard page reloads. With small to medium bundle sizes, budo seems to reload faster, and with huge bundles (several MBs), parcel seems faster. Currently HMR is not even working in Parcel as pointed out earlier in this thread. I don't really understand how anybody is using this in production right now. 🤷 |
P.S. Submitted a PR. 😄 |
Commenting here what I wrote on the PR so others can see. Seems to me like you could just hook into the existing HMR system to do a full page reload if you really wanted to. if (module.hot) {
module.hot.accept(function () {
window.location.reload();
});
} However, I'm wondering why this is really needed? HMR is powerful because it allows you to maintain the state of your application across code changes, so you don't need to e.g. re-open a modal and click through 17 steps each time you make a change to the code. |
@devongovett Yeah, that was the first thing I tried, although it feels like a hack. When I save a file, it triggers a hot module reload, so my code gets re-executed before the hot module replacement reloads the page. This means any blocking code will slow down the reload cycle, and I end up with more memory usage during development. (Often the start of the application will create a WebGL context, generate geometries, and push features onto the GPU.)
I agree it can be very powerful, but only if the code is setup to work with it, and only in specific applications (e.g. React, Vue, etc). I've never been able to take advantage of application-wide HMR in a real WebGL project because of GL state, performance constraints, and things like that. Anyways... as pointed out in this thread, hot module replacement is not working in Parcel, which is probably part of the reason some people are asking for a |
You could do something like this if you don't want the module to be re-executed: if (module.hot) {
module.hot.dispose(function () {
window.location.reload();
});
} This will trigger the reload on module dispose rather than after the module has been re-executed. You could also use that hook to store your state for later, and on
That shouldn't be the case. The event starts at the module which changed, and bubbles up to the root. If you |
Ok – this was never clear to me. It might be good to explain the system in the docs somewhere, rather than assume everybody is using React/Vue/etc. So, how does one go about "setting up" HMR without copying the internals of The code here pretty much sums up the application I would like to build: Or is it basically React-or-nothing? |
P.S. To illustrate the issue with reload and thread blocking, try this example:
import * as THREE from 'three';
console.log('Creating...');
const sphere = new THREE.SphereGeometry(1, 512, 512);
console.log('Done');
if (module.hot) {
module.hot.accept(() => {
// or use this instead of dispose()
// window.location.reload();
});
module.hot.dispose(() => {
window.location.reload();
});
} Whether using |
@brandon93s Thanks, your solution works perfectly for me. Hence, I now have no need for the |
+1 on wanting an Using
works, but there still is an second where the new content flashes before the page reload occurs. Plus still having |
@devongovett This makes sense to me, I think that's what webpack dev server does in hot mode. |
What about with asset types that implement hot module reloading themselves? Like it seems reasonable to make all CSS files support hot module reloading by default, but if you wanted to disable that behaviour for some reason, how could you? |
I found a hacky solution to reload immediately: // put this at the top of your code
if (module.hot) {
module.hot.dispose(() => {
window.location.reload();
throw 'whatever'
})
} Or... if (module.hot) {
module.hot.dispose(() => {
window.location.reload();
})
} else { do_something(); } |
Parcel uses "hot module replacement" (HMR), which has quite intuitive problems with `requestAnimationFrame`-based animation: parcel-bundler/parcel#289 We now use a pretty ridiculous hack to cancel previous animation loops when setting up new ones for our examples.
I would like to have this functionality as well.
Would this get implemented? |
I would love to have a |
For anyone who is looking for a zero-config tool for canvas/WebGL prototyping, I ended up building my own tool, canvas-sketch, that approaches (hot) reloading differently, in a way that is more suitable for requestAnimationFrame and so on. |
I'm running Parcel in a Django CMS setup. The HMR is fantastic for all my JS and CSS changes, however ParcelJS doesn't know anything about my Django HTML templates at this stage, nor is it possible or practical for Parcel to be used to bundle them in any way. As such I don't get a reload when I update my templates. It would be great if I could just give Parcel the path to my templates directory and tell it to perform a hard reload whenever a change is detected there, but keep HMR support for the other stuff. I know I should just implement browsersync for this sort of thing but it would seem a shame to add that as Parcel already handles almost everything I need/want for so little effort. |
Is it/could it be possible to initiate a hard reload over the websocket from a custom plugin? Being able to execute custom code on the client side could be pretty powerful (I have no idea if this already exists though) |
Bump for the It can potentially lead to myriads of nasty bugs. Especially, in the hands of less-experienced developers. I'm not sure whether the hmr is worth such a price. Thanks for the amazing work, btw. |
I second this; I often have to manually restart the dev server when developing since it just stops working. That's on top of it getting stuck in an endless loop as per #1317. |
+1 for |
Guys, let's not get this to a 3130 level. @paulosborne, you would +1 it? Just hit the thumbs up button on the first post. Thanks. |
Because Parcel - Could not serve static files parcel-bundler/parcel#1080 - Could not use native reload on HMR parcel-bundler/parcel#289
Because Parcel - Could not serve static files parcel-bundler/parcel#1080 - Could not use native reload on HMR parcel-bundler/parcel#289
I am using a workaround. Because I'm getting an error when parcel is updating: 'parcelRequire' of undefined // page reload on parcel hmr
window.onerror = function(e) {
if(e == `Uncaught TypeError: Cannot read property 'parcelRequire' of undefined`) {
console.log('yess')
location.reload();
}
}; |
So, should both of the suggested solutions be implemented?
|
If you want to reload after file changes, you can run Parcel in watch mode, which compiles changes to another directory (default
Then run a live-server, which listens to file changes and reloads (assuming your output is to the
Here's what my
|
In #2676 which just landed in master, the default was changed to reload the page unless you call |
For those using TypeScript: const hot = (module as any)?.hot;
if (hot) {
hot.dispose(() => {
window.location.reload();
throw "hotReload";
});
} |
🙋
Hi there! I'd like to start exploring Parcel as a workflow for creative coding (WebGL, Canvas2D, etc). I'm trying to migrate some programs I've written for non-HMR workflow to this new HMR workflow, and I'm hitting huge performance issues since the code (which is doing things like creating a WebGL/Canvas context) was not designed to be re-run multiple times.
🎛 Configuration
Take a simple program like this:
🤔 Expected Behavior
I'd like to develop with the same way that a JS file runs/loads in the browser (i.e. once, not many times). If possible, I'd like a way to replace JavaScript HMR with a simple
window.location.reload()
functionality. However, other features (like CSS) should still use HMR / inject without hard reload.😯 Current Behavior
Currently the above code, when saved several times, will create several canvas elements in the body.
💁 Possible Solution
A way of turning on/off regular hot reload. I am assuming this may already exist, but I couldn't find it, so perhaps it's more an issue of documentation?
The text was updated successfully, but these errors were encountered: