部署到 GitHub Pages?别忘了修复链接
本文最初发表于前一天,网址为https://maximorlov.com/deploying-to-github-pages-dont-forget-to-fix-your-links/
将网站部署到 GitHub Pages 后,您的网站无法正常运行吗?
你看到的是一个空白页面,或者首页显示正常,但点击链接后却没有任何反应。你打开开发者工具,却发现一堆 404 状态码。
很多开发者都会遇到这种情况——网站在本地主机上运行良好,但部署到 Github Pages 后,一切都崩溃了。
通过了解核心问题,您将能够发现它并防止它在您未来的所有部署中发生,而不仅仅是在 Github Pages 上。
让我们一起调查这个问题,确保您的网站在生产环境中正常运行。
什么是根相对链接?
为了更好地理解为什么在部署到 Github Pages 时链接经常失效,首先我们需要了解什么是根相对链接。
根相对链接是指以斜杠 ( //) 开头的链接。点击根相对链接时,它会忽略当前 URL 的路径位置。URL 的哪一部分是路径?域名之后的所有内容。例如,以下 URL 的路径https://example.com/blog/articles是/blog/articles:
无论位于何处,根相对链接始终指向当前域内的同一路径。请看以下示例:
<!--
Root-relative links ignore the current URL and always lead
to the same path within the current domain
-->
<!-- Current location: https://example.com/ -->
<a href="/awesome-post"> <!-- leads to: https://example.com/awesome-post -->
<!-- Current location: https://example.com/blog -->
<a href="/awesome-post"> <!-- leads to: https://example.com/awesome-post -->
<!-- Current location: https://example.com/blog/articles -->
<a href="/awesome-post"> <!-- leads to: https://example.com/awesome-post -->
根相对链接和 GitHub Pages
当我们将网站移动到不同的路径位置时,根相对链接的不灵活性就会显现出来。
假设你的文章托管在某个地方https://example.com/<article-slug>,现在你决定将它们迁移到网站的专属博客版块。你的文章现在位于[此处应填写博客地址https://example.com/blog/<article-slug>]。如果你从该页面链接到另一篇文章,例如[此处应填写文章<a href="/awesome-post">链接],那么该链接将指向已不存在的旧地址。https://example.com/awesome-post
根相对链接会忽略其当前路径,并且不会跟随位置变化。
当你在本地开发网站,然后将其部署到 GitHub Pages 2 时,也会发生同样的情况。网站的位置会从根目录(/)变为项目仓库名称:
您网站上的所有内容(包括图片、CSS 和 JS 文件等资源)都已迁移到新位置。指向/awesome-article本地主机的链接需要指向/my-project/awesome-article生产环境中的网址。
给所有链接加上前缀
要解决这个问题,你需要在所有链接前加上项目仓库名称的前缀。幸运的是,大多数静态网站生成器和框架都提供了在构建过程中配置此设置的选项,因此你无需手动操作。
了不起的盖茨比
在 Gatsby 中,您可以pathPrefix向其添加值gatsby-config.js:
// Configure Gatsby to prefix all links with the Github repository name
module.exports = {
pathPrefix: '/my-project',
}
然后,在构建应用程序时,您需要--prefix-paths像这样将该标志添加到命令中:
gatsby build --prefix-paths
如果不添加此标志,Gatsby 将忽略该pathPrefix配置,并将您的网站构建为如同托管在根路径下一样。
文档:https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/path-prefix/
创建 React 应用
使用 Create React App 时,配置位于文件homepage中的属性中package.json:
"homepage": "https://username.github.io/my-project",
利用这一点,Create React App 将推断出要在生成的 HTML 中使用的位置。
如果您使用的是 React Router v4 或更高版本,则需要在任何<Router>组件上进行额外配置,以<Link>在 `<s>` 标签前添加前缀。<BrowserRouter>例如:
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Link to="/awesome-post">
</BrowserRouter>
Create React App 会从设置中提取路径位置homepage,并通过环境变量将其提供给您PUBLIC_URL。
文档:https://create-react-app.dev/docs/deployment/#building-for-relative-paths
Next.js
更新:随着 Next.js 9.5 的发布,为所有链接添加前缀比以前容易得多。您可以在 next.config.js 文件中进行配置
basePath。如果您使用的是旧版本的 Next.js,可以按照以下步骤操作。
在 Next.js 中,首先需要将assetPrefix配置添加到next.config.js文件中:
const pathPrefix = process.env.NODE_ENV === 'production'
? '/my-project'
: '';
module.exports = {
assetPrefix: pathPrefix,
env: {
pathPrefix,
},
};
此外,您还需要将前缀赋值给一个环境变量,以便在应用程序中重复使用。遗憾的是,Next.js 没有提供简便的方法来为<Link>组件添加前缀。您必须手动操作,最佳方法是创建一个<PrefixedLink>组件并在整个应用程序中使用它。
import Link from 'next/link';
const PrefixedLink = ({ href, as = href, children, ...props }) => (
<Link
href={href}
as={`${process.env.pathPrefix}${as}`}
{...props}
>
{children}
</Link>
);
export default PrefixedLink;
<Link>将应用程序中的所有组件替换为这些<PrefixedLink>组件,一切就绪。
文档:https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix
观景台
在 Vue 中,给链接添加仓库名称前缀非常简单。你需要正确publicPath设置vue.config.js:
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/my-project/' // note the trailing slash
: '/',
};
该设置仅在生产环境中应用,因此不会破坏您在本地主机上的开发工作流程。
文档:https://cli.vuejs.org/guide/deployment.html#github-pages
为什么不使用相对链接?
你可能想知道——为什么我们不使用相对链接呢?像 `/etc/example.com` 这样的链接<a href="awesome-post">(不带斜杠/)会遵循其当前路径位置,即使你的网站托管在多个目录下也能正常工作/blog/articles/2020/...。
使用相对链接的缺点在于,它们会破坏依赖 HTML5 History API 的客户端路由。虽然你可能不会直接使用它,但 React Router、Vue Router、Next.js 和 Gatsby 等框架底层都使用了 History API。客户端路由是单页应用的核心,它使得用户无需刷新浏览器即可导航到其他页面。
如果你的网站不是单页应用程序,并且你不关心客户端路由,Create React App 和 Vue 允许你选择使用相对链接。
React Router v6(撰写本文时仍处于 alpha 测试阶段)预计将支持相对链接以及客户端路由。这无疑是个好消息,因为这意味着我们将拥有开箱即用的可移植应用程序,并且无需再担心链接失效的问题。
编写简洁的代码。保持领先地位。
每隔一周的周二,我都会分享构建健壮的 Node.js 应用的技巧。加入我们,与致力于职业发展的开发者们一起,获取成功所需的知识和技能。
-
有时你会看到根相对链接被错误地称为绝对链接。这在技术上是不正确的,因为绝对链接总是以协议(https://)开头。这种混淆源于根相对链接相对于URL 的 路径部分而言是绝对的。
-
GitHub Pages 区分用户站点和项目站点。用户站点通过根路径( `/usr/bin/github.io`
/)提供服务,但必须位于名为`username.github.io`的仓库中。一个 GitHub 帐户只能拥有一个用户站点。因此,您更常看到的是项目站点,本文也主要讨论项目站点 。
