Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Server Rendering #103

Closed
joeldenning opened this issue Aug 2, 2017 · 21 comments
Closed

RFC: Server Rendering #103

joeldenning opened this issue Aug 2, 2017 · 21 comments

Comments

@joeldenning
Copy link
Member

joeldenning commented Aug 2, 2017

Some single-spa applications may want to server render some or all of the child applications that are active for a url. How to pull that off is not decided, but here's what I'm thinking for it so far:

const location = {href: '/url#/hash', hash: '#/hash'};
// New API for single-spa returns an array of string names.
const activeAppNames = singleSpa.findActiveApplications(location);

// The serverRender API will load the app but will probably not bootstrap it and will definitely not mount it. Instead it will check
// for a new lifecycle method (serverRender?) on the application. If the lifecycleMethod exists, it calls it. If not, it returns an empty string
Promise
  .all(activeAppNames.map(singleSpa.serverRender))
  .then(serverRenderedHtmls => {
    const finalHtml = serverRenderedHtmls.join("");
    res.write(finalHtml);
  })

Advantages of doing it that way:

  • The user of single-spa can control which applications to server render
  • findActiveApplications might have other use cases besides server rendering

Disadvantages:

  • You have to load the child application before you even know whether it supports server rendering or not. I'm not sure how this would be solved in any other way, though, besides perhaps including some configuration during declareChildApplication.
@rainboxx
Copy link

rainboxx commented Nov 24, 2017

The user of single-spa can control which applications to server render

I think this one is very importing for people that are doing migrations from older frameworks, eg. AngularJS 1.x.

perhaps including some configuration during declareChildApplication.

I thought about this while reading the intro of that paragraph. One could set serverSideRendering: false and bypass the check at all, while for all others the app will be loaded and still checked for the respective method to render to a string.

Was there already some progress beside this ticket?

@joeldenning
Copy link
Member Author

joeldenning commented Jan 9, 2018

@rainboxx apologies for the (very) late response on this.

I have not begun writing code for this. Would you be interested in collaborating on this?

@rainboxx
Copy link

rainboxx commented Jan 9, 2018

Hey @joeldenning, interested definitely. I might be able to also get time from my client to work on this, since we're planning to integrate this framework. How would you start? What would be a timeline?

@joeldenning
Copy link
Member Author

joeldenning commented Jan 10, 2018

To start out, maybe let's find a time to chat about it? Maybe on single-spa's slack we could go over the suggestions and questions above and figure out exactly what API we want single-spa to implement? I am not an expert in server rendering and welcome all feedback and suggestions.

I am online during U.S. business hours and also during nighttimes. You're in germany? Maybe if the timezones don't line up we could continue discussing asynchronously here in this issue, but I think hashing things out all at once might be more productive.

Your thoughts?

@rainboxx
Copy link

rainboxx commented Jul 2, 2018

Hey @joeldenning, sorry for not responding so long. The single spa framework approach had a low priority in the project I was working on. I left this project as of last month so finding time got even more worse :-(.

@joeldenning
Copy link
Member Author

joeldenning commented Jul 9, 2018

Ah sorry to hear that. If you or anybody else would like to reopen the conversation about single-spa server rendering, please do! I'm closing this comment for now, but would love to explore this.

@joeldenning
Copy link
Member Author

joeldenning commented Jan 17, 2020

Reopening this - core team talked about this and thinks it would be valuable. Here are the steps I can think of:

  1. get single-spa and SystemJS running in node
  2. Figure out how to get activity functions to run properly in node and allow server code to provide url
  3. Figure out the domElementGetter stuff in node
  4. Defer to framework for server rendering
  5. Compose a single html file with everything
  6. Ensure hydration works

@StyleT
Copy link

StyleT commented Feb 28, 2020

Hi! We're actively working on our own implementation of the SSR support here https://github.com/namecheap/ilc
It uses "single-spa" & TailorX to achieve the desired behaviour.

PM me if you guys are interested.

@joeldenning
Copy link
Member Author

joeldenning commented Feb 28, 2020

@StyleT I'd love to hear the direction you're going with server rendering and TailorX. I mentioned you in a slack conversation in the #maintainers channel - let's discuss there!

https://single-spa.slack.com/archives/C9JV40F7V/p1582917635011100

@joeldenning
Copy link
Member Author

joeldenning commented Mar 20, 2020

After some discussion with namecheap and also with @ScriptedAlchemy, we are going to go a different direction with this. We think that we will encourage the following:

  1. Each microfrontend runs its own nodejs server. They do not share a server.
  2. single-spa's checkActivityFunctions() api will work in nodejs (see Support for running single-spa in nodejs. #494)
  3. The fetching of html and other data from microfrontends is still TBD

@ScriptedAlchemy
Copy link

ScriptedAlchemy commented Mar 21, 2020

I can provide an example of the render middleware if that helps

@joeldenning
Copy link
Member Author

joeldenning commented Mar 21, 2020

👍 please do

@ScriptedAlchemy
Copy link

ScriptedAlchemy commented Apr 6, 2020

Primitive example of SSR via module federation. https://github.com/module-federation/module-federation-examples/tree/master/server-side-rendering

webpack-dev-middleware has some bugs in HMR. If you need it, I wrote something that serves as a replacement for hmr on the client-side until webpack-dev-server is more stable. Currently using it in my upgraded next.js repo to power their HMR. In this example repo, I've done the bare minimum and only run it in production mode. But I do have this dev functionality working on Next, so I know its a matter of cleaning up the development.js middleware file.

@joeldenning
Copy link
Member Author

joeldenning commented Apr 6, 2020

Thanks for sharing that example.

I am doing a proof of concept at https://github.com/isomorphic-microfrontends - will share progress as I go along.

@joeldenning
Copy link
Member Author

joeldenning commented Apr 27, 2020

I'm shifting to a layout engine for now (#525) and will come back to server rendering after that. SSR might use the layout engine, so I think that this might be the proper order to do it in

@joeldenning joeldenning changed the title Figure out server rendering RFC: Server Rendering Apr 27, 2020
@ScriptedAlchemy
Copy link

ScriptedAlchemy commented Apr 27, 2020

Got SSR working over distributed networks. So I'm able to require() from s3 on-demand - treating it like the native file system, also could work with fetch() as well.

The layout engine is a good way to go if you cannot avoid the need for a controller somewhere at the head of the app. Since this is a non-webpack solution, it might be the optimal solution

@filoxo filoxo mentioned this issue Jun 24, 2020
@mbohgard
Copy link

mbohgard commented Sep 23, 2020

@joeldenning What have you learned or tried since you last visited this subject? We're worried about the SEO of our planned huge project with multiple SPAs tied together with i.e. single-spa.

@joeldenning
Copy link
Member Author

joeldenning commented Sep 23, 2020

Hi @mbohgard - I've made a lot of progress, actually. Check out single-spa/single-spa.js.org#333, which has some documentation and a link to an example.

@mbohgard
Copy link

mbohgard commented Sep 23, 2020

@joeldenning That's awesome. I'll dig in to that. Thank you!

@joeldenning
Copy link
Member Author

joeldenning commented Oct 2, 2020

The documentation for server-side rendering is now live at https://single-spa.js.org/docs/ssr-overview

@ScriptedAlchemy
Copy link

ScriptedAlchemy commented Oct 24, 2020

Well done!

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

No branches or pull requests

5 participants