I was on Twitter the other day, and I opened chrome devtools and went into the network console, and then clicked on a link on Twitter (specifically the one on the menubar which said 'Me'), and then, as always, the page didn't really load again, it seemed to be AJAX-ified, but then I looked into the network content, and all I saw was a few images and a few javascript files.
Unless Twitter loads content from the 'Me' page on the loading of the home page (which I highly doubt, since Twitter is pretty fast at loading too), what can make the navigation between Twitter's pages so fast?
Like all JS apps, the pages you see are just "views". You are on the same page, stuff gets loaded via AJAX, and then JS renders the data with the template to form that view.
Here's a scenario: when you open a clean browser and go to Twitter's timeline, everything loads. This also includes all scripts that are needed to render the succeeding pages.
Now, when you go to another page, like the "Me", Twitter does not have the resources of the page just yet. So, it loads via AJAX the needed resources to render the "Me" page like all data, and the template for it. After loading, it renders the data and with the template to form the "Me" page.
Now when you go back to the timeline, Twitter never discarded the timeline data but cached it (localstorage at best). Thus going back to the timeline (or any visited page for that matter) is just a matter of reading cached data, cached templates and rerendering the view onto the page. No network requests needed at all.
As you also notice, new data is retrieved incrementally, by just querying from the server new tweets rather than getting them all back. Only when the page determines that it needs a fresh set of data will it query a bunch of them.
Also, JSON data is a million times (to exaggerate) lighter than loading a normal page.
Related
I was browsing this website https://amaioswim.com/
and I did notice that when clicking on the navigation on the left side, the url address change instantly.
They also use a "fade out" and "Fade in" curtain to make the transition between pages seamless.
I'm wondering what kind of approach would you use to achieve this.
I know with JS you can change url, but only hashtags url... right?
or is it because they have a super fast server with 0 latency?
do you think they are loading everything ajax-ly in a same dvi container?
Thanks
This has little to do with the history API. (They are using that API to update the displayed URL, but that's a minor detail in how the site works; on its own it wouldn't create this behavior.)
This particular site is running a clientside framework. (I'm not seeing any obvious clues in the minified code as to which one.)
Links within the site are handled as AJAX requests. They're using the same endpoints for fresh page loads and for XHR calls, and are checking the X-Requested-With header to determine whether to send the full server-rendered HTML file (including the framework for the full site) or just the content for that particular page (which will be embedded clientside in the already loaded site.)
As evidence: this returns the full site (as when a user first visits that URL):
curl 'https://amaioswim.com/about'
This returns just the "about" content (as when a user clicks the "about" link after loading the site):
curl 'https://amaioswim.com/about' -H 'X-Requested-With: XMLHttpRequest'
(You can also see this by viewing the Network panel in the browser console while navigating the site.)
Loading just the content for an individual page is, of course, much faster than loading the entire page HTML (and its CSS and JS), and allows you to add glossy effects like crossfades and animations while the AJAX call is in progress.
Since some years you can use the html5 history api:
https://css-tricks.com/using-the-html5-history-api/
It will allow you to manipulate the url quite freely.
For example when you scroll to a new section you can put that section at the end of the browser url.
That's history API in action. Find more details here
Try the pushState and replaceState methods, that should get you this behavior. To have more precise control over these, you might also want to take a look at popState event
Twitter has the following UI behaviour that I want to replicate:
a homepage https://twitter.com with an endless feed you can scroll down;
if you click on a tweet it opens up with a dedicated URL (e.g. https://twitter.com/TheTweetOfGod/status/635493904834412545);
this tweet appears to be an embedded page/section 'on top' of the original feed, which you can still see around the edges but shaded darker;
If you click off the embedded tweet element (i.e. on the shaded area) you revert to the original https://twitter.com feed at the same point (i.e. page has not refreshed).
Note that if the tweet URL is opened up in a fresh tab then the author's profile page forms the shaded backdrop instead of the main feed page. So the main feed backdrop is only inherited if the tweet page has been accessed from https://twitter.com.
In web design terms does this design approach have a formal name/definition that might help me identify a suitable solution? I'm assuming it has a server-side dimension.
There are three aspects to your question. Let's first dive into the technology needed to implement everything, and then briefly discuss how Twitter leverages that technology.
TL;DR? Twitter uses the history API combined with AJAX and DOM manipulation to work its magic.
The techniques, and a little bit of background
(a) Changing the URL without refreshing the page (2 and 4 on your list)
There is an API for that, implemented by modern browsers.
window.history.pushState(state, title, URL);
window.history.replaceState(state, title, URL);
window.addEventListener('popstate', (event) => { /* use event.state */ });
The first two functions allow you to simulate the user navigating to URL. The first adds an entry to the navigation history, while the second replaces the current entry. This impacts what will happen when users use the back and forward buttons in their browser.
When users navigate back, or you simulate this using history.back(), the popstate event is fired and the state that you passed into pushState can be accessed via event.sate. The state can be any object, so this is useful to store, say, the title of the page (to update the document.title), the scroll position, or whatever else you want.
(b) Loading content directly
Because the entry is saved in the browsing history, it is possible that users visit this URL directly after having closed the tab or even their browser. They may also share the URL and have others visit it directly. In those cases, there will be no popstate event, but simply a request to your web server for the URL you passed to pushState. The URL must hence be meaningful to the server.
Twitter apparently loads the poster profile as a backdrop in this case. It depends on your use case what you want the page to look like. Anything goes!
(c) Loading content asynchronously (3 on your list)
Back to (a) for a bit. Twitter not only changes the URL, but also loads the tweet, meta data of that tweet and replies to it. This is then displayed in a modal popup.
Again, there is an API1 to load content asynchronously: AJAX. In particular, the XMLHttpRequest object and its functions are of interest. This can be used to make requests to the server and fetch content without needing the page to reload completely.
It is worth mentioning that a new API is being developed: the Fetch API. At the time of writing, there is basic support in all modern major browsers, but it is still somewhat under development.
After having fetched the content, it can be displayed on the page in any which way you like. JavaScript can be used to create, delete and modify elements in the DOM at will.
An example from your question: Twitter
Now that all techniques are on the table, let's summarize what Twitter does.
When a user clicks a tweet in their feed.
Load tweet meta data and replies (as described under (c)).
Create a backdrop and modal and populate them with the loaded content.
This uses standard techniques: create, delete and modify page elements.
Update the URL (as described under (a)) to enable easy sharing, amongst others.
When a user dismisses the modal.
Delete the modal and backdrop.
Update the URL (as described under (a)).
When a user directly visits the URL to a specific tweet.
Let the server respond with the profile page of the tweet author, with the tweet details loaded in a modal on top of it. Thus, no JavaScript is required at all. Of course, the modal can be dismissed just like in the previously described use case.
Implementing this on your own web site
You correctly identified that there are both client side and server side dimensions to this technique. The beauty of it is that, when implemented correctly, it is completely transparent to users. The only thing they will (not) notice is that there are fewer full page loads.
The references sprinkled throughout this answer should provide good starting points for you!
Final notes
All of this is sometimes also used to create smooth transitions between pages of the same site. In those cases, full pages are loaded asynchronously (as per (c)) and then a smooth transition, usually involving animations, is performed. There are many, many, many, many examples, tutorials and libraries for this. You may want to search for PJAX to learn and find more.
__________
1Not really a single API maybe, but an approach or mindset. See the MDN reference for more details.
I think that what is happening in Twitter is that the popup tweet loads the same content as the tweet in its own unique page; not that the modal has an unique URL.
If you use Angular, you can inject the same content into html modal templates or into standalone pages using route provider, and you could link from the modal content to the standalone page using the ID of the specific data to load that content.
EDITED TO ADD:
Here is the source code of a tweet in a stream of tweets, before it pops up as a modal:
<div class="js-tweet-text-container">
<p class="TweetTextSize TweetTextSize--normal js-tweet-text tweet-text" lang="en" data-aria-label-part="0">
Does anyone remember a 1990s TV show about a folklore prof investigating urban legends, shown on weird night on channel 4 <s>#</s><b>folklorethursday</b></p>
</div>
Here is the URL of the tweet when it is shown as a modal in front of the twitter feed: https://twitter.com/vogelbeere/status/887996116549107713
There are so many event listeners on the tag that it's hard to see which one is the link to the tweet.
I have a Website with heavy jQuery action. In order to create a less chaotic page load I hide() the content container on initial page load and show() it when the page has loaded: $(window).load(function() { //show content...
This is the sequence right now, which works well in a browser for human eyes:
hide content on initial page load.
wait until page has fully loaded.
show content.
do jquery action.
But I wonder how this works for crawlers. Does the crawler wait for "page->loaded" and "scripts->finished"? If not, the crawl result may become messy..
First, hidden content is down-weighted in ranking, so your content might not perform as well as you'd like. You want to make absolutely sure that what search engines see is the finished, not-hidden-any-more content.
You can look at what we (Google) "see" using Fetch and Render as Google in Search Console (former Webmaster Tools); read more about the feature in our post titled Rendering pages with Fetch as Google. If the rendered image looks right, you're good to go.
I'm currently working on the web-site using Polymer, Jekyll and Github pages. But I'm facing one big issue. When switching between pages there is a white screen showing every time, which is not correct behavior. I would like to always see the header section and left menu (without flash) even when switching between the pages.
The web-site is not vulcanized yet (there were another issues with that), so it is not very fast, but this should not be a reason. I was playing with the imports in <head> section and scripts, but nothing helps. Seems that the page actually renders only after DomContentLoaded event.
Any suggestions?
The web-site can be checked on this url and the source code is also available on GitHub.
If you refer to the transition when navigating between pages — the Polymer website feels faster because they don't do full page loads. Instead, they use AJAX to load the new pages and modify your URL bar with the help of the History API to make it look like you went from page A to page B. The term for this kind of thing is Single-page application.
The Facebook chat window remains open, unchanged, to refresh the page, or even when we change page. How to reproduce something similar? Tried with frameset, but it did not work.
How to keep a div open a window similar to the internal, even after refreshing the page or clocar on a website link?
Like them, you can try -
The data is shared between facebook pages. Probably HTML5 localStorage? Cookies? I'm not sure.
If you notice, they don't "refresh" the page, they ajax-refresh the content on the page for subsequent loads. (unless you manually navigate to the same page, of course.)
Finally, its all CSS mainly some z-index put to use.
I hope those 3 are enough to get you started.
I don't think the whole page of Facebook is loaded. Every link has it's own 'target'. Most of them fetch a page (I think with simply AJAX) to show, others to just change some partials of the screen. So let's say, you have two divs. One div is the chat-div. Positioning fixed and all, z-index on 100, it will always stay on top. The rest of the page is the other div. Within this div, you can load certain pages with AJAX, without the whole screen to refresh.
As with reloads of the screen: you can easily save (also with AJAX) whether the user closed the chat screen or has it opened. Just create a table in a database called 'chats' or something, then when a chatscreen is opened you put an entry in that table with 'person_1', 'person_2' 'lastmessage' and 'active'. When they close the chat, you can put the 'active'-field to false. Then, whenever someone loads the entire website, you check the table chats for active chats, and shows them when there are any.
I would look into qjuery-qjax: https://github.com/defunkt/jquery-pjax
From their docs:
pjax works by grabbing html from your server via ajax and replacing the content of a container on your page with the ajax'd html. It then updates the browser's current url using pushState without reloading your page's layout or any resources (js, css), giving the appearance of a fast, full page load. But really it's just ajax and pushState.