Comments (17)
Hi,
I can't speak for @christianalfoni but IE11 has been discussed in the past and the conclusion was that, yes it's probably possible to get Overmind to work without Proxies but that would imply developing and maintaining a whole new system of state read/write tracking which would significantly slow down development, make future improvement way harder and increase the bundle size.
Because of these reasons, there are no plan (as far as I know) to get IE11 supported.
If you haven't yet you can take a look a CerebralJS which support IE and is similar to Overmind in its approach.
from overmind.
@chimon2000 it is not just a question of including immer in overmind but a functional one. I worked on proxy-state-tree, the underlying library that is doing the mutation/access tracking for overmind. Immer and proxy-state-tree are fundamentally different in there implementation and scope of work.
I donβt see a way how overmind could use the approach of immer to keep track of state changes and dependency access without compromising its functionality.
We talked a whole lot about the bold move of dropping IE11 support in overmind and decided that it would be time to free us of the burden to support an old browser.
There is always the possibility of having a Babel/typescript plug-in to get IE11 support but that would be a big investment into a technology that will be gone in a few years (as edge will be based on chromium and come to win 7)
As said before getting IE11 support would be a huge investment in development resource that could be better used to improve to overall development experience by focusing on documentation and the devtools.
from overmind.
I've been exploring this topic some more lately. The problem lays with the async functions and sync mutations. I'm going to assume Overmind doesn't need sync mutations and it's ok if they happen before the next flush (correct me if I'm wrong).
With a sync action, you can wait until the action returns, then do a deep-diff of state:
const myAction = ({ state }) => {
state.model.year = 2016;
// when this action returns, do a deep-diff in ie11.
}
With async actions it's not so simple:
const myAction = async ({ state }) => {
state.model.year = 2016;
// 1. You need to do a deep-diff here
await something();
state.model.year = 2017;
// 2. You need to do a deep-diff here
await somethingMore();
state.model.year = 2018;
// 3. You need to do a deep-diff here
}
For the first deep-diff (1), Overmind could check if the function returns a promise and if it does, wait with setTimeout
until it yields or returns and do the first deep-diff.
The second deep-diff (2) is the problematic one because Overmind doesn't know the function has resumed. With es6 proxies, Overmind can know because a mutation coming from that action has occurred, but in es5 state.model.year = 2017
is completely transparent.
The third deep-diff (3) is easy again because the promise is resolved.
Some ideas to solve it:
- Using generators instead of async functions but for some reason (that I don't quite understand yet) they're kind of ugly and nobody wants to use them π
- Forcing people to always use
effects
for their awaits. That way Overmind can know when the action yields (calls an effects) or resumes (the effect resolves) and can do deep-diff in the correct places. Not pretty either, as it deviates from normal JavaScript:
const myAction = async ({ state, effects }) => {
state.model.year = 2016;
await effects.something(); // <- this is ok
state.model.year = 2017;
await fetchSomething(); // <- this is forbidden
state.model.year = 2018;
}
- Insert deep-diff's with babel in async actions. This won't be very performant of course. I don't know "how intelligent" can a babel plugin be.
const myAction = async ({ state, effects }) => {
state.model.year = 2016;
checkForMutations(state); // <- inserted by babel
await effects.something();
checkForMutations(state); // <- inserted by babel, but unnecessary, wasted CPU
state.model.year = 2017;
checkForMutations(state); // <- inserted by babel
await fetchSomething();
checkForMutations(state); // <- inserted by babel, but unnecessary, wasted CPU
state.model.year = 2018;
checkForMutations(state); // <- inserted by babel
}
from overmind.
Yes, the babel plugin is sure a tricky one. I'm on brainstorm mode here :)
Anyway, I've been taking a look at immer (mutation side) and memoize-state (tracking side) and even tho they rely on es6 proxies they have managed to work with es5 as well.
I'll try to dig more into their code and if I find something useful I'll let you know here.
from overmind.
https://www.pcworld.com/article/3393198/microsoft-edge-ie-mode.html
from overmind.
@christianalfoni is this something that could make it in the pipeline and if so what would a time frame look like? Overmind has been my favorite approach yet, but unfortunately this is a deal breaker.
from overmind.
I am more advocating for producing a separate bundle for ES5 than increasing the size of the current bundle. Both are viable options, but I acknowledge that it would be more work for maintainers. What is the current size restriction / goal for Overmind? How much would a non-proxied version increase the size of Overmind? I imagine the worst case (just reusing immer internally) would be around 4kb (min+gz).
I understand that CerebralJS is similar, but there are differences. Also, is the plan to always have feature parity between Cerebral and Overmind? If so, I'd think that would be more difficult than producing a backwards compatible version of Overmind. If not and Overmind is the way forward, then it would be pretty difficult to recommend Cerebral.
from overmind.
Fair enough
from overmind.
I wonder if the Chrome polyfill could work with Overmind:
https://github.com/GoogleChrome/proxy-polyfill
from overmind.
@luisherranz Sadly no. The polyfill supports just a limited number of proxy 'traps'. It also works by calling seal on the object passed to Proxy. This means that the properties you want to proxy must be known at creation time.
from overmind.
I think the question is if Overmind can be designed to replace entire objects, which is the requirement of the polyfill:
The following line will fail (with a
TypeError
in strict mode) with the polyfill, as it's unable to intercept new properties-
p.model.year = 2016; // error in polyfill
However, you can replace the entire object at once - once you access it again, your code will see the proxied version.
p.model = {name: 'Falcon', year: 2016};
// model Object {name: "Falcon", year: 2016}
For example, in "es5-mode" mutations could be triggered by a deep comparison of the previous state vs the new one, then replacing entire objects when needed.
The deep comparison would be something like this:
https://github.com/theKashey/immutable-changes/blob/master/src/index.js
Once that's done the tracking should work just fine.
By the way, I'm not stating that overmind should have support for IE11, I'm just wondering if it would be possible to do, while keeping the same external API.
from overmind.
For example, one problem of the approach I just mentioned would be the mutations made in async functions after the first await. I wonder if there's a way to trigger the deep comparison asynchronously...
from overmind.
The only way that comes to my mind right now is to trigger the comparison at regular intervals. Not ideal but hey, man, update your browser π
Another way to solve this issue could be a babel-plugin to substitute those mutations:
state.model.year = 2016;
// transpiled to =>
set(state.model, 'year', 2016);
from overmind.
@luisherranz that would be the basic idea of a babel-plugin. But it is not that simple. The tricky part is to identify and track state variable access/mutation by doing static code analysis of javascript/typescript. There are a million edge cases that need to be thought of for having this work reliable.
You could e.g. pass your state object into an arbitrary function inside an action and have it manipulate the state. In typescript the actions functions are at least typed but doing this in plain javascript would be nearly impossible.
from overmind.
Yeah, I believe they work with quite a bit of limitations. But please, if there is an elegant we should look into it :)
from overmind.
Very interesting suggestion!
Related to async it can actually work if it detects a promise being returned. It does a setTimeout and does a new diff until the promise resolves. Though this has a problem with:
export const someAction = ({ state }) => {
setTimeout(() => {
state.foo = 'bar'
})
}
Cause there is no way to know when the action is done. And there is no way to warn about this. That said, it is an edge case and since it is async it will be part of the next flush anyways.
My biggest worry here is performance. The deep-diff would require trigger the garbage collector a lot and also performance is issue. Cause after every flush
you have to create a copy of the state, which requires you to go through everything. And on the next flush you have to go through it again.
Microsoft is just about to release their new browser which can run in IE11 mode. Meaning that companies has absolutely no reason to not change the browser. They can run IE11 mode on old internal apps/pages and for everything else they get a modern browser.
"
Internet Explorer mode. Instead of forcing business users to switch between two different web browsers so that they can access internal websites that still required IE, Microsoft Edge will feature a fully-compatible Internet Explorer mode via a new tab. That way, users can run legacy sites and modern sites side-by-side in one browser.
"
I really like the thought experiment, though I truly think it will be work wasted. Microsoft should fix this... any they are with the new Edge browser :-D
from overmind.
My biggest worry here is performance. The deep-diff would require trigger the garbage collector a lot and also performance is issue.
Yes, performance would be definitely worse than in the proxy version.
Microsoft is just about to release their new browser which can run in IE11 mode.
Amazing news, I didn't know about that :)
from overmind.
Related Issues (20)
- Is there any way to change states outside component? HOT 10
- [BUG] State mutation error HOT 3
- Svelte + Overmind : Function called outside component initialization
- [BUG] Statemachine errors on send(), possible documentation issue HOT 2
- Devtools: add the option to fail silently if port wasn't found HOT 2
- [BUG] Vue State Hooks loses reactivity once using in nested components. HOT 4
- [BUG] States changes are not reflecting in the UI but dev tool shows the value changed HOT 1
- [BUG] Typo in "ensureMutationTrackingIsEnabled" function HOT 3
- Error: While trying to resolve module `phoenix` HOT 1
- [BUG] TypeError with webpack 5 HOT 1
- [BUG] proxy-state-tree - You are mutating the path HOT 1
- Does the graphql package work with any subscriptions on a graphql server or is it specific to the phoenix framework?
- [BUG] svelte reactivity broken on subsequent state changes cross-components HOT 4
- [Question] Is the project dead? Is so, what are options to migrate to? HOT 5
- [BUG] Incompatible with React 18 with Strict Mode HOT 13
- Page doesn't re-render after navigation in Next 13 HOT 12
- [BUG] `overmind-react` - multiple overmind named instances HOT 1
- [BUG] Overmind JS Not working in Next JS 13 HOT 1
- [BUG] Usage of 'useSyncExternalStore' causes errors with react below version 18 HOT 3
- [BUG] Can't mock overmind for jest snapshots HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from overmind.