angular / universal

Server-side rendering and Prerendering for Angular
MIT License
4.04k stars 483 forks source link

support "jQuery" #512

Closed PatrickJS closed 7 years ago

PatrickJS commented 8 years ago

make Universal easy enough to support any browser tech

update: I have a new Context design that will allow us to support this

jeffwhelpley commented 8 years ago

I am assuming you mean only for pre-rendering, right? This wouldn't make sense for re-rendering.

PatrickJS commented 8 years ago

pre-render to re-render

jeffwhelpley commented 8 years ago

foo man choo

jeffwhelpley commented 8 years ago

Seriously, though, if you are ONLY pre-rendering then we can use your headless browser technique to allow for jQuery and other browser specific stuff, but it won't work with re-rendering.

LGabAnnell commented 8 years ago

Why is this an issue? Angular2 has the capabilities of jQuery already, doesn't it? And from what I understand, jQuery is a fancy wrapper for document / window, which you don't want us to use. Also, since it's possible to manipulate the DOM with Angular2 without ever touching these objects, why bother?

I just can't see why you feel the need to support jquery

MarkPieszak commented 8 years ago

In an ideal world we don't need it at all, but there's still some developers who use it (or plugins/libraries that use it), so unfortunately Universal could use some sort of patch available for them. It's not an easy implementation of course...

Eventually I want to try and tackle at least suppressing Polymer from rendering server-side (so it doesn't error out), since some people use ng2&polymer mix as well.

jeffwhelpley commented 8 years ago

Yes, Mark is right. It comes down to the fact that the server doesn't have the full DOM. So, libraries that directly touch the DOM either have to be ignored (i.e. stubbed out to do nothing) or patched in some way. So, for example when you call $('blah') that calls document.querySelector('blah') under the scenes. There is no global document object on the server so you either need to create a fake one or just no-op the call.

I think the direction we are going to try and go is to limit patching within the core universal lib as much as possible to avoid bloat. You can always patch that locally if you want BUT the much better solution IMO is to isolate all code that directly touches the DOM into client-only components and services (ideally a service). If you think about it...almost all use cases for jQuery will be client-only anyways. You don't need that functionality on the server. So just put it in a client-only service and there is no need to patch.

I think the reason why Patrick is exploring this in spite of what I am saying is that people often have legacy code that is hard to refactor so it is nice to have some level of support AND with pre-rendering (which is done at the command line before you deploy static assets) you could theoretically have a little more jQuery support.

Let me know if that makes sense or if you have other questions.

LGabAnnell commented 8 years ago

you can always patch that locally if you want BUT the much better solution IMO is to isolate all code that directly touches the DOM into client-only components and services

That is exactly what I've been doing, isBrowser has helped a lot. Maybe suggest

if (isBrowser) {
    import "jquery";
}

for those who really need it /s

Thing is, I've had to work around server rendering errors such as <Component>.animate is not defined, while animation is part of the Angular 2 framework, I've also had to do my own "in-page" cache and http implementation so my api server isn't hit twice at each page load.

"Backwards compatibility" makes sense of course, but it's just that there's still issues within the angular 2 framework, I don't have any further questions but thanks for the answers.

jeffwhelpley commented 8 years ago

So, totally fine to do if (isBrowser), however my opinion is that you should avoid the use of that if you can and instead use the Angular DI to abstract out client-only or server-only services. This does not work for components since they aren't loaded through DI, but with services you can have a common interface between client and server, but only the client side has an provider that is put in the client side bootstrap. The server side bootstrap doesn't contain anything so that service isn't implemented. This type of setup is slightly cleaner.

PatrickJS commented 8 years ago

Zone.js allows us to support anything now

MarkPieszak commented 8 years ago

Woah what, how's that? @gdi2290 :8ball:

PatrickJS commented 8 years ago

it's a ton of magic but it makes the impossible possible ;)

PatrickJS commented 8 years ago

I updated this issue to only focus on jQuery while browser globals are moved to this issue https://github.com/angular/universal/issues/534

bhargav-sae commented 7 years ago

Is there any example out there which will explain how to use jQuery. For me it is working but getting ReferenceError: $ is not defined error

PatrickJS commented 7 years ago

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

ohabash commented 6 years ago

@gdi2290

Zone.js allows us to support anything now

? but what is the best way to refactor so that server ignores jquery ($) ? is it if (isBrowser) ?

Im looking for a solution that will make the server ignore jquery instead of refactoring component code.

angular-automatic-lock-bot[bot] commented 5 years ago

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.