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

Server side/page functionality #39

Closed
ThatTonybo opened this issue May 9, 2020 · 17 comments
Closed

Server side/page functionality #39

ThatTonybo opened this issue May 9, 2020 · 17 comments
Labels
discussion enhancement New feature or request

Comments

@ThatTonybo
Copy link

Reef's got some awesome use cases already, and I'm willing to make the switch, but I'm not sure about it's compatibility with server side work or multiple pages. I'd like to be able to click a link and change to a new URL (displaying correctly in the address bar), while keeping the instant change/fast functionality.

I was thinking, maybe using the same page and main #app component, but for each page, attaching a different component and somehow changing the address URL for display/routing purposes. Makes me wonder if a fully fledged router (something cheesy like reef-router of course) could be considered.

Side question also, is there any sort of chat/discussion group that exists for Reef? Somewhere like Reddit or even Discord would be great.

Thanks for making something that can be picked up and used awesomely in just one day.

@ThatTonybo
Copy link
Author

I went ahead and made a simple router, taking my cheesy name example. Still interested about the other questions though.

@cferdinandi
Copy link
Owner

Hi @ThatTonybo...

No router yet, but it would be interesting to add one.

I like the general direction you went with yours. There's probably some things I'd change. I'm still not 100% sure what the best way to pair "this is the current view" with "this is the template" is.

The if...else approach you've taken in the template() function seems simple enough. If they were more tightly integrated, I could either merge router parameters from the URL into the props for the template, or pass in a routerProps object as a second argument.

Vue and React take differing approach approaches on this, and neither feels particularly intuitive. I'd need to give this some thought.

A couple of things on my mind after looking at Navigo:

  1. It should support "real" URLs with the History object and a hash pattern, with a fallback to hash in unsupported browsers.
  2. It should support URL parameters, ex. /user/:id, where :id becomes an extractable value from the URL
  3. It should support nested URL patterns. I'm not sure if using a nested argument, similar to what Vue/React routers do, is the right approach. I quite like how Navigo just "figures it out" for you.
  4. I personally don't like attaching state info to the links. This may not work at all, but I would love a system where you create plain old links, and the router intercepts the clicks and just "figures it out."

Side question also, is there any sort of chat/discussion group that exists for Reef? Somewhere like Reddit or even Discord would be great.

Not at this time. Frankly, I just don't have the time or energy to manage another chat space.

@cferdinandi cferdinandi added discussion enhancement New feature or request labels May 9, 2020
@cferdinandi
Copy link
Owner

A counterargument to all of this...

JS-based routers need to recreate a lot of what browsers do out-of-the-box.

They need to catch URL clicks, make sure they point to the same domain, update the URL, listen for forward/backward button clicks, parse the URL path, shift focus back up to the top of the document, and more.

There's a compelling argument to be made for the simplicity of full page reloads with either separate directories/HTML files for each route, or query parameters (which Google recognizes as separate pages).

Separate HTML file structure

This would get you paths like /, /contact, and /about. You could load separate components in each index.html file, or load the same file and parse the path.

/index.html
/about/index.html
/contact/index.html
<a href="/about">About</a>

Query Paramters

This gets you paths like /, ?p=contact, and /=about. You serve a single index.html file, and use a helper function like getParams() to parse the parameters.

<a href="/?p=about">About</a>

Hybrid

Sometimes you need to get unique values. You can use query string parameters for those while keeping pretty URLs for everything else.

<a href="/user?id=123">My Profile</a>

This is very "not in vogue" right now, but... it just seems so much simpler.

@ThatTonybo
Copy link
Author

@cferdinandi Appreciate your views here very much. My router at most is to serve a basic use for myself right now based on my fairly limited knowledge of routing, and my limited time I have to develop such things.

I feel like any sort of extension, including something like a router, shouldn't force a specific design or way of doing things onto the user - something like the hybrid option would work well however it might be an idea to make it all customizable by the user, so they can choose what they want.

For bigger applications though, the separate HTML structure sounds like it would be better, because you can split everything up. Though with that sort of structure, that means you'd need to rely on folder structure which could get messy.

About what you mentioned about Navigo, I like the idea of it figuring it out without needing any states or things like that, as it's another case of forcing how it works onto the user, it's a quick and practical way to do it though. A sort of need to strike a balance between simplicity and complexity though. Having the ability to grab URL parameters is a must also.

Not sure what you mean by nested URL patterns by the way, something like /user/:id/messages/:id or totally different to that?

Overall though, I think something like a proper router with good functionality would take a little while with some long term discussion to work out what's best.

As for the chat group, that's fine, for most cases it's not even really that great, though it's certainly handy in some cases for discussion or asking questions that the community might know.

Thanks again for getting back to me. If you feel it'd be necessary, I'm willing to modify my router or even accept a pull request to pull it up to standard or add a bit more functionality.

@cferdinandi
Copy link
Owner

Quick update: there's a router in the works, almost done and available for preview without documentation on the router branch.

Reef.Router() will provide deeper integration with Reef than you would get with off-the-shelf alternatives.

It doesn't not require you to add any special properties to your links or use custom elements.

Step 1: Create your links

Just like you would normally.

<ul>
	<li><a href="/">Home</a></li>
	<li><a href="/about">About</a></li>
	<li><a href="/contact">Contact</a></li>
</ul>

Step 2: Define your routes

Create a new Reef.Router() to define your routes.

// Create a router
var router = new Reef.Router({
	routes: [
		{
			id: 'about',
			title: 'About',
			url: '/about'
		},
		{
			id: 'contact',
			title: 'Contact Us',
			url: '/contact'
		},
		{
			id: 'home',
			title: 'Home',
			url: '/'
		}
	]
});

Step 3: Associate your router with one or more components

Pass your router in to the router property on the Reef options object. The route object is automatically passed into the template function on render.

// Create an app
var app = new Reef('#app', {
	router: router,
	data: {
		greeting: 'hello!'
	},
	template: function (props, route) {
		return `
			<h1>${route.title}${route.params.id ? `: ${route.params.id}` : ''}</h1>
			<p>${props.greeting}</p>`;
	}
});

Any time a new router is trigger, any attached components automatically re-render.

The document title is also updated, and focus management is handled for you as well.

@cferdinandi
Copy link
Owner

@ThatTonybo So... you unfortunately scooped up reef-router on NPM. How do we get that transferred over so I can publish the official project?

@cferdinandi
Copy link
Owner

@ThatTonybo Actually, never mind. I've got something else figured out.

@ThatTonybo
Copy link
Author

I'm happy to unpublish my router or leave a note to use the official one if need be. Happy that you've got something going, it'll make working with bigger sites nice for sure.

@cferdinandi
Copy link
Owner

Yea, no worries at all! I realized Reef is reefjs on NPM, so if I published it as it's own thing, I'd use the same naming convention (reefjs-router).

I'm still debating between making a separate module and keeping it as a separate file within reefjs itself.

@ThatTonybo
Copy link
Author

If it doesn't add too much onto the existing size of the package and you think enough people will have a use for it, I don't think there's much harm in including it as part of reefjs. Although for modularity reasons (and maybe in the future if you want to publish other parts) splitting it into another module would be better.

I feel splitting it would be the better choice, so long as documentation for it is put with the rest (Under Advanced maybe? Don't think it needs an entire page).

@cferdinandi
Copy link
Owner

Yea, I'm using poor word-choices here, too.

So... it would always be a separate "module" in the literal sense. I'm just not sure if it needs its own repo or not.

As in...

// 1. Both files under `reefjs`
import Reef from './reef/dist/reef.js';
import Router from './reef/dist/reef-router.js';

// 2. Separate repos
import Reef from './reef/dist/reef.js';
import Router from './reef-router/dist/reef-router.js';

Of course, neither of these respect the NPM way of doing this, where you point to a package and drop the .js because of the package.json's main property.

@cferdinandi
Copy link
Owner

Routing add as an optional script in v7.1.0

@ThatTonybo
Copy link
Author

Got one more question regarding the new router, default functionality seems a bit off?
image
I'm using all default values/settings and it seems the URL changes, but not the page content. It also doesn't render anything on first load which I assume is due to it not knowing which route it's on.

@cferdinandi
Copy link
Owner

There were a few quirks that were fixed in the latest version. Make sure you’re using 7.1.4.

@ThatTonybo
Copy link
Author

I downloaded 7.1.4 directly off GitHub releases. Might try the CDN and see if that sorts anything.

@ThatTonybo
Copy link
Author

@cferdinandi Might of found the issue, which seems to be route positions:

		{
			id: 'about',
			title: 'About',
			url: '/about'
		},
		{
			id: 'contact',
			title: 'Contact Us',
			url: '/contact'
		},
		{
			id: 'home',
			title: 'Home',
			url: '/'
		}

Something like this works as the / is at the bottom, but:

		{
			id: 'home',
			title: 'Home',
			url: '/'
		},
		{
			id: 'about',
			title: 'About',
			url: '/about'
		},
		{
			id: 'contact',
			title: 'Contact Us',
			url: '/contact'
		}

As / is at the top, it fails to get to any other routes. Tested on 7.1.5 as just released.

@cferdinandi
Copy link
Owner

@ThatTonybo Popping this out into its own issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants