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

Extend server-side rendering by adding Express middleware support #95

Open
astoilkov opened this issue Oct 4, 2015 · 9 comments
Open

Comments

@astoilkov
Copy link
Owner

As discussed in #92

@Kanaye
Copy link
Collaborator

Kanaye commented Oct 31, 2015

Does this need more work than just a function that take the options, creates the Middleware and returns the Middleware.tryServePage function ?
Do you have a name in mind for that function ?
I can not come up with anything better than blocks.middleware and I kind of don't like that name.

@astoilkov
Copy link
Owner Author

Yeah. Actually this is super easy to implement. I will thing about a name and get back to you. I will also take a look at the code and try and remember if there was anything additional I wanted to do for this.

@kokujin
Copy link

kokujin commented Nov 30, 2015

Any news on this issue?

@astoilkov
Copy link
Owner Author

Hi @kokujin. I have some more ideas about blocks.middleware. However, until I have the time to complete them I think exposing a method blocks.middleware will be sufficient. What do you think @Kanaye?

@Kanaye
Copy link
Collaborator

Kanaye commented Nov 30, 2015

Sounds like a plan.
PR is on it's way as I played a little with it a week ago or so.
We could leave this issue open so we have a place to discuss possible enhancements for that API.
I thought a bit about it and I am thinking about a way to add data from "outside" the server side rendered app.
Cause the server shouldn't need to AJAX itself, in case you are using the same express app for blocks and an API.
Just some things I'm currently thinking about.
[edit: typos again]

Kanaye pushed a commit to Kanaye/jsblocks that referenced this issue Nov 30, 2015
@Kanaye
Copy link
Collaborator

Kanaye commented Nov 30, 2015

Okay not as easy as I thought, it seems I missed some cases while playing with it.
First we can't just return the middleware as it would only serve the rendered HTML.
My solution is that we would return an express app with the middleware and an express.static middleware registered.

The second problem is, that a view registered to the route '/' does not get shown if the app is mounted to something else then '/', e.g.:

/* ... */
app.use('/web', blocks.middleware());
/* ... */

the router will calculate wrong routes.

@Kanaye
Copy link
Collaborator

Kanaye commented Dec 1, 2015

I will describe the problem in a detail. To make it easier start with an example:

// Server side...
var express = require('express');
var blocks = require('blocks');

var MainApp = express();
var SubApp = express();
/* do things and stuff with the main app */
SubApp.use(blocks.middleware(/* options here */));
MainApp.use('/web', subApp);

MainApp.listen(8000);

So we have a MainApp and a SubApp mounted to the route /web.

// the blocks app
var App = blocks.Application({
    history: 'pushState'
});
App.View('Home', {
    options: {
        route: '/'
    }
/* ... */
});

App.View('Test',   {
    options: {
        route: '/test'
    }
/* ... */
});

If we now fire an request to http://localhost:8000/web the server will render the Home- View and send it's HTML.
This is cause the req.url will be '/'. So the server-side app see's http://localhost:8000/.
But the client side app see's the real url and will hide the view as it does not know an view with the route /web.
If the app has view without an route e.g. as the navigation and someone clicks an element with data-query="navigateTo($root.Test)" it will render the right view and show it.
But the url will be http://localhost:8000/test so if you reload the page it will fail because the server-side app will never get called.

The req object has an property baseUrl wich shows the complete path before req.url.
To be clear:
The full url (e.g. in browser): http://localhost:8000/web/test.
In our middleware in the app above:
req.url => /test
req.baseUrl => /web.

My approach is to create a new property baseUrl in the Router and use it to generate urls and to figure out on which view we the app is when set and the app is in pushState-history.
I would use the req.baseUrl url and transfer it in window.__blocksServerData__ object
So we would also have the correct url on the client.

What do you think about this aproach? @astoilkov

@astoilkov
Copy link
Owner Author

Ok. Let's recap to see if I have understood you correctly. You want to transfer the req.baseUrl to the client so you could append that value to every route, right?

If that's the idea I like it. Correct me if I am wrong.

Is that everything we need to do to support a middleware scenario?

@Kanaye
Copy link
Collaborator

Kanaye commented Dec 2, 2015

Yeah, that's it basically.
I have a working approach diff here
but it needs more testing and some clean ups.

I think I can provide a working (and tested) version tomorrow or Friday.

Kanaye pushed a commit to Kanaye/jsblocks that referenced this issue Dec 9, 2015
Kanaye pushed a commit to Kanaye/jsblocks that referenced this issue Dec 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants