npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simple-pjax

v0.3.0

Published

Zero-configuration PJAX for typical websites

Downloads

32

Readme

js-standard-style

TOC

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 http://mitranim.com/simple-pjax/.

Read an explanatory post at http://mitranim.com/thoughts/cheating-for-performance-pjax/.

Pjax is a combo of pushState and Ajax. There are other 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:

npm i --save-dev simple-pjax
jspm install npm:simple-pjax

Import in your code:

import pjax from 'simple-pjax'

Or include as a script tag:

<script src="simple-pjax.js" async></script>

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 <a> 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).

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:

<a href="/other-page" data-noscroll>clicking me doesn't scroll the page!</a>

If you want an individual link without pjax behaviour, add the data-no-pjax attribute:

<a href="/other-page" data-no-pjax>I have native behaviour!</a>

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:

<a href="/current-page" data-force-reload>I sneakily refresh the page when clicked!</a>

Methods

simple-pjax exports one simple method that sneakily refreshes the current page, as if you clicked a <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.

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:

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.