We all hate waiting for websites to load before we can start using or surfing it. The internet has a come a long way in terms of decreasing load time, but this has just made the user more impatient. In fact, it has been found that on average a user would not wait for more than 4 seconds for a web page to load. With such short time requirements, even a decrease of milliseconds in the loading time can affect a website greatly. While on the client-side, improving Internet connection is obviously a way to load websites faster, web developers can develop websites with numerous techniques that will help their site to load faster. We are here to talk about one such technique, Pjax.
Pjax is made up of two terms, pushState and Ajax. Before diving into pjax, let's have a brief look at what Ajax and pushState are.
XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files. Ajax's most appealing characteristic is its "asynchronous" nature, which means it can communicate with the server, exchange data, and update the page without having to refresh the page.
Here's an example. Let's say a person navigates from the homepage of a site to the Help page. We're loading the content of that Help page with Ajax. That user then heads off to the Products page which we again load and swap out content with Ajax. Then they want to share the URL. With the History API, we could have been changing the URL of the page right along with the user as they navigate, so the URL they see (and thus share or save) is relevant and correct.
The pushState method of the History API changes the current URL of the browser to a specified URL and also manipulates the browser history so that the browser back button does not create a problem.
For example, let's suppose we are at https://www.foobar.com. Now, we click a button that redirects us to https://www.foobar.com/foo.html. After this, we again click a button that fires the pushState method that changes the URL to https://www.foobar.com/bar.html but does not change the page, and thus nothing except the URL of the browser changes. Now, if we click on the back button, it will take us to https://www.foobar.com/foo.html. That means, pushState does not only change the URL of the page but, behind the scenes, it also manipulates the history so as to add an element to the stack with the changed URL. Thus, the back button will take us to the previous URL instead of the previous web page.
Pjax is just the combination of these two concepts. Pjax works by fetching HTML from your server via Ajax and replacing the content of a container element on your page with the loaded HTML. It then updates the current URL in the browser using pushState. This results in faster page navigation for two reasons:
- No page resources (JS, CSS) get re-executed or re-applied.
- If the server is configured for Pjax, it can render only partial page contents and thus avoid the potentially costly full layout render.
A Basic Example
To install pjax through npm -
$ npm install pjax
To install it through bower -
$ bower install pjax
You will have to include the pjax.js file in your HTML files to access the pjax functionality.
I installed it through npm and will be using npm to start the server as well. It doesn't matter what you use to start the server or what MVC framework you use, it will work for every one of them just fine.
After running the above commands, we can dive straight away into the code. To demonstrate the working of pjax, we will be making two links, one that will be using pjax to change the content of a div and change the URL, and another one that will not be using pjax and thus will be loading the whole page. Both links will re-direct to the same page so that we can clearly see the difference.
Ok, so my code for the main page looks something like this (main.html):
And the code for the common page looks something like this (common.html):
In this code, we have initialized the pjax class and passed on some values.
elements are comma-separated values of those elements on which pjax would take effect. Here,
a.js-Pjax are the anchor elements with the class
selectors are the containers that will get their content replaced by pjax. Note that both the HTML pages using pjax have to have the same layout and the same number of DOM elements at the same position. If there's any change in any of these things, pjax will go into fall-back mode (it will just do nothing) and will load the page as it normally would. So, in selectors, we put ids or classes of those elements whose content we want to be replaced by the other page's DOM element, that will be called on the click of an element defined in elements.
We are all done with our pjax enabled site! Now we will start our server. npm users can start it by using the command
npm run <script-name> .
Now when you open up the site, you can see the home page that we built in main.html. Now when you click on 'First Link,' you can see that the URL and the content of the div under the links have changed. It looks like you navigated through the site but nothing essentially changed except the things we defined while building pjax. Now if you go back and click on 'Second Link,' you can see an alert box with the text 'An alert box' appearing on your window. While we have used the same JS on both the pages, 'First Link' didn't show the alert box while the 'Second Link' did. This is because pjax only changes the URL and the content of the containers defined while building it, it does not even re-execute JS or reapply any CSS. This saves a lot of time when loading heavy sites.
Below video shows the behavior of the site we just built -
GitHub repository for the above code - https://github.com/akshanshjain95/pjax-tutorial
GitHub repository for pjax - https://github.com/MoOx/pjax
Thanks for reading. I hope it helped you!
This article was originally published on the Knoldus blog.