Gives MPA a SPA-like user experience with no refreshing and incremenal loading.
npm install --save-dev mtos
<script src="https://cdn.jsdelivr.net/npm/mtos@0.8.0/dist/mtos-iife.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mtos@0.8.0/dist/mtos-umd.min.js"></script>
<script
type="module"
src="https://cdn.jsdelivr.net/npm/mtos@0.8.0/dist/mtos-esm.js"
></script>
You can copy the scripts in the dist folder directly to your web server static folder.
Recommendations:
You can also download the script using npm.
npm pack mtos
tar -xzf mtos-0.8.0.tgz
mv package/dist/mtos-iife.min.js .
rm -r mtos-0.8.0.tgz package
Goto target href.
function goto(href: string, push?: boolean): boolean;
mtos.goto("/blog/1");
Check if link is internal link.
function check(a: HTMLAnchorElement): boolean;
mtos.check("https://localhost:5050/blog/1"); // true
Setup mtos with user configuration.
interface Config {
/** Eval Script Element When Update, Default is false */
eval?: boolean;
/** Fetch Options */
fetch?: RequestInit;
/** Auto Scroll Behavior */
scroll?: {
enable?: boolean;
left?: number;
top?: number;
behavior?: "auto" | "smooth";
};
/** Fetch Hooks */
onMatch: (a: HTMLAnchorElement) => boolean;
onFetchStart?(href: string): boolean | undefined | void;
onFetchEnd?: (html: string, href: string) => string | undefined | void;
onFetchError?: (error: Error, href: string) => void;
/** Render Hooks */
onBeforePageRendered?: (href: string) => void;
onPageRendered?: (href: string) => void;
/** Dom Patch Hooks */
getNodeKey?: (node: Node) => any;
onBeforeNodeAdded?: (node: Node) => Node;
onNodeAdded?: (node: Node) => Node;
onBeforeElUpdated?: (fromEl: HTMLElement, toEl: HTMLElement) => boolean;
onElUpdated?: (el: HTMLElement) => void;
onBeforeNodeDiscarded?: (node: Node) => boolean;
onNodeDiscarded?: (node: Node) => void;
onBeforeElChildrenUpdated?: (
fromEl: HTMLElement,
toEl: HTMLElement
) => boolean;
}
function setup(userConfig: Config): void;
-
Use New Match Function
Replace default match function, check if link is internal link, if
true
enable mtos, iffalse
ignore this link. By default, the function ischeck
.mtos.setup({ onMatch({ host, href }) { return !href.endsWith("refresh") && host === window.location.host; }, });
-
Use Fetch Options
Setup the fetch request options.
mtos.setup({ fetch: { headers: { Cookie: "xxx=yyy", }, credentials: "same-origin", }, });
-
Use Hooks
Use patch hooks to enable transition animation.
mtos.setup({ onBeforeElUpdated(fromEl, toEl) { if (toEl.tagName === "MAIN") { toEl.classList.add("animated", "fadeIn"); } }, onElUpdated(el) { if (el.tagName === "MAIN") { setTimeout(() => { el.classList.remove("animated", "fadeIn"); }, 500); } }, });
-
Life Cycle
Using life cycle hooks to update progress.
mtos.setup({ onFetchStart() { updateProgress(0); }, onFetchEnd() { updateProgress(60); }, onBeforePageRendered() { updateProgress(80); }, onPageRendered() { updateProgress(100); }, });
Main function, add onclick
property to all matched link elements.
function mtos(): void;
Mtos works similar to SPA, but is based on native dom. The workflow like this:
- Query all
<a>
elements which propertyhref
includes current host. - Add a
onclick
function, when clicked, fetch the html content from target link. - Push link to history state.
- Diff current document with fetched content, update changed elements.
- Goto 1.
-
Enhance traditional Multi Page Application, so that pages do not need to be refreshed for a better user experience and no changes to the project structure are required.
-
Enhance Static Site Generators to give the original multi-page architecture a SPA-like experience.
-
Creating simple websites using just html can be used to replace the SPA + SSR architecture in many simple cases.
fix: eval script block- feat: support diff root elements that not head and body
- feat: cache page when hover link (optional)
- feat: support update part of elements, like htmx
fix: restore scrolling position when go backfeat: support animation between pagesfeat: support filer target linkfeat: support onMount, onUnmount, ...hooksfeat: support fetch hook, enable request with cookie
Copyright (c) 2022, Raven Satir