Skip to content

Modernize pace.js - #565

Merged
CodeByZach merged 5 commits into
candidate-2.0from
modernize
Nov 7, 2026
Merged

CodeByZach merged 5 commits into
candidate-2.0from
modernize

Conversation

@CodeByZach

Copy link
Copy Markdown
Owner

Moves pace.js from CoffeeScript-compiled ES5 to modern JavaScript (ES2021) for the 2.0 browser targets, without changing what it does. Bugs are kept as they are and get fixed in later PRs, each with its own tests.

Commits (each one builds and passes the tests on its own):

  1. Build for the 2.0 browser targets: .browserslistrc (baseline 2021 with downstream: Chrome/Edge 96, Firefox 95, Safari 15.2), the esbuild target, and a syntax check that allows ES2021 and runs es-check against .browserslistrc.
  2. Replace CoffeeScript helpers with rest parameters, includes and bind.
  3. Remove code for browsers 2.0 doesn't support: Internet Explorer's XDomainRequest, prefixed requestAnimationFrame, and fallbacks for features every supported browser has.
  4. Rewrite pace.js in modern JavaScript: classes, const/let, arrow functions. The commit message lists the small differences (return values of public methods, which were CoffeeScript leftovers, and for...in over class methods) and what was kept on purpose.
  5. README: browser support and size.

pace.min.js goes from 4.7 kB to 3.6 kB gzipped.

How to verify: npm test runs the syntax checks and the browser tests against pace.js and pace.min.js. To compare behavior with the previous version, run any page or test against git show candidate-2.0:pace.js and this branch's pace.js side by side.

The supported browsers are declared in .browserslistrc as "baseline 2021
with downstream" (Chrome and Edge 96, Firefox 95, Safari 15.2). The build
minifies for those versions instead of ES5.

The syntax check now allows ES2021 (acorn) and also runs es-check, which
reads .browserslistrc and fails on built-ins those browsers lack, such as
Array.prototype.at. pace.js itself is unchanged.
pace.js was compiled from CoffeeScript, which added small helper functions
for things JavaScript now has built in: rest parameters instead of slicing
`arguments`, Array.prototype.includes instead of an indexOf polyfill, and
Function.prototype.bind. __extends stays until the classes are rewritten.

No behavior changes, apart from the wording of the error thrown when
ajax.trackMethods is missing (as with `Pace.start({ ajax: true })`).
Every supported browser has these, so the fallbacks never run:
- performance.now() (no Date fallback)
- unprefixed requestAnimationFrame and cancelAnimationFrame (no prefixed
  versions or setTimeout fallback)
- addEventListener on XHR and WebSocket objects (no on<event> fallback)
- XHR progress events (no onreadystatechange fallback)
- the unprefixed transform property (no webkitTransform or msTransform)
- Object.defineProperty, WebSocket, history.pushState/replaceState, console

XDomainRequest only existed in Internet Explorer, so pace no longer wraps it.

requestAnimationFrame and cancelAnimationFrame are still saved when pace
loads, so a later replacement of window.requestAnimationFrame (zone.js
patches it, for example) doesn't change what pace calls. No behavior
changes.
Replaces the CoffeeScript output with ES2021: classes instead of prototype
functions and __extends, const/let, arrow functions instead of `_this`, and
destructuring, optional chaining and ??= instead of temporary variables.
The logic is unchanged, including its known bugs, which get fixed
separately with tests.

Kept as before on purpose:
- Loops over options and sources read the length once and index into the
  list, so non-array values (`extraSources: false`, an HTMLCollection as a
  source's elements) are handled exactly as before.
- The XHR and WebSocket wrappers are installed outside a class body, so a
  read-only window.XMLHttpRequest is still skipped silently instead of
  throwing in strict mode.
- requestAnimationFrame is still read once, when pace loads.

Small differences:
- Pace.on/once/off/trigger/start/stop/restart/go, and the methods of
  Pace.bar and Pace.sources, no longer return CoffeeScript's leftover
  values (array lengths, timer ids, class names). Pace.track and
  Pace.ignore still return the callback's result.
- Methods of Pace.bar and Pace.sources are class methods, so `for...in`
  no longer lists them.
- The error thrown when the target element is missing is a NoTargetError
  instead of a plain Error.
Lists the browsers from .browserslistrc and points users of older browsers
to pace-js 1.x. The sizes are measured: pace.min.js is 3.6 kB gzipped, and
the blue themes are 0.2 to 3.2 kB.
@CodeByZach
CodeByZach merged commit ac1c6a9 into candidate-2.0 Nov 7, 2026
2 checks passed
@CodeByZach
CodeByZach deleted the modernize branch November 7, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant