Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Velocity.js does not work in Node environments #14

Closed
jamwaffles opened this issue Oct 1, 2015 · 10 comments
Closed

Velocity.js does not work in Node environments #14

jamwaffles opened this issue Oct 1, 2015 · 10 comments

Comments

@jamwaffles
Copy link

One of the key reasons to use React in a project is for the server-side rendering, however Velocity expects window to be defined which it is not in a Node environment. There's a Velocity issue open concerning this but there has been no fix so far, and I don't think there ever will be. There are various suggested solutions but they're quite inelegant, and it would be nice if the library itself provided a fix of some sort.

I think velocity-react should have a shim that only loads Velocity when in a browser environment. I'm not sure how simple it would be, but pre-calculating the final transition states on the server would be a bonus. Failing that, could a VelocityComponent (et al) set the transition state on initial render?

@fionawhim
Copy link
Collaborator

Interesting point.

Having the velocity-react components short-circuit out and not do anything on the server (including not requiring Velocity) I expect would be trivial.

I would assume that in most cases the rest would just work; for consistency you'd want to “finish” the Velocity animation as soon as the client was in play. While that has the potential for jumpiness, I think that in a lot of cases the "end" state for an animation matches the neutral rendering of the element, so you wouldn't notice.

Is the short-circuiting something you're interested in putting together? If not I can take a look. I haven't done any isomorphic React, so if you could point me to a good toy starter project I could toss in a VelocityComponent and see what happens.

Certainly being able to “finish” an animation on the server would be ideal, to have the DOM match more correctly. I don't know how feasible that is or if it's on a roadmap. (cc: @kenwheeler)

@jamwaffles
Copy link
Author

I could probably have a crack at the short circuiting behaviour, but regrettably I don't have the time to figure out a nicer solution. Ideally you'd pre-calculate the styles on the server, but I think that's impossible particularly for stuff like slideDown as it depends on the height of rendered elements on the client. Some way of "snapping" the elements into their animated states would work ok, and it might even happen automagically if velocity-react binds to the componentDidMount event properly.

@kenwheeler
Copy link
Collaborator

In my experience writing componentry for isomorphic environments, I've typically used https://www.npmjs.com/package/exenv to check whether I should be doing any window referencing. That said, certain things can be abstracted away from the dom, but others require dom querying. I have also experimented with circumventing this by storing dimensions in a cookie on the first request and querying them server side on the next request. I'll look at the source to see what I can do to avoid throwing on the server.

@jamwaffles
Copy link
Author

I've just had a quick go at trying to monkey patch Velocity on the server to no avail. Velocity depends heavily on the DOM so it would be pretty difficult to tear it away from it. I tried a conditional require (ew, I know)...

if(typeof window !== 'undefined') {
  var Velocity = require('velocity-animate');
} else {
  var Velocity = function() { }
}

... but I get an odd error on the client:

Uncaught TypeError: Cannot read property 'firstChild' of undefined

Really not sure why this is triggered, but my React (0.13 FWIW) component is very basic and I don't think I'm doing anything wrong React-wise.

@kenwheeler
Copy link
Collaborator

I'll take a look and see if I can sort this out in core velocity with a window existence check or something

@fionawhim
Copy link
Collaborator

@jamwaffles I think the firstChild error can come up if you don't have a child for the VelocityComponent. (Which is something that perhaps we should be tolerant of; though VelocityComponent has no DOM footprint of its own, and relies on a child to have a presence on the page.)

@fionawhim
Copy link
Collaborator

OK, I traced this out a bit. VelocityComponent plays fast-and-loose with findDOMNode to try and avoid having its own DOM footprint. This seems incompatible with server-side rendering.

The alternate trick of trying to add a ref to the child by cloning it also seems to fail in my testing of 0.13, possibly also because of VelocityComponent’s lack of its own node.

My plan is to get this package working with 0.14, then see if the problem persists or if any new solutions present themselves.

As a last resort, we could make VelocityComponent take an optional prop that would cause it to render its own DOM node (a la ReactTransitionGroup) and that would likely smooth this over.

@fionawhim
Copy link
Collaborator

OK, pals. Looks like my investigations above were ERRONEOUS. Turns out (and I need to tattoo this to my trackpad or something), npm link and React do not play well together. That is, using npm link to pull in a dev version of velocity-react from a local repo does not work because velocity-react will resolve a different copy of react than the main app.

@jamwaffles I believe this accounts for the firstChild error the two of us saw, and later “Only a ReactOwner can have refs” errors I found.

I'll close this since it's fixed on master, and get out a 1.0.1 release that includes the shim from #22.

@mars
Copy link

mars commented Oct 5, 2015

@phopkins oh yeah the npm link + dupe React bit me too. I ended up pushing to a branch at Github and using npm install --save github:owner/repo#branch to test.

@jamwaffles
Copy link
Author

Thanks for taking the time to investigate this and fix it everyone. I'll try out the new release asap.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants