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

Server rendering problem #64

Closed
tgeorges opened this issue Dec 15, 2017 · 13 comments · Fixed by #68
Closed

Server rendering problem #64

tgeorges opened this issue Dec 15, 2017 · 13 comments · Fixed by #68

Comments

@tgeorges
Copy link

Hi esri-loader team !

I experienced a bad issue when using version from 1.5.x with React server rendering : window.Promise was not defined.

The workaround was quite simple but not esthetic...
Maybe you can fix it and make this library server rendering aware ?

=> link to the problem :

Promise: window['Promise']

@tomwayson
Copy link
Member

Thanks @tgeorges

I would like to make this work, but unfortunately I don't have a server rendered react app nor the relevant expertise to test with.

If you manage to get this working and want to make a pull request w/ the fix, I'd be glad to review/merge assuming I can reason about the changes and that tests pass.

@andygup
Copy link
Member

andygup commented Dec 19, 2017

@tgeorges did your code work with a previous version of esri-loader? BTW window isn't available on the server. You may have to cut a special version of this library to bypass that. Here are some suggestions: webpack/react-starter#37

@tomwayson
Copy link
Member

tomwayson commented Dec 20, 2017

That's a good question @andygup, I can see how it would have worked w/ an older version and not this one, and that's what I was assuming, but would be good to confirm from @tgeorges.

I neglected to mention before that I have a WIP example of how to use esri-loader in an Ember Fastboot (server-rendered) app. That uses esri-loader 1.5^. One difference w/ Ember is that the addon that wraps this library explicitly overwrites the Promise implementation w/ Ember's RSVP. That said, I'm still a bit surprised the above line didn't cause an issue in Ember Fastboot b/c I believe that is executed before the code that overwrites it.

Which brings up a point that generally speaking if you want to use this in a server-rendered application you can not load JSAPI modules or render a map on the server side (b/c you can't run Dojo the ArcGIS API for JavaScript in node). So, any calls to the actual methods in this library need to be gated to a browser environment. For example, in my Fastboot example, I load the modules and create the map inside the component's didInsertElement() lifecycle hook (which is equivalent to React's componentDidMount()) because that hook is not executed on the server. I presume if @tgeorges had this working before, he was doing something similar.

We could implement a naive fix like Promise: window && window['Promise'] or Promise: isBrowser && window['Promise'] as suggested in the thread @andygup linked to. However, I'm reluctant to do that w/o actually being able to test it in a server-side environment where the current code is failing. Again, if @tgeorges wants to try that, and can confirm it works, and makes a PR, and it doesn't break in a browser, I'll be glad to merge it.

@tgeorges
Copy link
Author

Hi @tomwayson and @andygup ! Thanks for your suggestions :-)
For now I have foolishly create that global context on the server side to ensure it works correctly :

import Promise from 'bluebird';

global.window = global.window || {};
global.window.Promise = global.window.Promise || Promise;

Its a not elegant solutions but working for now. What I can suggest is to use an universal implementation of Promises (working in both client and server sides) as a dependency.

What is your opinion ?

@tomwayson
Copy link
Member

tomwayson commented Dec 20, 2017

Thanks @tgeorges

I deliberately chose not to take a dependency on a promise library. I don't think that is needed to solve this problem.

I think we can do what I suggest above (Promise: window && window['Promise']). esriLoader.utils.Promise will be undefined on the server, but it should never actually be invoked on the server, so that should be OK.

@tgeorges
Copy link
Author

Ok I understand, do you need some support for that ? I think a simple test in your library to ensure that browser window is defined is enough

@tomwayson
Copy link
Member

tomwayson commented Dec 20, 2017

Well, since I can't currently reproduce the problem, I can't be sure that my suggestion would fix it. I'd prefer to have that confirmation before making that change and cutting a release.

Is your application's code available somewhere so I can try it myself?

Alternatively would you be able to reproduce the problem in a minimal react app created from one of the universal boilerplates, or at least point me to one that approximates your application's setup?

Left to my own devices I'd just try creating an app via Next.js b/c that looks like the fastest way for me to get something up and running, but I'm not sure if that would accurately approximate how your app is rendered server-side.

@tomwayson tomwayson added this to the 2.0.0 milestone Dec 20, 2017
@tgeorges
Copy link
Author

Hi @tomwayson,
sorry for the delay. My code cannot be published easily but I can suggest you a good starter kit from kriasoft to reproduce the problem.
You can find it here : https://github.com/kriasoft/react-starter-kit
To reproduce it, simply declare a Map component in component hierarchy, and use it in a page (for exemple Home) in router hierarchy.

In this component, load Esri Js with your library, and try showing it directly : it will be server rendered and you will touch the problem :-)

I will be unavailable next week but I can find some time the 1st week of 2018 to help you reproduce that

Cheers and happy XMas time :-)

@tomwayson
Copy link
Member

@tgeorges this should be fixed by installing esri-loader@^1.6.0

@tomwayson
Copy link
Member

@Biboba
Copy link

Biboba commented Jan 23, 2018

Hi,

It is a pity that map cannot be rendered at the server side as well.
@tomwayson mentionned that it is because 'b/c you can't run Dojo in node' but isn't it doable as mentionned in the documentation:
http://dojotoolkit.org/documentation/tutorials/1.10/node/

Thanks !

@tomwayson
Copy link
Member

@Biboba I've updated my comment above to be more accurate: "you can't run the ArcGIS API for JavaScript in node." I haven't tried it myself, but server-side rendering JavaScript maps is not trivial even w/o the challenges of trying to load Dojo modules.

Instead, I'd look into doing something like rendering a static image on the server and replacing that w/ the map once the ArcGIS API is loaded in the browser.

@Biboba
Copy link

Biboba commented Jan 24, 2018

@tomwayson Thanks for your precisions !

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

Successfully merging a pull request may close this issue.

4 participants