I'm trying to import this library into a React component which gets server rendered first then registers client side after. So essentially i need the same React component to work in the browser and in Node. This is causing issues in Node because i get Error: Sorry, the Vimeo Player API is not available in this browser..
The Javascript API should allow Node as a browser for some behavior. Even if the API does not support many functions in Node, the API should still allow you to at least import it without errors.
When trying to import this library server side in Node I get Error: Sorry, the Vimeo Player API is not available in this browser.
Import in any file server side.
I'm not very familiar with React, so I don't know how it works server-side. There's really nothing in the library that can happen without having an <iframe> that it can postMessage to, so I don't think there's much that can be done to make it work. Happy to review a pull request though!
OK, let me talk through this, happy to contribute if the concept makes sense to you @bdougherty.
Here is a super simple sample React component.
import React from 'react';
import Vimeo from '@vimeo/player';
const Video = React.createClass({
// 'componentDidMount' only runs client side after the component has
// mounted i.e. loaded and placed in the DOM.
componentDidMount: function() {
const player = Vimeo.Player(this.refs.iframe); // React lets us grab the iframe through the refs property
player.on('play', function() {
console.log('played the video!');
});
},
// 'render' spits out the HTML for the component.
// In React you have 2 options: render client side or render server
// side. I prefer to render server side for quick load times and SEO.
// The 'render' function should be able to run both server side and
// client side. As you can see here no player code or anything that
// would break.
render: function() {
<div>
<iframe src={`https://player.vimeo.com/video/XXX?autoplay=1`} frameBorder="0" ref="iframe" />
</div>
},
});
export default Video
The componentDidMount will never run server side and that is the only place it would make sense to include anything from this library. But since the library errors out on initialization it prevents me from including it in this file at all.
Hopefully that makes sense. Maybe if you're open to it, I can try and whip up a way to including browser checks at a later stage in the process after initialization. Like on function calls or something?
I guess maybe the best way is to update compatibility-check.js to skip the check if in Node?
+1 - In my react app I'll get "window is not defined" on server side render just by importing it
@alexmarchant can you try the react-server-fix branch to see if that change fixes the issue?
Shoot! Seems like the issue may be more complicated that simply bypassing the check.
I get the error ReferenceError: document is not defined and then stubbed document and got TypeError: e.querySelectorAll is not a function and so i stubbed that and got an error about location.href so i stubbed that, and then got an error for Element.setAttribute()...
Instead of automatically searching the page for vimeo elements, i wonder if adding a function to call manually would make this more library more versatile?
It looks like import Vimeo from '@vimeo/player' triggers a function calling the window element.
The only way I could make this work was to use require instead of import, and call require _after_ the component has been mounted.
As in:
componentDidMount: function() {
const VimeoPlayer = require('@vimeo/player');
const player = new VimeoPlayer(this.refs.iframe);
player.on('play', function() {
console.log('played the video!');
});
}
Is this still desired? I'd be happy to factor out a function to check the page for vimeo elements which would only run if typeof window !== 'undefined' or some other equiv check.
There is an open PR since a few months. It fixes this issue. Is there a plan to review it or accept it?
Seem to be receiving this same error when compiling my Gatsby project. Any ideas?
Same as @pureth here.
@Jonqth I used @dbismut 's suggestion as a work around for this bug.
Most helpful comment
It looks like
import Vimeo from '@vimeo/player'triggers a function calling thewindowelement.The only way I could make this work was to use
requireinstead ofimport, and callrequire_after_ the component has been mounted.As in: