GoogleWebComponents / google-chart

Google Charts API web components
https://www.webcomponents.org/element/@google-web-components/google-chart/elements/google-chart
Apache License 2.0
358 stars 130 forks source link

importing this element breaks server-side-rendered app #243

Open odahcam opened 5 years ago

odahcam commented 5 years ago

This element (or at least it's dist code) does a lot of window variable usage, breaking an SSR app, since there's no window on server-side. Error might be like that (this one's from an Angular app):

$ cd dist && node server
<app_workdir>\dist\server.js:250113
const nativeShadow = !(window['ShadyDOM'] && window['ShadyDOM']['inUse']);
                     ^

ReferenceError: window is not defined
rslawik commented 5 years ago

The problematic line seems to come from the ShadyCSS polyfill which is used by the Polymer library that this component depends on.

The content of the dist code is specific to your tooling and build setup. This element does not have any custom build rules. In general the code here expects to run in the browser (e.g. it asynchronously adds Google Charts library to the document) so it is better to exclude <google-chart> from any server-side rendering.

Have you been able to successfully use other Polymer-based web components in your SSR setup? Is it possible to customize your setup and exclude <google-chart> to register the component only in the browser?

odahcam commented 5 years ago

...so it is better to exclude from any server-side rendering.

I've tried to only import the component in the client-side, but it is not exactly possible with ES6 w/o dynamic modules enabled and I don't know what happens to my Angular app/build/SSR when it is. In fact, there's no place for me to registry or unregister the elements, the import '@google-web-components/google-chart' itselft triggers the problem.

The problematic line seems to come from the ShadyCSS polyfill which is used by the Polymer library that this component depends on.

About the polyfills, I import'em myself in polyfills.ts file (a standard Angular project file) and simply skip importing them in the polyfills.server.ts file that does the job for me. I think this lib shouldn't be importing any web components polyfill at all, that's the user's job and should be fully optional. Polyfills should fill something, not try to pre-fill a may-existing gap.

Have you been able to successfully use other Polymer-based web components in your SSR setup? Is it possible to customize your setup and exclude to register the component only in the browser?

Yes, but not Polymer v1, I was only successful with Origami module and I believe lit-element should work w/o extensions too. For excluding the element I think I may be able to ignore the element import itself, but I'd need some research.


It is a little problematic to rule if ShadyCSS or google-carts should access window directly, because they are meant to be used in web, but (and it's a big but) even since jQuery golden times, I do check for window and document before using them, it is just a good practice that can avoid any weird issues like this one.

Also, this polyfills thing could be one of the gilty for these excessive sizes web-components currently and usually have. Just to make my point stronger here about whether a element should not optionally depend of a polyfill or not.

I can't blame anyone for the issue, maybe this issue should be in another repository, I need help here, hehe.