type
Post
status
Published
date
Feb 8, 2026
slug
nextjs-shopping-platform-017
summary
tags
Next.js
category
编程学习
icon
password
1. Section Intro
Alright guys, we're just about there. There are a couple components that I want to add to the homepage to make it look a bit more professional.
好的,朋友们,我们快完成了。我想在首页添加几个组件,让它看起来更专业一些。
First we will add an Icon Boxes component. This will just be some cards with some icons and some common text you see in an ecommerce website like money back guarantee and 24/7 support.
首先,我们将添加一个图标框组件。这将是一些带有图标的卡片,以及一些在电商网站上常见的文字,比如退款保证和7×24小时支持。
Then we will create a countdown timer like you often see on sites like this. We will set it to something like 5 days.
然后,我们将创建一个倒计时器,就像你经常在这类网站上看到的那样。我们将把它设置为大约5天。
Then we'll go ahead and wrap things up for now and talk about where to go from here.
然后,我们将暂时结束,并讨论接下来的方向。
3. Icon Boxes Component 图标框组件
We are going to add a very simple static component for display that will show some common ecommerce website feature boxes. Free shipping, customer support, etc.
我们将添加一个非常简单的静态显示组件,用于展示电商网站常见的功能框。比如免费配送、客户支持等。
Let's create a new file at
components/icon-boxes.tsx and add the following code:
让我们在 components/icon-boxes.tsx 创建一个新文件并添加以下代码:We just have some icons and text here. Let's import this component into the homepage and render it.
这里我们只有一些图标和文字。让我们将这个组件导入到首页并渲染它。
Open the
app/(root)/page.tsx file and import the IconBoxes component:
打开 app/(root)/page.tsx 文件并导入 IconBoxes 组件:Now, add it below the
ViewAllProductsButton component:
现在,在 ViewAllProductsButton 组件下方添加它:3. Deal Countdown Component 优惠倒计时组件
Now, we are going to create a component that will display a deal countdown timer. It's not going to do much, but it's a nice touch to add to the homepage.
现在,我们将创建一个显示优惠倒计时器的组件。它不会做太多事情,但添加到首页会是一个不错的点缀。
Create a new file at
components/deal-countdown.tsx and add the following code:
在 components/deal-countdown.tsx 创建一个新文件并添加以下代码:Here is a quick breakdown:
这里是一个快速分解:
- We set a target date
- 我们设置一个目标日期
- Time Calculation: The calculateTimeRemaining function computes the difference between the target date and the current time, converting the result into days, hours, minutes, and seconds.
- 时间计算:calculateTimeRemaining 函数计算目标日期和当前时间之间的差值,将结果转换为天、小时、分钟和秒。
The
timeDifference calculates the number of miliseconds between now and the target date.
timeDifference 计算从现在到目标日期的毫秒数。We use
Math.floor to round to the nearest whole number. We don't want 2.8 days for example.
我们使用 Math.floor 向下取整到最接近的整数。例如,我们不想要 2.8 天。We convert the miliseconds into days by dividing the
timeDifference by the number of milliseconds in a day, which we get with (1000 * 60 * 60 * 24)
我们通过将 timeDifference 除以一天中的毫秒数(即 (1000 * 60 * 60 * 24))来将毫秒转换为天。We get the remaining time in hours by using the modulo operator to find the remainder of miliseconds that don't fit into full days.
timeDifference % (1000 * 60 * 60 * 24) gives the leftover milliseconds after accounting for full days. Dividing that by (1000 * 60 * 60) converts the remaining milliseconds into hours.
我们通过使用模运算符来计算剩余的小时数,找出不能凑成整天的毫秒余数。timeDifference % (1000 * 60 * 60 * 24) 给出了扣除整天后剩余的毫秒数。将其除以 (1000 * 60 * 60) 将剩余的毫秒数转换为小时。We then get the ramaining time for minutes by calculating the leftover milliseconds after accounting for full hours.
timeDifference % (1000 * 60 * 60) gives the remaining milliseconds after removing full days and hours.
Dividing by 1000 * 60 converts these milliseconds into minutes.
然后,我们通过计算扣除整小时后剩余的毫秒数来得到剩余的分钟数。timeDifference % (1000 * 60 * 60) 给出了扣除整天和整小时后剩余的毫秒数。除以 1000 * 60 将这些毫秒转换为分钟。We convert the remaining time for seconds by calculating the leftover milliseconds after accounting for full minutes.
timeDifference % (1000 * 60) gives the remaining milliseconds after removing full days, hours, and minutes. Dividing by 1000 converts the milliseconds into seconds.
我们通过计算扣除整分钟后剩余的毫秒数来转换剩余的秒数。timeDifference % (1000 * 60) 给出了扣除整天、小时和分钟后剩余的毫秒数。除以 1000 将毫秒转换为秒。- Timer with useEffect: We use an interval to update the remaining time every second and stop the timer when it hits zero.
- 使用 useEffect 的计时器:我们使用一个间隔每秒更新剩余时间,并在时间归零时停止计时器。
- StatBox Subcomponent: This small reusable component renders each time unit (like "Days" or "Hours") with its value.
- StatBox 子组件:这个小型可复用组件渲染每个时间单位(如"天"或"小时")及其值。
- Render a loading state during hydration
- 在水合期间渲染加载状态
- Return depends on if the timer is up or not.
- 返回内容取决于计时器是否结束。
Now import the component into
app/page.tsx and add it to the homepage.
现在将组件导入到 app/page.tsx 并添加到首页。Put it above or below the
IconBoxes component.
将其放在 IconBoxes 组件的上方或下方。4. Wrap Up 总结
Alright, so if you made it this far, congratulations! This was not a small or easy project. I just want to talk a little bit about where to go from here.
好吧,如果你已经坚持到这里了,恭喜你!这不是一个小项目,也不容易。我想稍微谈谈接下来该怎么做。
So if you plan on getting a dev job or freelancing, if you understand most of this project, I would definitely say that you're ready. We hit on a lot of advanced and real-world concepts.
所以如果你打算找一份开发工作或者做自由职业,如果你理解这个项目的大部分内容,我可以肯定地说你已经准备好了。我们涉及了很多高级和现实世界的概念。
As far as this particular project goes, feel free to do what you want with it. It's open source. You can put it on your portfolo although I would suggest changing it up a bit. Maybe change up the style, products, categories and even add some features. I would like to keep going with this app as well. Like I said in the beginning, I plan on using this for my wife's art website in the future. Any additional features that I add, will be in this course. I already have the code for adding a Google login as well as a magik link login, which is a passwordless authentication method. So I may add those within the next few months.
至于这个特定的项目,你可以随意使用。它是开源的。你可以把它放在你的作品集里,不过我建议稍微改动一下。也许可以改变一下风格、产品、分类,甚至添加一些功能。我也想继续开发这个应用。就像我一开始说的,我计划将来把它用在我妻子的艺术网站上。我添加的任何额外功能都会在本课程中。我已经有了添加谷歌登录以及魔法链接登录(一种无密码身份验证方法)的代码。所以我可能会在接下来的几个月里添加这些功能。
But again, I want to congratulate you and wish you the best in your endevours of a software development. And I hope to see you in the next course!
但再次,我想恭喜你,并祝你在软件开发的努力中一切顺利。希望在下一门课程中见到你!
5. Vercel Hobby Plan Error
不采用,可以使用下节的方法。(实际部署时未遇到这些问题)
问题背景
使用Vercel Hobby Plan(免费版)部署Next.js电商项目时,出现边缘函数中间件大小超1兆字节限制的报错,Vercel付费版无此限制。
核心解决方案
舍弃
bcrypt密码加密方式,改用内置Web加密API,减小中间件体积,适配Vercel免费版部署要求。具体操作步骤
1. 新建加密处理文件
在项目
lib文件夹下创建encrypt.ts文件,编写基于Web加密API的哈希、密码比较函数,采用HMAC算法+SHA-256哈希实现密码加密与验证。2. 卸载相关依赖
运行命令卸载
bcrypt相关依赖,必要时添加兼容标志:3. 替换项目中bcrypt引用
在项目相关文件中,将
bcrypt的hashSync、compareSync方法,替换为encrypt.ts中自定义的哈希、比较函数;添加await关键字处理异步逻辑,涉及文件包括:- lib/actions/user.actions.ts
- lib/models/user.ts
- lib/controllers/auth.ts
4. 处理样本数据密码
修改项目样本数据文件,遍历用户数据,使用自定义哈希函数重新处理密码,避免明文存储密码。
5. 重新提交并部署
- 将修改后的代码推送至GitHub仓库;
- 在Vercel项目中添加加密密钥环境变量;
- 执行重新部署操作,验证部署是否成功,同时测试密码加密功能是否正常。
6. Vercel Hobby Tier Fix Vercel 免费套餐修复
If you are using the free "hobby" tier for Vercel, you may at some point get the following error:
如果你正在使用 Vercel 的免费 "hobby" 套餐,你可能会在某个时候遇到以下错误:
I had made a post to try and fix this by swapping out bcrypt for a custom password encrypt script, but it turns out that wasn't the best fix and didn't work in some cases. If you already did that, that's absolutely fine, but it's not needed.
我曾经发过一篇帖子,尝试通过用自定义密码加密脚本替换 bcrypt 来解决这个问题,但事实证明那不是最好的修复方法,而且在某些情况下不起作用。如果你已经这样做了,那完全没问题,但这不是必须的。
We can address the issue by splitting the
auth.ts file into two files as mentioned in the this section of the Next.js Docs
我们可以通过将 auth.ts 文件拆分为两个文件来解决这个问题,正如 Next.js 文档的这一部分 中所提到的。Why This Works 为什么这样有效
By moving the authorized callback and configuration logic into a separate file (auth.config.ts), you reduce the size of the Edge Function code that Vercel processes. This modular approach not only solves the size limit issue but also makes your codebase cleaner and easier to maintain.
通过将授权回调和配置逻辑移到一个单独的文件(auth.config.ts)中,你可以减少 Vercel 处理的 Edge Function 代码大小。这种模块化方法不仅解决了大小限制问题,还使你的代码库更清晰、更易于维护。
Create The Config File 创建配置文件
Let's create a new file in the root called
auth.config.ts
让我们在根目录下创建一个名为 auth.config.ts 的新文件Add the following imports:
添加以下导入:
Now create a new config object called
authConfig and add the authorized function like so:
现在创建一个名为 authConfig 的新配置对象,并添加 authorized 函数,如下所示:Edit auth.ts 编辑 auth.ts
Now, in the
auth.ts file, remove the 2 imports:
现在,在 auth.ts 文件中,删除这两个导入:and add the following import:
并添加以下导入:
Remove the
authorized callback and instead, add this to the callbacks object:
删除 authorized 回调,而是将其添加到 callbacks 对象中:You can also remove the following because we use it in the config file:
你也可以删除以下内容,因为我们在配置文件中使用它:
We also want to specify the "jwt" value for the session.strategy as a literal rather than a regular string. So add
as const to it like this:
我们还想将 session.strategy 的 "jwt" 值指定为字面量而不是普通字符串。所以像这样添加 as const:This is because this value has to be one of 3 values ("jwt" | "database" | undefined) and we want to make sure it's always "jwt" and not a string that could be anything. Here, strategy is no longer inferred as string; it is inferred as the literal type "jwt". If you don't add this, you will get an error for for the
config we pass into NextAuth at the end of the file.
这是因为这个值必须是 3 个值之一("jwt" | "database" | undefined),我们想确保它始终是 "jwt" 而不是可以是任何值的字符串。在这里,strategy 不再被推断为字符串;它被推断为字面量类型 "jwt"。如果你不添加这个,你会在文件末尾传递给 NextAuth 的 config 中收到错误。Update the middleware Function 更新 middleware 函数
The last thing we need to do is update the
proxy.ts file to the following:
我们需要做的最后一件事是将 proxy.ts 文件更新为以下内容:This will now use the
auth.config.ts file for the configuration and the auth.ts file for the middleware function.
现在这将使用 auth.config.ts 文件进行配置,使用 auth.ts 文件进行 middleware 函数。Deploy To Vercel 部署到 Vercel
Now try and push to Vercel and you should no longer get the error about the Edge Function size being too large.
现在尝试推送到 Vercel,你应该不会再收到关于 Edge Function 大小太大的错误了。
📎 参考文章
- 一些引用
- 引用文章
欢迎您在底部评论区留言,一起交流~
Loading...
