Svelte Navigator History
⚠️⚠️⚠️ This package moved to
@svelte-navigator/history
.
⚠️⚠️⚠️
History module for
svelte-navigator. It abstracts
the management of the apps location using either the HTML5 History API, the hash
fragment of the URL or an in-memory mode.
⚠️⚠️⚠️ This is an experimental package, that will be used for the next
version of svelte-navigator. ⚠️⚠️⚠️
Table of Contents
Build requirements
Svelte Navigator History depends on a build process in which certain environment
variables are replaced. This is necessary in order to provide descriptive error
message in development, while keeping the production bundles lean.
If you're using rollup you can use
@rollup/plugin-replace
like so:
import replace from "@rollup/plugin-replace";
const isDev = Boolean(process.env.ROLLUP_WATCH);
const nodeEnv = isDev ? "development" : "production";
export default {
plugins: [
replace({ "process.env.NODE_ENV": JSON.stringify(nodeEnv) }),
],
};
If you're using webpack you can use
webpack.DefinePlugin
:
const webpack = require("webpack");
module.exports = {
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
}),
],
};
API
NavigatorHistory
Each History implements the following interface:
interface NavigatorHistory<State = unknown> {
push: (uri: string, state?: State | null) => void;
replace: (uri: string, state?: State | null) => void;
go: (delta: number) => void;
navigate: NavigateFn<State>;
readonly location: NavigatorLocation<State>;
readonly action: Action;
subscribe: (subscriber: Subscriber<HistoryUpdate<State>>) => () => void;
createHref: (to: string) => string;
release: () => void;
}
push
Calling history.push
navigates to a new URL and optionally pushes a value to
the history stack. The state is an arbitrary (serializable) value. It can be
thought of as something like the message body of an http post request. It
contains details which are not visible in the URL, but are bound to the specific
request.
history.push("/blog?id=123");
history.push("/about", { from: "/blog" });
replace
Calling history.replace
replaces the current URL and optionally the value of
the history stack.
history.replace("/login");
history.replace("/login", { from: history.location });
go
history.go
allows you to navigate the history stack, similar to using the back
and forward buttons of the browser.
const goBack = () => history.go(-1);
const goForward = () => history.go(1);
navigate
history.navigate
is a convenience method, that combines the functionality of
push
, replace
and go
.
history.navigate("/blog?id=123");
history.navigate("/login", {
state: { from: history.location },
replce: true,
});
history.navigate(-1);
location
The location represents the current state of the URL. It is very similar to the
built-in window.location
, in that it has properties for the pathname
,
search
and hash
of the URL. It can however also carry a state, that can be
set when changing location.
A location looks like this:
interface NavigatorLocation<State = unknown> {
pathname: string;
search: string;
hash: string;
state: State | null;
key: string;
}
action
The action represents what event lead to the change in location. Possible values
are:
"POP"
: The default value. It is caused by hitting the back or forward button
of the browser, or by calling history.go
."PUSH"
: A new entry has been pushed to the history stack, by calling
history.push
. This is what you want to use when navigating programmatically
in your app."REPLACE"
: An entry of the history stack has been replaced with another one.
This is caused when history.replace
has been called.
subscribe
You can register an event handler by calling history.subscribe
. The handler
you pass to subscribe
is called with the location and action of the latest
navigation. It is also called when the subscriber is registered. subscribe
returns an unsubscribe
function, which when called removes the event
subscriber.
const unsubscribe = history.subscribe(({ location, action }) => {
const url = `${location.pathname}${location.search}${location.hash}`;
console.log(`Action: ${action}; Url: ${url}`);
});
unsubscribe();
createHref
history.createHref
takes a path and returns a string, you can use as a href
attribute of an <a>
element. For hash routing for example, a "#"
has to be
prepended to the beginning of a path.
release
A history might need to attach some global event handlers to be able to react to
changes in location. If you're for whatever reason creating lots of history
instances (which is probably a bad idea...), you should call history.release
when you don't need the instance anymore. It will unregister all event handlers
and allow the instance to be garbage collected, preventing memory leaks.
Browser History
Browser history uses the
HTML5 History API to
store app's location and state in the URL. This is probably the best choice for
most apps, as it enables best CEO possibilities and will be most intuitive for
most users. This setup however needs some additional work because you need to
configure your server to always serve your index.html file when a request
doesn't match a file. You can read more about it in
vue-routers docs about history routing.
createBrowserHistory
Create an instance of a browser history. It will update the URL when the app's
location changes. It will also listen to navigation events dispatched by the
browser after the back and forward buttons have been clicked.
When using createBrowserHistory
don't interact with the browsers history
object yourself. It will lead to inconsistent states and you won't have a good
time debugging that... Also, always use the created history instance to read the
current location, and don't use the browsers location
object. Again
inconsistent location states aren't fun.
import { createBrowserHistory } from "svelte-navigator-history";
const history = createBrowserHistory();
history.subscribe(console.log);
history.navigate("/blog?id=123");
browserHistory
browserHistory
is an instance of a BrowserHistory, that is created for
convenience. It can be used as the default history instance.
import { browserHistory } from "svelte-navigator-history";
browserHistory.subscribe(console.log);
browserHistory.navigate("/blog?id=123");
Hash History
Hash history uses the hash fragment of the URL to simulate routing via URL. This
approach is great if you want to get started quickly or if you don't have access
to your server's configuration.
createHashHistory
Create an instance of a hash history. It will change the hash of the URL when
the app's location changes.
Again, you should not interact with the global history
or location
objects
yourself.
import { createHashHistory } from "svelte-navigator-history";
const history = createHashHistory();
history.subscribe(console.log);
history.navigate("/blog?id=123");
hashHistory
hashHistory
is an instance of a HashHistory, that is created for convenience.
It can be used as the default history instance.
import { hashHistory } from "svelte-navigator-history";
hashHistory.subscribe(console.log);
hashHistory.navigate("/blog?id=123");
Memory History
Memory history keeps the location state of your app in memory. This is mainly
useful for testing if you don't run your tests in a browser. You could also use
a memory history if you want to control the state of a widget you embed in
another app using a router.
createMemoryHistory
Create an instance of a hash history. It will change the hash of the URL when
the app's location changes.
Again, you should not interact with the global history
or location
objects
yourself.
import { createMemoryHistory } from "svelte-navigator-history";
const history = createMemoryHistory();
history.subscribe(console.log);
history.navigate("/blog?id=123");
memoryHistory
memoryHistory
is an instance of a MemoryHistory, that is created for
convenience. It can be used as the default history instance.
import { memoryHistory } from "svelte-navigator-history";
memoryHistory.subscribe(console.log);
memoryHistory.navigate("/blog?id=123");
parsePath
Create a location object from a URL string.
import { parsePath } from "svelte-navigator-history";
const path = "/search?q=falafel#result-3";
const location = parsePath(path);
stringifyPath
Joins a location object to one path string.
import { stringifyPath } from "svelte-navigator-history";
const location = {
pathname: "/search",
search: "?q=falafel",
hash: "#result-3",
};
const path = stringifyPath(location);
createNavigate
Create the createNavigate
convenience method expected in the
NavigatorHistory
interface. Pass a Partial NavigatorHistory
object, which
implements the push
, replace
and go
methods, to the factory function.
import { createNavigate } from "svelte-navigator-history";
const customHistory = {
push(uri, state) {
console.log("PUSH");
},
replace(uri, state) {
console.log("REPLACE");
},
go(delta) {
console.log("GO");
},
};
customHistory.navigate = createNavigate(customHistory);
License
MIT