Universal: List browser global that we need to support in Universal

Created on 16 Sep 2016  路  37Comments  路  Source: angular/universal

The next version of Universal can support/mock any browser global so please list out any of the that are the most important ones for me to make sure you can use it.

It's worth noting there is a best practice way of dealing with 3rd party services that should be considered before falling back to these supported globals

Browser

  • - [x] document
  • - [x] document.querySelector
  • - [x] document.querySelectorAll
  • - [ ] document.cookie
  • - [ ] XMLHttpRequest
  • - [ ] fetch
  • - [ ] localStorage
  • - [ ] navigator
  • - [ ] history
  • - [ ] location
  • - [ ] navigator
  • - [ ] localStorage
  • - [ ] sessionStorage
  • - [ ] window (please list out which properties you're using on window and how you use it)
  • - [ ] window.pageYOffset
  • - [ ] window.pageXOffset
  • - [ ] window.scrollTo
  • - [ ] window.addEventListener
  • - [ ] {{ list_your_global }}

Common Libs (with globals)

  • - [ ] jQuery
  • - [ ] {{ list_your_global }}

Research (we need to determine if possible)

  • - [ ] Polymer
  • - [ ] Foundation
  • - [ ] d3
  • - [ ] videojs
  • - [ ] angularfire2
  • - [ ] firebase
  • - [ ] @angular2-material

Supported (so far)

  • - [ ] {{ }}

Twitter Poll
https://twitter.com/gdi2290/status/776893828045246466

The reason for this is to allow faster adoption of Universal JavaScript with components that the developer may or may not have control over

Please leave a comment of a browser global that you use (if window make sure to include some of the properties or functions used) and what you're using it for to make it in the next release

update:
added research list
added polymer

Most helpful comment

Supporting window would change the game for me

All 37 comments

Polymer would be a nice addition if it's possible.

Polymer++

Also Angular 2 Material

Supporting window would change the game for me

which properties on window does everyone use?

@rogerpadilla I have material support added to Universal 2.0.5
https://github.com/angular/universal-starter/commit/b34cfff1eeed79b66ff5c52f77b7175806e0884d

-localstorage
-location
-scroll
-onload

+1 for localStorage

XMLHttpRequest

window.history - navigation
window.navigator - 3rd party scripts using userAgent detection
window.localStorage - browser storage
window.sessionStorage - session data
window.onresize - custom lazyload functions
window.onorientationchange - custom lazyload functions
window.innerWidth - custom lazyload functions
window.innerHeight - custom lazyload functions
window.scrollY - custom lazyload functions
window.scrollX - custom lazyload functions

document.documentElement.clientWidth - custom lazyload functions, cross browser
document.documentElement.clientHeight - custom lazyload functions, cross browser

our 3rd party global libs:

Foundation
d3
videojs

3rd party:

  • angularfire2
  • firebase

3rd party:

  • angular2-google-maps

Seems to currently be the most popular angular 2 google maps wrapper library, can specifically see issue 668 angular-universal support

Hi @gdi2290 , you mention that there is a best practice for dealing with 3rd party services, what is it?

  • [x] document.createEvent
  • [x] document.createEventObject
  • [x] window.ace

ace editor comes with brace module
I was suggested to hack into brace and write

if(typeof window == "undefined"){
     return false;
}

but it introduces other errors in code.
without supporting it I doubt if a production level work can be done using universal and doing something like this beats the purpose of universal's tenet of same reusable code for server and client altogether.
I feel kind of blocked as I don't see easy way to trim out codes using ace while rendering on server without having to doif(server) {..} else{..}kind of logics
Additionally I guess this model of adding support for browser globals one by one on user request is not scalable or clean rather, these should be pluggable to angular-universal such that the needy guy can quickly write his/her plugin at will or else he will remain blocked until the next release of angular-universal comes out.

@gdi2290 Any idea when this might b available? If not can you provide the information on the best practice way of dealing with 3rd party services as at the moment it's a bit of a nightmare trying to integrate certain features.

@dotoodot At the moment using isBrowser etc is probably the best option, unless you want to use DI and try and abstract some of the methods for the server.

What are you trying to use?

@MarkPieszak One example is https://github.com/zefoy/angular2-perfect-scrollbar

I'm using DI for some things such as 3rd party scripts which I've kind of got my head round but when it come to things like the above i.e loading a module just for the client I get a bit lost.

One thing you could try doing is creating a ghost/empty Component directive for it (that you inject in your server NgModule file. You might be able to pull something like that off, if it's real simple, just so that the server completely ignores it. Make sure you don't include the Module for that library in your server NgModule, only do that in the Client part.

@Component({ 
    selector: 'perfect-scrollbar'
})
export class PerfectScrollbar { }

You're right though, it would be helpful to document this more thoroughly, it's a bit of a complicated process!

  • [ ] window.matchMedia
  • [ ] window.requestAnimationFrame

@MarkPieszak How are you doing? I would like to do something similar to @dottodot, except with a window.localstorage service.. there's a nice post here: http://stackoverflow.com/questions/39085632/localstorage-is-not-defined-angular-universal/39098748#39098748 on an approach for using window.localstorage in angular-universal except that it produces an error on the server... details here http://stackoverflow.com/questions/41430971/angular-universal-starter-localstorage-in-production-using-window-in-browser ... I'm sure I'm missing something simple and it sounds like the ghost/empty approach might work... What do you think? Is there a good way to wrap LocalStorage as an 'empty' provider, in node.module.ts so that it doesn't generate an error?

providers: [
    // ...
    UserService,
    {provide: LocalStorage, useValue: {getItem() {} }}
]

(Many thanks and hope this is the right place for a question like this)

@owencooney You'd basically want to do a similar thing, so for your main.client providers, make sure LocalStorage (shown above) uses a BrowserStorage class that uses localStorage / sessionStorage. So make getItem / setItem methods (etc) that end up doing localStorage.getItem(key) for example.

While in your main.node list of providers, for that LocalStorage, provide some MockStorage class, that has the same implementation (getItem/setItem/etc) but they do nothing.

That should do it! That's the gist of dependency injection magic :)

@MarkPieszak awesome, I'll give that a go! Thanks a mil Mark!

won't be supported officially
https://github.com/angular/angular/issues/13822

I just find a workaround to avoid if (typeof window === 'undefined') { return; } in every case when dom is used directly. just use jsdom-global package as require('jsdom-global')(); in in the main module or somewhere. no need to worry about workarounds anymore.

I get error Error: Cannot find module "." when trying to add it to the main.node file, how are you implementing it?

@MarkPieszak make sure you have both jsdom and jsdom-global installed, maybe thats the issue.

Interesting, yeah I tried both. Let me try with a fresh blank repo.

Doesnt work for me, this generate other errors

angularfire 2 wont work because XMLHttpRequest not available

@hiepxanh it is avialable through something like @angular/common/http

@Toxicable I mean, angular universal won't work with third party library like angularfire 2, when that lib making some request, I have to add:
(global as any).XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
to the top of server.ts to clear that error.

In case anyone come here for angular ssr issue, you can use below webpack config for your server ts build.

{
test: /hammerjs/,
loader: "null-loader"
}

Similarly: https://medium.com/@puresmash/solve-hammer-js-issue-on-ssr-project-2e79664a7196

@egjs/hammerjs will work also, but it's not working properly with slider on mobile in my project.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings