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

Proposal: Socket Engine - Framework and Platform agnostic Angular Universal rendering. #1000

Closed
Toxicable opened this issue May 19, 2018 · 41 comments

Comments

@Toxicable
Copy link

Toxicable commented May 19, 2018

While I personally think that having a separate NodeJS Express server for handling SSR is good solution it's not always possible to do so in every environment.
Therefore we can provide a simple and easily solution that enables Universal on any platform or framework.

Angular Socket Engine

Draft implementation: #999
Framework and Platform agnostic Angular Universal rendering.

Usage Server

npm install @nguniversal/socket-engine @nguniversal/common --save

const socketEngine = require('@nguniversal/socket-engine');

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');

socketEngine.startSocketEngine(AppServerModuleNgFactory);

This will the socket engine which internally hosts a TCP Socket server.
The default port is 9090 and host of localhost
You may want to leave this as a plain .js file since it is so simple and to make deploying it easier, but it can be easily transpiled from Typescript.

Usage Client

Your client can be whatever language, framework or platform you like.
Aslong as it can connect to a TCP Socket (which all frameworks can) then you're good to go.

This example will use JS for simplicity

import * as net from 'net';

const client = net.createConnection(9090, 'localhost', () => {
  const renderOptions = {id: 1, url: '/path',
    document: '<app-root></app-root>'} as SocketEngineRenderOptions;
  client.write(JSON.stringify(renderOptions));
});

client.on('data', data => {
  const res = JSON.parse(data.toString()) as SocketEngineResponse;
  server.close();
  done();
});

GRPC Engine

Draft implementation: #1003
Another proposed implementation thats very similar to the above Socket Engine, but instead of using a TCP Socket as the transport it uses GRPC.
This will make consuming it much easier since we can provide the .proto file and you're good to go.

Feel free to discuss advantages of both implementations.

@lionskape
Copy link

This is perfect! ECommerce are realy need this feature.
I think GRPC engine will be much more better than TCP.

@Toxicable
Copy link
Author

@lionskape We're happy to hear why one might be better than the other.
We may also end up implementing both, since they're simply implementations of an Interface they're relatively easy to maintain

@swaechter
Copy link

swaechter commented May 23, 2018

Hey @Toxicable thank you very much for this draft. After some thoughts this looks like a really interesting idea because all communication is done via TCP and no further language bindings are required to communicate with the renderer code (Like I did with J2V8 in my own solution). This allows a larger adoption, still Node.js is required (Maybe I just have to get rid of the idea to do it without Node.js at all).

A few questions:

  • Is there a way to consume the libraries? At the moment the PR is still failing. It would be great if there is a possibilitiy to consume them, so I can implement a Java solution in the next days.

  • Is there a way to stop the server or should we just terminate/kill the Node.js process executing the script?

  • Does ls-routes and the function createFactoryAndGetRoutes allow us to retrieve all routes including the lazy loaded root routes? That would be really helpful to handle routing in my Java middleware

  • What are your thoughts about cookies? Do you have some techniques in mind how to pass the session/cookies from language X to the TCP server and back?

Btw: I try to keep things simple, so I prefer TCP over gRPC. But I can also implement a Java gRPC version if you are interested.

Best,
Simon

@Toxicable
Copy link
Author

@swaechter

Is there a way to consume the libraries?

Right now there's no way to consume the libs. However you can just copy paste it into your app (note you'll need to copy paste Common Engine aswell.

Is there a way to stop the server or should we just terminate/kill the Node.js process executing the script?

The function returns a handler which you can call server.stop()

Does ls-routes and the function createFactoryAndGetRoutes...

This was a mistake on my part, the ls-routes is in a separate PR, I accidentally put it into the socket-engine one.
However for that one, yes it can retrieve all routes, lazy and eager, although it's just lsRoutes the function createFactoryAndGetRoutes shouldn't be exposed as a public api.

What are your thoughts about cookies?

I havn't put any effort into cookies just yet, but that's definitely something we can add onto these new additions. Right now i'd just like to keep it simple and make sure it solves the problems that people have with Universal on other platforms.

still Node.js is required

It will really always be a requirement, sure other tools such as J2V8 allow you to get around it but simply using Nodejs is a much much simpler solution.

@yanshuf0
Copy link

yanshuf0 commented Jun 4, 2018

What's the ETA on this? Will there be documentation/examples?

@Toxicable
Copy link
Author

@yanshuf0 It is our highest priority at the moment.
It's currently blocked on a few Bazel issues but once they're resolved then it shouldn't be far away.
It's hard to give a timeline since there's a bunch of factors that can throw that out the window, such as my avilablity, blockers, other release related issues.

Initially there will be a quick doc on how to get started just so we can get it out as fast as possible.
But we will add better examples and docs later on.

You can track them here
#1003
#999

@dherges
Copy link

dherges commented Jun 5, 2018

When you ask for "when is it ready?" ask first "what could I do to make it quicker/better?"

@yanshuf0
Copy link

yanshuf0 commented Jun 7, 2018

@dherges ok?

@inunotaisho
Copy link

@Toxicable So what is the status of the Java component of Universal?

@Toxicable
Copy link
Author

Toxicable commented Jun 26, 2018

@inunotaisho26
There wont be a Java specific component.
This proposal opens up generic transports for Angular Universal
Either one of these will require a small amount of code to talk to them on the Java side but it will be very minimal.
Take a look at this example here in Nodejs, the equivilent of this is what needs to be done in Java.
https://github.com/angular/universal/blob/ea6f7b13b70c40b55ce72bd549e2dfb56ca146db/modules/socket-engine/README.md#usage-client

Current status:
Socket Engine: This is mostly done, just requires a review.
GRPC Engine: Blocked on a bazel issue at the moment.

@vxhviet
Copy link

vxhviet commented Jun 28, 2018

Hey @Toxicable, if you don't mind could you please give an example on how could I use the suggested solution. Sorry, I'm an Android developer that just side track into front-end dev to create an ad-landing for our app, so a lot of this stuff is still very new to me.

I got stuck at this step in the official tutorial as our backend is in Java/ Spring. I have a rough idea of putting the Usage Server section in your solution into the server.ts file and the Usage Client need to be translated into Java and should go into our backend side. Is that correct?

@Toxicable
Copy link
Author

@vxhviet This is not ready yet, there is still work to be done before we can release this.

@9you
Copy link

9you commented Jul 16, 2018

Hello @Toxicable. I think it's really nice if we can pass some pre-fetched data to the TCP server to avoid additional API requests or passing user's selected locale (like we usually do window._some_name = { some_json_data };). Or at least we can pass cookies to TCP server to deal with APIs that have authentication enabled.
Thanks.

@Toxicable
Copy link
Author

@9you The TCP server will simply be running your application through platformServer.
So any sort of caching should be done through there, which is not at the TCP Server level or in the scope of this proposal.

@someApprentice
Copy link
Contributor

Thanks to @nguniversal/common, I could implements thrift-engine by myself.

Impressive. But it may be not necessary because to solve this problem you need just simple add providers argument to the engine. Im already working on that pull request but I have some issues with a building application.

You can help fix this issues and providers feature for socket-engine will be sooner.

@CaerusKaru
Copy link
Member

@gosp see #1003

@someApprentice
Copy link
Contributor

What do RenderOptions do? To get a template for a particular route, you just need pass the url parameter. And, moreover, you always need to pass the <app-root></app-root> value to the document parameter, otherwise there will be an error. And to send a GET request, you must pass it to the url parameter either (e.g. /details/12). So, the id parameter is also not clear for what.

So what exactly do these parameters do?

@Toxicable
Copy link
Author

The id parameter is not used for rendering. It's used by the client to identify which request the content was rendered for. Since we're using bidirectional sockets here there's no request/response like with HTTP, therefore you need some identifier to figure out what response from the universal server correspondence to the request you just made

@someApprentice
Copy link
Contributor

@Toxicable so if I want to make a several request at the same session I must define a several id accordingly, is it correct?

And what does the document parameter?

@MattiJarvinen
Copy link

Hmm... Has anyone used something like https://github.com/zeit/pkg to package whole node + app with dependencies into one binary?

Binary compile targets:

  • nodeRange node${n} or latest
  • platform freebsd, linux, macos, win
  • arch x64, x86, armv6, armv7

@RadouaneRoufid
Copy link

Hi,

I want to know if there is a solution to get the cookies server side. How can I achieve this using this lib ?

Thank you.

@meiordac
Copy link

meiordac commented Mar 8, 2019

really need this feature (or an implementation for Universal PHP)

@angular angular deleted a comment from vinay-akkipet Aug 19, 2019
@hahmed09
Copy link

hahmed09 commented Oct 18, 2019

When will this be released?

@jpmmartin
Copy link

Hello can someone provide some example of how this should be used with php backend?

@vinay-akkipet
Copy link

Can the team please provide a tentative date for this release, that would help us wait on this if it isn't too far away from now. Thanks!

@tayambamwanza
Copy link

@vinay-akkipet I'd hate to be negative but I think they are focusing on angular 9 and ivy

@sergey-morenets
Copy link

@tayambamwanza Yes, we understand that. But Angular 9.0 (with full Ivy support) and 9.1 were already released

@tayambamwanza
Copy link

@sergey-morenets Lol not at the time that I posted the comment, 13 January.

@LayZeeDK
Copy link

LayZeeDK commented Apr 7, 2020

@nguniversal/socket-engine and @nguniversal/common have been released throughout versions 6.0.0-9.1.0. Is anything missing?

@sergey-morenets
Copy link

@LayZeeDK That's fine. Do we already have socket-engine integration with Java/Spring Boot?

@LayZeeDK
Copy link

LayZeeDK commented Apr 8, 2020

@LayZeeDK That's fine. Do we already have socket-engine integration with Java/Spring Boot?

I haven't tried out any of these releases, but if this proposal has been implemented as part of them, we just need to spin up the socket engine and connect to it through a TCP socket as described by OP.

@ahsan79
Copy link

ahsan79 commented May 2, 2020

@Toxicable , Can you please explain the flow and high level logic of your implementation. I am new to Angular and as I can understand from the code, the agnostic platform (Python, Java, php etc) is creating a conection to port 9090 of Node API server passing the SocketEngineRenderOptions and is returning the SocketEngineResponse, which is the prerendered page to Angular which will then render it on the Browser. Is it right?
Also I want to understand that whether Node will still be needed in backend to make this work and therefore will there be a need of Node server once we deploy it into production.
And if the above client and server side code works, can you please provide some documentation? Thanks

@webchannel-idc
Copy link

Any update on this? Any chance of running SSR on a Java app/Tomcat server? :)

@swaechter
Copy link

@webchannel-idc A few years ago I wrote a Java implementation/proof of concept (See this thread). After solving so many issues (and seeing so many more open, unsolved ones) I would definitely recommend to use Node.js to host the frontend and to SSR there - not in Java. The developer experience (E.g. debugging) is so much better

@alan-agius4
Copy link
Collaborator

This issue is now obsolete due to changes in the recent releases.

@sergey-morenets
Copy link

This issue is now obsolete due to changes in the recent releases.

Hi @alan-agius4

Can you please specify that changes?

@alan-agius4
Copy link
Collaborator

The @nguniversal/socket-engine has been deprecated and removed in version 15 as such this issue is obsolete. We are revisiting on ways to make universal more pluggable without the need for @nguniversal/socket-engine.

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Mar 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests