◆ ライブラリはなくても困らない
◆ ページ移動時にアプリ内なら history.push で URL 書き換え
◆ ページ移動やページバックで URL が変わるとデータを更新して再 render
  ◆ URL のルート情報
  ◆ そのルートで使うデータの初期化
◆ lit-html の render に渡すテンプレートをルート情報に応じて変える

React や Vue には router ライブラリがあります
React のは公式とは別ですが ほぼ標準みたいな有名なものです
Vue では公式のライブラリになってます

lit-html で SPA にしようとして そういえば router ライブラリがないなと思いました
issue を見てみても lit-html はテンプレートライブラリだから router は好きな外部のライブラリを使ってということでした

Page.js や vaadin など

ライブラリはなくてもいい

実際 これまで SPA のページ作るときにフレームワークも使ってなければ router ライブラリも使ってないことがほとんどでしたが特に困ってません
標準というものがないなら なしでいいかなと router ライブラリなしで作ってみました



router と言ってもやることは 一番上の階層で 今の URL に応じたテンプレートを返すだけです

render(
view(data),
document.getElementById("root")
)

がルートの render なら view 関数ではこういう感じでテンプレートを選びます

const view = data => {
if (data.route === "foo") return pages.foo(data)
if (data.route === "bar") return pages.bar(data)
}

この pages.foo や pages.bar では lit-html の html 関数を使ってテンプレートを返します

ページを頻繁に切り替えるとかページが重いのでキャッシュしたい場合は cache ディレクティブが使えます
https://lit-html.polymer-project.org/guide/template-reference#cache


また URL からどのテンプレートを使うのかの情報を判断する処理も必要です
ルートの view 関数に入れてしまうのもありですが 多くの場合判断するだけじゃなくてそのページとしてデータの初期化が必要です
そうなると データの更新とかが入るので view 部分にいるのは適切じゃないです

なので URL が変わるタイミングで呼び出される関数を用意してそこで処理を行います
その後更新されたデータを使って render を実行します
上の例では data.route にそこで設定されたルート名が入る想定です


あとはリンクです
単純に window にクリックリスナをつけて クリックされたのが a タグの中だったら history.push でページ移動することもできます
ただし本当に全部だと困るので別タブで開く target 属性がある場合やアプリ管理外の URL へのリンクなら何もせずブラウザに任せます

全体をまとめて受け取ると困る場合もあるなら それぞれの click リスナで history.push を使う場合は navigate 関数を設定する作りにもできます

html`<a href="/page1" @click=${navigate("/page1")}>link</a>`

href があるなら navigate 引数に書かなくても event.currentTarget.href で取得するのもありです