https://github.com/mitranim/simple-pjax
Zero-configuration PJAX for typical websites
https://github.com/mitranim/simple-pjax
Last synced: 8 months ago
JSON representation
Zero-configuration PJAX for typical websites
- Host: GitHub
- URL: https://github.com/mitranim/simple-pjax
- Owner: mitranim
- Created: 2015-07-17T22:14:38.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2019-09-07T19:20:37.000Z (over 6 years ago)
- Last Synced: 2025-04-26T06:56:57.514Z (9 months ago)
- Language: JavaScript
- Homepage: http://mitranim.com/simple-pjax/
- Size: 1.28 MB
- Stars: 49
- Watchers: 4
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
[](http://standardjs.com)
## TOC
* [Description](#description)
* [Installation](#installation)
* [Usage](#usage)
* [Configuration](#configuration)
* [Methods](#methods)
* [Gotchas](#gotchas)
## Description
Lean library that improves page loading times for classic multi-page websites.
Gives them some of the advantages enjoyed by SPA (single-page apps).
Configuration is optional.
See a simple demo at https://mitranim.com/simple-pjax/.
Read an explanatory post at https://mitranim.com/posts/cheating-for-performance-pjax.
`Pjax` is a combo of `pushState` and `Ajax`. There are
[other](https://github.com/defunkt/jquery-pjax) pjax implementations floating
around, but most of them are jQuery-based or overengineered. Hence `simple-pjax`.
To explain what pjax is about, first let's get a rough idea of how page
transitions work on most sites:
* Load and parse the new HTML document. Create a new JavaScript runtime.
* Redownload all stylesheets, scripts, fonts, images, etc. (Connections take time even if the resources are cached.)
* Parse and execute the downloaded scripts.
* Parse styles and apply them to the document.
* Throw away the current document and JavaScript runtime, switch to the new document and runtime.
* Download and execute asynchronous scripts, if any.
Here's how page transitions work with simple-pjax:
* Load and parse the new HTML document.
* Replace the contents of the current document.
* Let it execute the new scripts, if any.
Benefits:
* Don't redownload stylesheets, scripts, fonts, images.
* Don't execute scripts that have already been executed.
* Keep the JavaScript runtime and WebSocket connections intact.
The benefits are especially dramatic on mobile devies and slow connections.
Works on IE10+. Has no effect in browsers that don't support
`history.pushState`.
## Installation
Grab through your favourite package manager:
```sh
npm i --save-dev simple-pjax
jspm install npm:simple-pjax
```
Import in your code:
```javascript
import pjax from 'simple-pjax'
```
Or include as a script tag:
```html
```
## Usage
Works automatically. When navigating between internal pages, the library
prevents a full page reload. Instead, it fetches the new document by ajax and
replaces the contents of the current document.
After replacing the document, it executes any _inline_ scripts found in it.
Ignores scripts with an `src` under the assumption that all pages have the same
set of scripts, and they have already been downloaded.
Affects both `` clicks and `popstate` history events, such as when the back
button is clicked.
Visibly indicates loading when it takes a while (by default after 250 ms). You
can customise the timeout and the functions called to add and remove the
indicator.
## Configuration
`simple-pjax` works with zero configuration, but it also exports an object with
configurable properties and useful methods. In the presense of a
CommonJS-compliant module system, it does a proper export; otherwise the object
is assigned to `window.simplePjax`.
Example config (see defaults in [source](src/simple-pjax.ts)).
```javascript
import pjax from 'simple-pjax'
// Timeout before calling the loading indicator function. Set to 0 to disable.
pjax.indicateLoadAfter = 100
// Called when loading takes a while. Use it to display a custom loading indicator.
pjax.onIndicateLoadStart = function() {
document.documentElement.style.opacity = 0.5
}
// Called when loading ends. Use it to hide a custom loading indicator.
pjax.onIndicateLoadEnd = function() {
document.documentElement.style.opacity = null
}
// If a selector string is provided, it's checked every time when scrolling
// to an element (e.g. via data-scroll-to-id). If an element with the
// {position: 'fixed', top: '0px'} computed style properties is found, the
// scroll position will be offset by that element's height.
pjax.scrollOffsetSelector = '.navbar-fixed'
// If a string is provided, it will be used as the default value (default
// element `id`) for the `[data-scroll-to-id]` attribute.
pjax.defaultMainId = 'mainView'
```
You can prevent page scroll by adding the `data-noscroll` attribute to a
link:
```html
clicking me doesn't scroll the page!
```
If you want an individual link without pjax behaviour, add the `data-no-pjax`
attribute:
```html
I have native behaviour!
```
By default, links to the same page are ignored. If you want to force a page
refresh, add the `data-force-reload` attribute. This reload doesn't affect
scroll position:
```html
I sneakily refresh the page when clicked!
```
## Methods
simple-pjax exports one simple method that sneakily refreshes the current page,
as if you clicked a `` leading to this page. The refresh is done through pjax
and doesn't destroy the JS runtime and other assets. It also doesn't affect
scroll position.
```js
import pjax from 'simple-pjax'
pjax.reload()
```
## Gotchas
You need to watch out for code that modifies the DOM on page load. Most websites
have this in the form of analytics and UI widgets. When transitioning to a new
page, that code must be re-executed to modify the new document body.
`simple-pjax` mitigates this in two ways.
First, it automatically executes any inline scripts found in the new document.
If you embed analytics and DOM bootstrap scripts inline, they should work
out-of-the-box.
Second, it emits two `document`-level DOM events, before and after the
transition. Use them to perform any necessary DOM mutations or cleanup. Example:
```javascript
document.addEventListener('simple-pjax-after-transition', () => {
// perform DOM mutations
})
document.addEventListener('simple-pjax-before-transition', () => {
// perform cleanup
})
```
## ToDo
Investigate if it's possible to get the final URL of an XHR after a server
redirect without using `responseURL`, which is still not supported in Safari 8.0
and IE 11.