使用Next.js和Vercel Postgres创建一个链接缩短器。学习动态路由,数据库连接和域自定义。
tl; dr
检查演示here
检查源代码here
介绍
链接缩短器已成为共享冗长URL的首选解决方案,尤其是在角色计数很重要的平台上。它们简单,高效且非常方便。在这篇博客文章中,我们正在使用Next.js和Vercel Postgres进行简单且免费的链接缩短器的创建。
我们的演示将展示以下功能:
- 访问SLUG时自动重定向到目标链接
- 跟踪每个链接的访问次数
- 显示数据库链接的统计数据
先决条件
除了创建典型的NextJS应用程序的要求外,您还需要一个Vercel帐户。如果您没有一个,则可以注册here。
安装
遵循本指南的最简单方法是到degit a Nextjs样板。
npx degit codegino/nextjs-ts-tw-tldr next13-i18n
由于个人喜好,我将使用TailwindCSS和TypeScript,但是您可以使用普通的CSS和JavaScript。
安装依赖项
npm i
删除未使用的文件
删除app
和components
文件夹下的所有内容
rm -rf app/* components/*
设置NextJS-第1部分
制作占位符路线解析器
在链接Shortener应用程序中,“ slug”是每个缩短链接的唯一名称。此slug可帮助该应用在单击缩短链接时将用户发送到正确的URL。
我们将使用NextJS的动态路线为我们独特的slug铺路。现在,我们将其保持基础,只需将任何slug重定向到一个页面。
// app/[slug]/route.ts
export const GET = () => {
return NextResponse.redirect('https://google.com', 302);
};
使用npm run dev
运行该应用后,我们可以转到http://localhost:3000/xyz
,它应该重定向到Google的主页。
初始部署
首先部署我们的应用程序将简化该过程。 Vercel提供了一种将现有项目连接到数据库的简便方法,该项目将在以后创建。
安装Vercel CLI
首先安装Vercel CLI:
npm i -g vercel
登录到Vercel
接下来,登录到您的Vercel帐户:
vercel login
部署应用程序
最后,部署应用程序:
vercel --prod
有关使用Vercel CLI部署的更多信息,请查看this guide
设置数据库
创建Vercel Postgres数据库
首先,登录您的Vercel帐户,导航到dashboard,然后选择“ Storage
”选项卡。然后,单击Create Database
按钮。
将出现一个对话框。选择PostgreSQL
选项,然后单击Continue
。
您会看到另一个弹出窗口。如果您同意该条款,请单击Accept
。然后,设置您的数据库名称,然后单击Create
。
创建链接表
当前,Vercel Postgresql没有为各种操作提供内置界面。因此,我们现在使用查询跑步者。
CREATE TABLE links (
id SERIAL PRIMARY KEY,
alias VARCHAR(255) NOT NULL UNIQUE,
target VARCHAR(2048) NOT NULL,
visit_count INTEGER DEFAULT 0
);
上面的查询将创建一个具有以下列的表:
- id:每个链接的唯一标识符
- 别名:将用于创建缩短链接的sl
- 目标:目标URL
- visit_count:访问链接的次数
我们可以添加其他跟踪信息,例如源主机,用户代理等。但是,对于此演示,我们将保持简单。
添加一个新链接条目
要测试我们的设置,让我们使用以下查询添加一个新的链接条目:
INSERT INTO links (alias, target)
VALUES ('nggyu', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ');
我们可以使用Browse
选项卡浏览表。
设置NextJS-第2部分
安装Vercel Postgres软件包
首先安装Vercel Postgres软件包:
npm i @vercel/postgres
连接项目
按照以下步骤将您的Vercel项目连接到数据库:
Vercel简化了从数据库加载环境变量的过程。您可以通过运行以下命令来执行此操作:
vercel env pull .env.development.local
- 安装Vercel Postgres软件包
npm install @vercel/postgres
- 更新路线处理程序
接下来,用提供的代码替换app/[slug]/route.ts的内容。
// app/[slug]/route.ts
import {NextResponse} from 'next/server';
import {sql} from '@vercel/postgres';
// Exporting an async GET function that takes the params object in the second argument
export const GET = async (_, {params}) => {
// Making a SQL query to select a link from the links table where the alias matches the provided slug
// The result is limited to 1 row
const {rows} =
await sql`SELECT * FROM links WHERE alias=${params.slug} LIMIT 1`;
// If no rows are returned, return a response indicating the slug is not in the record
if (rows.length === 0) {
return new Response(`<h1>/${params.slug} is not in our record</h1>`, {
status: 400,
headers: {
'content-type': 'text/html',
},
});
}
// If a row is returned, increment the visit_count for the link with the provided slug
if (rows[0]) {
await sql`UPDATE links SET visit_count = visit_count + 1 WHERE alias = ${params.slug}`;
}
// Redirect to the target of the first row (the selected link)
return NextResponse.redirect(rows[0].target, 302);
};
应用程序运行后,访问http://localhost:3000/nggyu
应将我们重定向到目标链接。
我们看到了404页,因为我们还没有创建Home/index页面。
设置默认页面(可选)
如果没有提供lug的情况,则该应用程序将尝试解析未定义的根路由。但是,您可以根据需要自定义此行为。对于此演示,我将设置根路由,以显示数据库中所有链接的基本统计信息。
创建布局组件
// app/layout.ts
import '../styles/tailwind.css';
export const metadata = {
title: 'Next Link Shortener',
description: 'Generated by Next.js',
};
export default function RootLayout({children}: {children: React.ReactNode}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
创建主页
此页面将以表格式显示数据库中所有链接的统计信息。
// app/page.ts
import React from 'react';
import {sql} from '@vercel/postgres';
const Page = async () => {
const links = await getData();
return (
<div className="min-h-screen bg-gray-100 flex flex-col items-center pt-8">
<h1 className="text-2xl font-bold mb-5 text-gray-900">Links stats</h1>
<div className="flex flex-col items-center overflow-hidden">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left font-medium">Alias</th>
<th className="px-6 py-3 text-left font-medium">Target</th>
<th className="px-6 py-3 text-left font-medium">Visit Count</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{links.map((link, index) => (
<tr key={index}>
<td className="px-6 py-4 whitespace-nowrap">{link.alias}</td>
<td className="px-6 py-4 whitespace-nowrap">{link.target}</td>
<td className="px-6 py-4 whitespace-nowrap">
{link.visit_count}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
const getData = async () => {
const {rows} = await sql`SELECT * FROM links`;
return rows;
};
export default Page;
运行应用程序后,每次访问别名都应增加访问数量。
自定义域
如果不自定义我们的域,我们可能最终会获得更长的链接,从而破坏了链接缩短器的目的。例如,Vercel为此演示提供的默认域是https://demo-nextjs-link-shortener.vercel.app/nggyu。
与Vercel
Vercel允许我们修改域。这是过程:
- 导航到
Settings
选项卡 - 选择
Domains
- 选择要修改的域
- 击中
Edit
- 输入您要使用的子域,然后单击
Save
与DNS提供商
上一个选项很棒,但是域中有Vercel品牌。如果要删除它,可以使用自己的域。
记住,这不是免费的,因为您需要购买域。我从NameCheap
得到了我设置它:
- 如果您使用的是namecheap,请转到仪表板上的
Advanced DNS
选项卡。 >如果您使用的是其他提供商,则可以Google如何在<your provider>
中添加CNAME Record
。 - 创建新记录
- 要将所有流量引导到Vercel,我添加了带有主机
@
和Value76.76.21.21
的A Record
- 接下来,我添加了一个带有主机
links
和valuecname.vercel-dns.com
的CNAME Record
在Vercel中添加自定义域:
- 转到
Settings
选项卡 - 单击
Domains
- 输入要在文本字段中添加的域
- 单击
Add
可能会询问您是否要将现有流量重定向到我建议这样做的新域。
设置后,您应该拥有一个可以与世界共享的功能齐全的链接shortener应用程序。
结论
总而言之,我们探索了如何使用next.js和vercel Postgres,设置动态路由,连接到数据库并跟踪链接访问来构建链接Shortener。我们还深入研究了使用Vercel和DNS提供商自定义域,展示了我们设置的灵活性。请记住,虽然此演示是基本的,但它为扩展的无尽可能性打开了大门。愉快的编码!