In my experience, the frontend is not really the best place to implement undo. The challenge I had was keeping everything in sync with the server across a multitude of different possible and sometimes complex operations (my case included splices on a time axis, with side effects). It was simply more feasible to just let the server handle it all than have code doing the same thing on both sides, in addition to having to design a web service API that optimized for data size across the pipe.