Skip to content

Commit cdd7c08

Browse files
authored
Merge pull request #2 from BRIXTOL/next
Next
2 parents 1056f4f + 257b546 commit cdd7c08

6 files changed

Lines changed: 267 additions & 14 deletions

File tree

changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
11
# CHANGELOG
2+
3+
#### 30/03/2021 | v0.1.1-beta.1
4+
5+
- Fixes Prefetch hover toggle between navigation
6+
- Update Readme typos + other stuff.
7+
8+
#### 29/03/2021 | v0.1.0-beta.1
9+
10+
Initial Release

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@brixtol/pjax",
3-
"version": "0.1.0-beta.1",
3+
"version": "0.1.1-beta.1",
44
"private": false,
55
"description": "A modern next generation pjax solution for SSR web applications",
66
"author": "ΝΙΚΟΛΑΣ ΣΑΒΒΙΔΗΣ",

readme.md

Lines changed: 247 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
> _This is still in beta stages, use it with care and expect some changes to be shipped before official release. Tests are still being worked on and will be pushed at v1, sit tight._
1+
> _This is still in beta stages, use it with care and expect some changes to be shipped before official release. Tests are still being worked on and will be pushed at official v1, sit tight._
22
33
## @brixtol/pjax
44

5-
A blazing fast, lightweight (8kb gzipped), feature full drop-in next generation pjax solution for SSR web applications. Supports multiple fragment replacements, appends and prepends. Pre-fetching capabilities via mouse, pointer, touch and intersection events and snapshot caching which prevent subsequent requests for occurring that results in instantaneous navigation.
5+
A blazing fast, lightweight (8kb gzipped), feature full drop-in new generation pjax solution for SSR web applications. This Pjax variation supports multiple fragment replacements, it ships with advanced pre-fetching capabilities executing via mouse/pointer/touch or intersection events and provides a snapshot caching feature which prevents subsequent requests for occurring resulting in instantaneous page navigation.
66

7-
##### Example
7+
##### Demo
88

