刷新后 Github 页面 URI 上的客户端路由和 404
Client-side routing and 404 on Github Pages URIs after refresh
这可能更多的是 Github 页问题而不是 JS 问题。
我正在学习 VanillaJS SPA. I'm finding when I push it to Github Pages with gh-pages
上的教程,而如果您从 /
开始并单击各种导航链接,则路由有效,您将看到 URI 相应地更新为 /posts
, /settings
, 等等
但是,如果我在 /posts
、/settings
等刷新页面,或尝试转到 /
以外的任何路线,我会收到来自 Github.
我敢肯定,这是因为应用程序只是在 DOM 操作并更新浏览器中的 URI 字符串。 Github 页面的网络服务器知道如何处理 /
,但当涉及到 /posts
、/settings
等时,它正在寻找实际的子目录,这些子目录实际上并不存在于外部DOM 操纵。
我很好奇是否有办法让客户端路由与 Github 页面一起工作,或者这是否行不通并创建子目录以对应这些路线是必经之路?
这是路由代码:
import Dashboard from "./views/Dashboard.js";
import Posts from "./views/Posts.js";
import PostView from "./views/PostView.js";
import Settings from "./views/Settings.js";
const pathToRegex = path => new RegExp("^" + path.replace(/\//g, "\/").replace(/:\w+/g, "(.+)") + "$");
const getParams = match => {
const values = match.result.slice(1);
const keys = Array.from(match.route.path.matchAll(/:(\w+)/g)).map(result => result[1]);
return Object.fromEntries(keys.map((key, i) => {
return [key, values[i]];
}));
};
const navigateTo = url => {
history.pushState(null, null, url);
router();
};
const router = async () => {
const routes = [
{ path: "/", view: Dashboard },
{ path: "/posts", view: Posts },
{ path: "/posts/:id", view: PostView },
{ path: "/settings", view: Settings }
];
// Test each route for potential match
const potentialMatches = routes.map(route => {
return {
route: route,
result: location.pathname.match(pathToRegex(route.path))
};
});
let match = potentialMatches.find(potentialMatch => potentialMatch.result !== null);
if (!match) {
match = {
route: routes[0],
result: [location.pathname]
};
}
const view = new match.route.view(getParams(match));
document.querySelector("#app").innerHTML = await view.getHtml();
};
window.addEventListener("popstate", router);
document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener("click", e => {
if (e.target.matches("[data-link]")) {
e.preventDefault();
navigateTo(e.target.href);
}
});
router();
});
我没有使用这个 server.js
因为我没有看到 express
如何与 Github 页面一起工作:
const express = require('express');
const path = require('path');
const app = express();
app.use(
'/static',
express.static(path.resolve(__dirname, 'frontend', 'static'))
);
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'index.html'));
});
app.listen(process.env.PORT || 8000, () => console.log('Server running...'));
GitHub 页面仅适用于静态网站。这意味着它不提供设置服务器(您可以在其中使用 Node.js/Express 代码)或允许动态页面路由的选项。
但是,它确实允许您拥有自定义 404 页面,您可以将其用作解决此问题的方法:
将您的主要逻辑移动到一个名为 404.html
的文件中,然后每次用户请求的路径实际上不存在时都会提供该文件。
这种方法的一个缺点是您无法限制网站上的范围,因此您必须手动为真正找不到的路径创建一个特殊情况。
您不能使用 URL 导航,但必须实施 SPA #
标签导航。
GitHub 页面将仅支持 Jekyll,而不是 URL 类似 Firebase 托管的重写。
只需编辑 index.html
和 routes
:
<nav class="nav">
<a href="#" class="nav__link" data-link>Dashboard</a>
<a href="#posts" class="nav__link" data-link>Posts</a>
<a href="#settings" class="nav__link" data-link>Settings</a>
</nav>
点击这些将发出 popstate
事件。
如果您将 404.html 添加到 /docs 文件夹并将 html 从 index.html 文件复制并粘贴到其中,这将解决任何构建问题。
步骤
- 构建应用程序
- 复制并粘贴 index.html 到一个新的 404.html 文件中
- 推送给你GitHub repo 以便页面可以重新部署网站的新版本
注意:每次都必须这样做,因为构建会从 /docs 文件夹中清除创建的 404.html 文件。这适用于 angular 个应用程序。
这可能更多的是 Github 页问题而不是 JS 问题。
我正在学习 VanillaJS SPA. I'm finding when I push it to Github Pages with gh-pages
上的教程,而如果您从 /
开始并单击各种导航链接,则路由有效,您将看到 URI 相应地更新为 /posts
, /settings
, 等等
但是,如果我在 /posts
、/settings
等刷新页面,或尝试转到 /
以外的任何路线,我会收到来自 Github.
我敢肯定,这是因为应用程序只是在 DOM 操作并更新浏览器中的 URI 字符串。 Github 页面的网络服务器知道如何处理 /
,但当涉及到 /posts
、/settings
等时,它正在寻找实际的子目录,这些子目录实际上并不存在于外部DOM 操纵。
我很好奇是否有办法让客户端路由与 Github 页面一起工作,或者这是否行不通并创建子目录以对应这些路线是必经之路?
这是路由代码:
import Dashboard from "./views/Dashboard.js";
import Posts from "./views/Posts.js";
import PostView from "./views/PostView.js";
import Settings from "./views/Settings.js";
const pathToRegex = path => new RegExp("^" + path.replace(/\//g, "\/").replace(/:\w+/g, "(.+)") + "$");
const getParams = match => {
const values = match.result.slice(1);
const keys = Array.from(match.route.path.matchAll(/:(\w+)/g)).map(result => result[1]);
return Object.fromEntries(keys.map((key, i) => {
return [key, values[i]];
}));
};
const navigateTo = url => {
history.pushState(null, null, url);
router();
};
const router = async () => {
const routes = [
{ path: "/", view: Dashboard },
{ path: "/posts", view: Posts },
{ path: "/posts/:id", view: PostView },
{ path: "/settings", view: Settings }
];
// Test each route for potential match
const potentialMatches = routes.map(route => {
return {
route: route,
result: location.pathname.match(pathToRegex(route.path))
};
});
let match = potentialMatches.find(potentialMatch => potentialMatch.result !== null);
if (!match) {
match = {
route: routes[0],
result: [location.pathname]
};
}
const view = new match.route.view(getParams(match));
document.querySelector("#app").innerHTML = await view.getHtml();
};
window.addEventListener("popstate", router);
document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener("click", e => {
if (e.target.matches("[data-link]")) {
e.preventDefault();
navigateTo(e.target.href);
}
});
router();
});
我没有使用这个 server.js
因为我没有看到 express
如何与 Github 页面一起工作:
const express = require('express');
const path = require('path');
const app = express();
app.use(
'/static',
express.static(path.resolve(__dirname, 'frontend', 'static'))
);
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'index.html'));
});
app.listen(process.env.PORT || 8000, () => console.log('Server running...'));
GitHub 页面仅适用于静态网站。这意味着它不提供设置服务器(您可以在其中使用 Node.js/Express 代码)或允许动态页面路由的选项。
但是,它确实允许您拥有自定义 404 页面,您可以将其用作解决此问题的方法:
将您的主要逻辑移动到一个名为 404.html
的文件中,然后每次用户请求的路径实际上不存在时都会提供该文件。
这种方法的一个缺点是您无法限制网站上的范围,因此您必须手动为真正找不到的路径创建一个特殊情况。
您不能使用 URL 导航,但必须实施 SPA #
标签导航。
GitHub 页面将仅支持 Jekyll,而不是 URL 类似 Firebase 托管的重写。
只需编辑 index.html
和 routes
:
<nav class="nav">
<a href="#" class="nav__link" data-link>Dashboard</a>
<a href="#posts" class="nav__link" data-link>Posts</a>
<a href="#settings" class="nav__link" data-link>Settings</a>
</nav>
点击这些将发出 popstate
事件。
如果您将 404.html 添加到 /docs 文件夹并将 html 从 index.html 文件复制并粘贴到其中,这将解决任何构建问题。
步骤
- 构建应用程序
- 复制并粘贴 index.html 到一个新的 404.html 文件中
- 推送给你GitHub repo 以便页面可以重新部署网站的新版本
注意:每次都必须这样做,因为构建会从 /docs 文件夹中清除创建的 404.html 文件。这适用于 angular 个应用程序。