I am using mithril 0.2.2-rc.1. I saw in the routing documentation:
Routing is a system that allows creating Single-Page-Applications (SPA), i.e. applications that can go from one page to another without causing a full browser refresh.
Indeed when I am routing to the same page with different parameter only the part that I want to change is refresh expect this :
m("img[src='assets/images/logo.png'][alt=''][width='100']")
I can see in the network communication that the image is reloaded (another GET request).
Is there a way to avoid that?
route.js
m.route.mode = "pathname";
m.route(document.getElementById('app'), '/', {
'/': main,
'/modelling/:level': main
})
It's difficult to see how the two pieces of code fit together, but two things suggest themselves:
Every change of route (even if that change results in the same route entry, eg /modelling/x to /modelling/y) will result in the entire DOM being regenerated. You can prevent this behaviour by calling m.redraw.strategy( 'diff' ) in each route component's controller.
Repeatedly requesting the same resource does not lead to extra calls to the server: a multi page site with every page requesting the same JS and CSS will only load those resources once, and will hit browser cache on subsequent requests. Thus repeatedly asking for the same image resource will not generate any new calls to the server.
If you check the documentation of the m method you will see that the config attribute lets you retain elements across redraws. So this should work for you:
m('img', {config: function persist(el, isInit, context)}) {
context.retain = true;
}
Related
I know how a MVC application handles routing,
(/foo/bar get) request hits the server
route /foo/bar with get method is found or not found, if found route handles the request by calling a method which serves a view page with corresponding data filled up.
client gets a html document with many links to other pages.
Another link is another procedure just like this one.
However, I have been learning react+meteor pack, which is a SPA (single page application) without ssr(server-side rendering). The most critical part that gets me confused is routing.Let's say I have 3 different routes for my SPA. (/), (/route2), (/route3)
(/route2) request hits the server. What does the server serve ? The whole application code with (/route2) active or what ?
Let s say we are on (/) route and clicked (/route2) route. So what s happening now ? Does react empty the #mainDıv and put related component instead, from where, the bundle.js which already contains all of the views' html as components ?
Is there a way to send only requested page's html and js, and after showing the content, getting other pages' html and js in the background, without client even feels. So that when another route is hit, only data will be on the wire.
Finally , only sending the related page's html - css - js when requested,I don t don't know if such a technique exists, seems to lack the SPA experience, but I am not sure If it would lack SPA expereince. It would be great to explain how to approach this issue.
With a SPA you typically (read: virtually always) configure your server to serve the same bootstrap HTML/Javascript regardless of which URL has been requested. A request for /route2 will get the same HTML response as a request for / or any other URL (unless you have specific exceptions for specific reasons). The SPA always starts with the same bootstrap code and examines the current browser's URL, then dynamically loads content as needed. How exactly that content is loaded and when it is loaded depends on the specific framework/code/circumstances/configuration, but yes, ultimately the contents of the DOM are dynamically being replaced by Javascript.
I've run into a situation where I would like to be sure about how do browsers handle URIs that include a fragment identifier, such as Products#A. Imagine my website has two pages: Products and FAQs. Then, inside each I want to use # to navigate to specific HTML elements. So:
What is the difference between href="Products#A" and href="#A" if I'm already in page Products?
And if I'm in page FAQs?
Does placing an URL like in href="Products#A" always triggers a server call or does the browser know that it is already on page Products and it does not make a server call?
What is I add a / (like href="/products#A")? Does this force a server call?
Is this standard for all browsers?
I've run a few tests but I'm missing some theory here.
If the link, fragment excepted, resolves to the same URL as the current page, then it will navigate around the current page.
If it resolves to a different page, then it will load a new page.
It doesn't matter how the relative (or absolute) URL is actually expressed, only what it resolves to.
To answer your questions, I am doing these with my own experience.
What is the difference between href="Products#A" and href="#A" if I'm already in page Products?
Nothing. Just for safety, and if you are in a different page, and the content is rendered using the same partial (or the same source), this might help.
And if I'm in page FAQs?
It navigates normally to Products and finds the element with id="A" and scrolls to there.
Does placing an URL like in href="Products#A" always triggers a server call or does the browser know that it is already on page Products and it does not make a server call?
That's a client call, no server calls are made for URL fragments.
Is this standard for all browsers?
I believe so.
I want to allow users to request webpages of my website both directly from the server or using links, which will be handled by Backbone's router.
When a user requests a webpage directly from the server, a full page is served (with html, head, body, stylesheets and scripts).
On the other hand when a user requests a webpage by clicking on a link, only the relevant part of the page is requested and then inserted in the correct place, and other elements of the webpage remain untouched.
By inserting in the correct place I mean creating a View once a particular route is reached. The view is then initialized and calls its render method to fetch the relevant part of the webpage and inserts it into DOM using $el.html(content).
But I do not want to call the view's render method when a webpage was fetched directly from the server, because all needed content has already been rendered, and re-rendering it only causes some ui-flickering effects.
Is there some common way to let Views know that they shouldn't render themselves, because the fully rendered webpage has been fetched from the server?
I could pass a flag like clientSideNavigation = true to the router, everytime a link is clicked, which then will be passed to views by the router so that they know whether to render the content or not.
But it does not work when user uses aa back/foward buttons.
I could also check in a view if within its $el there is some particular element that should be present on this webpage - for instance if I had a view called CatsView I could check if #cats-box is within its $el element. But it involves some more DOM manipulations, which I would prefer to avoid.
Have a root view and have place holder for child views. First time render the complete page from the server.
For rendering parts of the view on link clicks, you can define corresponding events hash on the root view.
Let the event handler callbacks call a controller(custom js object) which does the job of loading the data ,constructing the view and passing the data to it.
Finally also update the url with Router navigate(http://backbonejs.org/#Router-navigate) method with {trigger:false} to the corresponding url, so then when refresh is hit, the user comes back to the same view.
In the router callback for the specified url call the same method on controller object by passing a flag so that the functionality is in sync and also using the flag you can prevent calling router navigate method since its not required.
I own a single page application implemented using AngularJs.
Let's suppose my application has 2 pages, sharing the same main top-navbar.
The navbar should display (among other things of course) the current number of unread messages addressed to the connected user, like this screenshot shows:
In my current implementation, while AngularJs starts to be loaded, I trigger in the run method an ajax query to get all the current user's messages (of course, just after the query aiming to check if any user is authenticated).
However, as $http.get is perfectly asynchronous by nature, it is frequent that there is a delay of one or even two seconds (in the worst case, if there are many messages and an additional logic) between the navbar display and the update of number of messages:
............ 1 second later ......
If the icon was a specific page content, I could use the resolve property of the template, but in this case, the navbar is shared by each page.
Should I display some icon representing a "load" of messages while messages are queried to inform user that some messages may be present?
How to deal with this case?
It seems to be the main drawback of single-page-application IMHO.
Indeed, in a non-single page application, the query could happen at server side before server before sending the web page to the client, leading to no delay at all.
I see this as the beauty of single page apps. Rather than waiting seconds for a page to load messages (on the server) that I might not be interested in, it can be lazy loaded giving me instant feedback to perform my desired task.
I would typically go with a directive for something like this and stay off $rootScope, but it sounds like ngShow/ngHide would be able to tie in directly to your setup:
HTML/JADE (classes are just an example)
div#messages(ng-show='messages')
i.fa.fa-envelope-o
span.badge {{messages.new.length}}
div#msgLoading(ng-hide='messages')
Javascript/Angular
.run(function($rootScope, $http, ...
...
//$rootScope.messages has not been instantiated yet
$http.get('//someendpoint').then(function(results) {
$rootScope.messages = results.data;
});
...
I have an web app. Basically its a single page application. The initial page is a flat html file called index.html, with a single script declaration pointing to require.js. From there I use backbonejs to handle the client side logic. The index.html is being served by nodejs.
My issue is that, any action within the page, for example, i click on a link, the backbone router is called. Which is the behavior I want being a single page application.
For example: www.testserver.com then i click on a link which shows a modal screen for registration www.testserver.com/register, via backbone router with push state on
The issue arrises when, instead of accessing a certain link within the app, i open the url straight in browser. For example I paste, www.testserver.com/register, in the browser. The request is then sent to my node router. I am assuming this is the correct behavior, since the page doesnt exist yet, meaning the backbone router doesnt exist as well.
I was wondering, on what the correct work around for this is. What am i supposed to do, when i access this link? How do i pass the correct behavior back to my backbone application.
Thank you very much.
The server should return always the index.html page. When you start the router in your Backbone than, the router handle the navigation and call the function you defined for the actual route.
Assuming you don't need to do any SEO type stuff such that each unique URL loads its own metadata, just always serve the same index.html as stated. However if you want to have different static head content based on the URL, you should do that within node based on the path (e.g. keep an array of metadata for each route that you slip into a slightly-more-dynamic initial view template, based on your existing flat index.html)