What is piconav
?
piconav
is a tiny library that keeps the browser URL in sync with your JS state for Single Page Applications.
It also syncs the document
title, canonical URL and meta description.
It aims to allow Google indexing of SPA's to prevent the need for server side rendering / hydrating.
Why did you make piconav
?
Why should I use piconav
?
- Easy to use.
- Use
piconav
if you want to get something up and running quickly.
- Easy to replace.
- Minimal API.
piconav
is very simple.- You can copy or customize the functionality quickly.
How to add piconav
to your JS project.
Install: yarn add piconav
or npm install piconav
.
1. Create a nav.js
to add configuration and event handlers to piconav
.
import {on, off} from "./../lib/piconav";
import {storeIns} from "./../stores/store";
const resetPrimaryScroll = () => {
document.querySelector("html").scrollTo(0, 0);
};
const {nav, navByBrowser, updateDoc} = on({
site: {
canonicalDomain: `https://example.com`
},
events: {
js: {
after: ({data}) => {
if (data !== null && "type" in data && data.type !== "home") {
resetPrimaryScroll();
}
}
},
browser: {
after: (url, params) => {
return storeIns.onBrowserNav(url, params);
}
}
}
});
export {
nav,
navByBrowser,
updateDoc
}
2. Import nav.js
to your store, map JS state to document
state.
When the user navigates via browser:
events.browser.after(url, params)
is called.
- Your code is expected to call
updateDoc(navEvent)
soon after.
When the user navigates via JS click:
Example using a MobX store:
@observable curUrl = null;
nav(appSpecificData, src = "js") {
this.curUrl = {
url: "/a/b/c",
title: "A Title",
metaDesc: "A page description",
data: appSpecificData,
src
};
}
Note: src
is either js
or browser
.
E.g If curUrl
is set via the events.browser.after
function, src
will be "browser"
.
Using an observable to store curUrl
property allows updating both the JSX DOM and document
when state changes.
Updating document
when curUrl
changes:
const disposer = observe(storeIns, "curUrl", ({oldValue, newValue}) => {
const {url, title, metaDesc, data, src} = newValue;
const navEvent = {
url,
doc: {
title,
metaDesc
},
data
};
if (src === "js") {
nav(navEvent);
return;
}
if (src === "browser") {
updateDoc(navEvent);
return;
}
});
Using observe
on curUrl
allows calling nav
and updateDoc
in a single place (instead of many call sites).
3. Run navByBrowser
on initial page load.
This will call events.browser.after
which will set your JS state to match the current URL.
This should be done preferably before you mount your JSX components so the first JSX render is your page content and not empty components.
This is important so the Googlebot snapshots and indexes the correct HTML.
navByBrowser();