99
We are using this module live on our [webshop](https://brixtoltextiles.com).
1010

11+
### Why?
12+
13+
The landscape of pjax based solution has become rather scarce. The current bread winners either offer the same thing or for our use cases were vastly over engineered. We wanted to couple together various techniques we found to be the most effective in enhancing the performance of SSR rendered web application.
14+
1115
## Install
1216

1317
```cli
@@ -18,14 +22,16 @@ pnpm i @brixtol/pjax
1822
1923
## Usage
2024

21-
To initialize, call `Pjax.connect()` in your bundle and optionally pass preset configuration. By default Pjax will replace the entire `<body>` fragment upon each navigation. You should define a set of `targets[]` whose inner contents change on a per-page basis.
25+
To initialize, call `Pjax.connect()` in your bundle and optionally pass preset configuration. By default, Pjax will replace the entire `<body>` fragment upon each navigation, so you should define a set of `targets[]` whose inner contents change on a per-page basis.
26+
27+
> The typings provided in this package will describe each option in good detail
2228
2329
<!-- prettier-ignore -->
2430
```js
2531
import * as Pjax from "@brixtol/pjax";
2632

2733
Pjax.connect({
28-
targets: ["body"],
34+
targets: ["body"], // Define fragments to be replaced here!
2935
cache: {
3036
enable: true,
3137
limit: 25,
@@ -38,7 +44,6 @@ Pjax.connect({
3844
mouseover: {
3945
enable: true,
4046
threshold: 100,
41-
proximity: 0,
4247
},
4348
intersect: {
4449
enable: true,
@@ -64,6 +69,238 @@ Pjax.connect({
6469

6570
```
6671

72+
#### Real World
73+
74+
Below is a real world example you can use to better understand how this module works so you can apply it into your web application. We are working on providing a live demonstration for more advanced use cases, but the below example should give you a good understanding and help you in understanding how to leverage the module.
75+
76+
<details>
77+
<summary>
78+
Example
79+
</summary>
80+
81+
The first thing we want to do is make a connection with Pjax. In your JavaScript bundle, we need to initialize. Our example web application has 3 pages, the home page, about page and contact page. We are going to instruct pjax to replace the `<nav>` and `<main>` fragments on every visit and then we are going to leverage `data-pjax` attributes to replace an additional fragment when we navigate to the contact page.
82+
83+
<br>
84+
**JavaScript Bundle**
85+
<br>
86+
87+
<!-- prettier-ignore -->
88+
```javascript
89+
import * as Pjax from "@brixtol/pjax";
90+
91+
export default () => {
92+
93+
Pjax.connect({
94+
targets: [
95+
"nav",
96+
"main"
97+
],
98+
})
99+
100+
}
101+
102+
```
103+
104+
**Home Page**
105+
<br>
106+
Below we have a very basic Home Page with pjax wired up and all `<a>` elements will be intercepted and cached. SSR web application (in most cases) will only ever have a couple of fragments that change between navigation, so keeping to that logic lets begin..
107+
108+
<!-- prettier-ignore -->
109+
```html
110+
111+
<!doctype html>
112+
<html>
113+
<head>
114+
<meta charset="UTF-8">
115+
<title>Home Page</title>
116+
<script src="/bundle.js"></script>
117+
</head>
118+
<body>
119+
120+
<header>
121+
122+
<h1>@brixtol/pjax</h1>
123+
124+
<!-- THIS FRAGMENT WILL BE REPLACED -->
125+
<nav>
126+
127+
<!-- This link will be intercepted -->
128+
<a
129+
href="/home"
130+
class="active">Home</a>
131+
132+
<!-- These links will be pe-fetched on hover -->
133+
<a
134+
href="/about"
135+
data-pjax-prefetch="hover">About</a>
136+
137+
<!-- This link will replace the #foo fragment -->
138+
<a
139+
href="/contact"
140+
data-pjax-replace="(['#foo'])"
141+
data-pjax-prefetch="hover">Faq</a>
142+
</nav>
143+
144+
</header>
145+
146+
<!-- THIS FRAGMENT WILL BE REPLACED -->
147+
<main>
148+
149+
<h1>Welcome to the home page</h1>
150+
151+
<div class="container">
152+
Brixtol Textiles is a Swedish apparel brand!
153+
</div>
154+
155+
</main>
156+
157+
<div id="foo">
158+
This fragment will not be touched until /contact is clicked
159+
</div>
160+
161+
<footer>
162+
This will not be touched during navigation
163+
</footer>
164+
165+
</body>
166+
</html>
167+
168+
```
169+
170+
**About Page**
171+
<br>
172+
The about page in our web application would look practically identical to the home page. We instructed pjax to pre-fetch this page upon hover, so navigating to this page will be instantaneous. The about page only has some minor differences, but for the sake of clarity, lets have look:
173+
174+
<!-- prettier-ignore -->
175+
```html
176+
177+
<!doctype html>
178+
<html>
179+
<head>
180+
<meta charset="UTF-8">
181+
<title>About Page</title>
182+
<script src="/bundle.js"></script>
183+
</head>
184+
<body>
185+
186+
<header>
187+
188+
<h1>@brixtol/pjax</h1>
189+
190+
<!-- THIS FRAGMENT WILL BE REPLACED -->
191+
<nav>
192+
193+
<!-- This link will be intercepted -->
194+
<a
195+
href="/home">Home</a>
196+
197+
<!-- These links will be pe-fetched on hover -->
198+
<a
199+
href="/about"
200+
class="active"
201+
data-pjax-prefetch="hover">About</a>
202+
203+
<!-- This link will replace the #foo fragment -->
204+
<a
205+
href="/contact"
206+
data-pjax-replace="(['#foo'])"
207+
data-pjax-prefetch="hover">Contact</a>
208+
</nav>
209+
210+
</header>
211+
212+
<!-- THIS FRAGMENT WILL BE REPLACED -->
213+
<main>
214+
215+
<h1>Welcome to the About Page</h1>
216+
217+
<div class="container">
218+
Brixtol Textiles makes jackets out of recycled PET bottles.
219+
<p>Producing clothing in a sustainable way is the future!</p>
220+
</div>
221+
222+
</main>
223+
224+
<div id="foo">
225+
This fragment will not be touched until /contact is clicked
226+
</div>
227+
228+
<footer>
229+
This will not be touched during navigation
230+
</footer>
231+
232+
</body>
233+
</html>
234+
```
235+
236+
**Contact Page**
237+
<br>
238+
The contact page will replace an additional fragment with the id value of `foo` which we instructed via attribute annotation. When the contact page link is hovered the page will be saved to cache, upon visit the `<nav>`, `<main>` and `<div id="foo">` fragments will be replaced.
239+
240+
<!-- prettier-ignore -->
241+
```html
242+
243+
<!doctype html>
244+
<html>
245+
<head>
246+
<meta charset="UTF-8">
247+
<title>Contact Page</title>
248+
<script src="/bundle.js"></script>
249+
</head>
250+
<body>
251+
252+
<header>
253+
254+
<h1>@brixtol/pjax</h1>
255+
256+
<!-- THIS FRAGMENT WILL BE REPLACED -->
257+
<nav>
258+
259+
<!-- This link will be intercepted -->
260+
<a
261+
href="/home">Home</a>
262+
263+
<!-- These links will be pe-fetched on hover -->
264+
<a
265+
href="/about"
266+
data-pjax-prefetch="hover">About</a>
267+
268+
<!-- This link will replace the #foo fragment -->
269+
<a
270+
href="/contact"
271+
class="active"
272+
data-pjax-replace="(['#foo'])"
273+
data-pjax-prefetch="hover">Contact</a>
274+
</nav>
275+
276+
</header>
277+
278+
<!-- THIS FRAGMENT WILL BE REPLACED -->
279+
<main>
280+
281+
<h1>Welcome to the Contact Page</h1>
282+
283+
<div class="container">
284+
This is contact page of our example! The below fragment was replaced too!
285+
</div>
286+
287+
</main>
288+
289+
<!-- THIS FRAGMENT WAS REPLACE VIA ATTRIBUTE INSTRUCTION -->
290+
<div id="foo">
291+
This fragment was replaced!
292+
</div>
293+
294+
<footer>
295+
This will not be touched during navigation
296+
</footer>
297+
298+
</body>
299+
</html>
300+
```
301+
302+
</details>
303+
67304
## Lifecycle Events
68305

69306
Lifecycle events are dispatched to the document upon each navigation. You can access context information from within `event.detail` or cancel events with `preventDefault()` and prevent execution.
@@ -92,7 +329,7 @@ document.addEventListener("pjax:load");
92329

93330
## Methods
94331

95-
In addition to Lifecycle events, a list of methods are available. Methods will allow you some basic programmatic control of the Pjax session.
332+
In addition to Lifecycle events, a list of methods are available. Methods will allow you some basic programmatic control of a Pjax session.
96333

97334
```javascript
98335

@@ -415,7 +652,7 @@ Example
415652
416653
## State
417654
418-
Each page has an object state value. Page state is immutable and created for every unique url `/path` or `/pathname?query=param` value encountered throughout a pjax navigation session. The state value of each page is added to its pertaining History stack record.
655+
Each page has an object state value. Page state is immutable and created for every unique url `/path` or `/pathname?query=param` value encountered throughout a pjax session. The state value of each page is added to its pertaining History stack record.
419656
420657
> Navigation sessions begin once a Pjax connection has been established and ends when a browser refresh is executed or url origin changes.
421658
@@ -582,9 +819,9 @@ interface IPage {
582819
583820
## Contributing
584821
585-
This module is written in ES2020 format JavaScript. Production bundles export in ES6 format. Legacy support is provided as an ES5 UMD bundle. This project leverages JSDocs and Type Definition files for its type checking, so all features you enjoy with TypeScript are available.
822+
This module is written in ES2020 JavaScript. Production bundles export in ES6 format. Legacy support is provided as an ES5 UMD bundle. This project leverages JSDocs and Type Definition files for its type checking, so all features you enjoy with TypeScript are available.
586823
587-
This module is consumed by us for a couple of our projects, we will update it according to what we need. Feel free to suggest features or report bugs, PR's are welcome too!
824+
This module is consumed by us for a couple of our projects and has been open sourced but exists as part of a mono/multi repo. We will update it according to what we need. Feel free to suggest features or report bugs, PR's are of course welcome!
588825
589826
## Acknowledgements
590827

src/app/render.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ export default (function () {
150150

151151
// window.performance.mark('render')
152152
// console.log(window.performance.measure('time', 'start'))
153+
prefetch.stop()
153154

154155
const target = parse(store.snapshot(state.snapshot))
155156

src/observers/hover.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { supportsPointerEvents } from 'detect-it'
2-
import { eventFrom } from 'event-from'
32
import { LinkPrefetchHover } from '../constants/common'
43
import { getLink, getTargets, dispatchEvent } from '../app/utils'
54
import hrefs from './hrefs'
@@ -127,12 +126,17 @@ export default (function (connected) {
127126
}
128127

129128
/**
129+
* NOT YET IMPLEMENTED
130+
*
130131
* Attempts to visit location, Handles bubbled mousovers and
131132
* Dispatches to the fetcher. Once item is cached, the mouseover
132133
* event is removed.
133134
*
134135
* @param {MouseEvent} event
135136
*/
137+
138+
// @ts-ignore
139+
// eslint-disable-next-line
136140
const onMouseMove = event => {
137141

138142
position.x = event.pageX
@@ -141,10 +145,14 @@ export default (function (connected) {
141145
}
142146

143147
/**
148+
* NOT YET IMPLEMENTED
144149
*
145150
* @param {Element} target
146151
* @param {number} index
147152
*/
153+
154+
// @ts-ignore
155+
// eslint-disable-next-line
148156
const proximity = (target, index) => {
149157

150158
const { top, left } = target.getBoundingClientRect()

src/observers/hrefs.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { supportsPointerEvents } from 'detect-it'
22
import { dispatchEvent, getLink, chunk } from '../app/utils'
33
import { Link } from '../constants/common'
4-
import * as prefetch from './../app/prefetch'
54
import * as regexp from '../constants/regexp'
65
import store from '../app/store'
76
import path from '../app/path'
@@ -159,7 +158,6 @@ export default (function (connected) {
159158
event.preventDefault()
160159
target.removeEventListener('click', click, false)
161160
render.capture(history.updateState) // PRESERVE CURRENT PAGE
162-
prefetch.stop()
163161

164162
return typeof state === 'object'
165163
? render.update(state)

0 commit comments

Comments
 (0)