我不太确定我在 next.js 电子商务项目的 signin.js route API 中编写的算法有什么问题,但按时正确加载页面非常好,无需等待很长时间(大约1s),但是我一部署到 netlify 中,事情就发生了变化,netlify 的错误页面弹出说
"2023-04-09T13:26:17.617Z 4cba366e-5bdf-4bcc-b6f0-9d6975604105 Task timed out after 10.02 seconds"
我用尽了我所有的选择,花了几天时间试图修复它,并尝试了网络上的许多建议解决方案,但到目前为止没有一个有效,现在感觉真的很绝望。当我在 AWS Amplify 中部署时也会发生同样的事情,而且我的图像甚至没有显示在那里,看到有人在 github 上建议要求 netlify 增加超时限制,但我认为这不会解决问题,因为访问者不会等待页面加载超过 4 秒,我什至不能说我现在有多绝望,花了这么多时间开发这个项目,需要尽快在我的 github 上为我的客户展示,我们将不胜感激任何帮助。
P.S:类似的事情也发生在forgot.js页面,当我输入电子邮件时总是返回 500 或 502,尽管它存在于我的 ddatabase 中! 到目前为止我尝试了什么:
-切换到不同的云平台,如 Amplify、Vercel...
-检查了很多次 .env 文件是否有问题,我很确定它一切正常,并且仔细检查了那里的每个变量。
-更新了项目中的所有包,还重新安装了 node_modules
制作链接: https://musical-lokum-78f90a.netlify.app/
页面 >signin.js
import React from "react";
import styles from "../styles/signin.module.scss";
import { BiLeftArrowAlt } from "react-icons/bi";
import Link from "next/link";
import LoginInput from "../components/custom/loginIput";
import Image from "next/image";
import { signIn } from "next-auth/react";
import { useState } from "react";
import { getProviders } from "next-auth/react";
import { useRouter } from "next/router";
import { getSession } from "next-auth/react";
import BarLoader from "react-spinners/BarLoader";
import {getCsrfToken} from 'next-auth/react'
function Signin({ providers, csrfToken, callbackUrl }) {
const [user, setUser] = useState({
email: "",
password: "",
});
const router = useRouter();
const [message, setMessage] = useState({
error: "",
successMessage: "",
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const result = await signIn("credentials", {
redirect: false,
email: user.email,
password: user.password,
});
if (result?.error) {
setLoading(false);
setMessage({ ...message, error: result.error });
}
if (result?.ok) {
const session = await getSession();
console.log(session);
const successMessage = "You have successfully logged in !";
const waitTime = 3000;
setLoading(false);
setMessage({ ...message, successMessage });
let timer = setTimeout(() => {
router.push(callbackUrl || "/");
}, waitTime);
return () => {
clearTimeout(timer);
};
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setUser({ ...user, [name]: value });
};
return (
<>
<div className={styles.login}>
<div className={styles.login__container}>
<div className={styles.login__header}>
<div className={styles.goback__svg}>
<BiLeftArrowAlt />
</div>
<span>Shop over +1 million products !</span>
</div>
<div className={styles.login__form}>
<Image src="/profilelogo.svg" width={100} height={100} alt="not" />
<h3>Sign in</h3>
<p> Sign in and start shopping immediately !</p>
<form onSubmit={handleSubmit}>
<LoginInput
icon="user"
placeholder="Username"
onChange={handleChange}
type="text"
name="email"
value={user.email}
required={true}
/>
<LoginInput
icon="password"
placeholder="Password"
onChange={handleChange}
type="password"
name="password"
value={user.password}
required={true}
/>
{message.error && (
<div
className={styles.login__error}
onAnimationEnd={() => setMessage({ ...message, error: "" })}
key={message.error}
>
<p>{message.error}</p>
</div>
)}
{message.successMessage && (
<div
className={styles.login__success}
onAnimationEnd={() =>
setMessage({ ...message, successMessage: "" })
}
key={message.successMessage}
>
<p>{message.successMessage}</p>
</div>
)}
<div className={styles.links}>
<span>
<Link className={styles.links__span__a} href="/signup">
Create an account
</Link>
</span>
<span>
<Link
className={styles.links__span__a}
href="auth/forgot"
>
Forgot password
</Link>
</span>
</div>
<button className={styles.loginButton} type="submit">
{
loading ? <BarLoader
color="#fff"
height={5}
loading = {loading}
speedMultiplier={2}
width={100}
/>
: "Sign in"
}
</button>
<div className={styles.divider}>
<span>or</span>
</div>
{ providers &&
Object.values(providers).map((item, index) =>
item.id === "credentials" ? null : (
<div className={styles.login__social} key={index}>
<a onClick={() => signIn(item.id)}>
<Image
src={`/${item.id}.svg`}
width={20}
height={20}
alt={`${item.name}`}
/>
<span>Continue with {`${item.name}`}</span>
</a>
</div>
)
)}
</form>
</div>
</div>
</div>
</>
);
}
export default Signin;
export async function getServerSideProps(context) {
const { req, query } = context;
const providers = await getProviders();
const session = await getSession({ req });
const csrfToken = await getCsrfToken(context);
const { callbackUrl } = query;
let defaultCallbackUrl = "/";
if (callbackUrl) {
defaultCallbackUrl = callbackUrl;
}
if (session) {
return {
redirect: {
destination: defaultCallbackUrl,
},
};
}
return {
props: { providers, session, csrfToken, callbackUrl: defaultCallbackUrl },
};
}
pages/api/auth> [...nextauth].js
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
import GithubProvider from 'next-auth/providers/github'
import CredentialsProvider from "next-auth/providers/credentials";
import dotenv from 'dotenv'
import User from '../../../models/User'
import bcrypt from 'bcrypt'
import joi from 'joi'
import {connectDB, disconnect} from '../../../utils/db'
import {MongoDBAdapter} from '@next-auth/mongodb-adapter'
import clientPromise from './lib/mongodb'
import { getToken } from 'next-auth/jwt'
dotenv.config()
const loginSchema = joi.object({
email: joi.string().email().required(),
password: joi.string().min(6).required(),
});
export default NextAuth({
adapter : MongoDBAdapter(clientPromise),
providers: [
CredentialsProvider({
id: 'credentials',
name : 'Sign in',
credentials : {
email: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password", placeholder: "********" }
},
async authorize(credentials,req) {
try {
await connectDB()
const email = credentials.email
const password = credentials.password
console.log(email,password)
if (!email || !password) {
throw new Error('Please provide an email and password.');
}
const {error} = loginSchema.validate({email,password})
if (error) {
throw new Error(error.details[0].message);
}
const user = await User.findOne({email})
if (!user) {
throw new Error('Invalid email or password.');
}
const checkMatch = await bcrypt.compare(password, user.password)
if (!checkMatch) {
throw new Error('Invalid email or password.');
}
return user
} catch (error) {
throw new Error(error.message);
}
finally
{
await disconnect()
}
}
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret:process.env.GOOGLE_CLIENT_SECRET,
}),
GithubProvider({
clientId: "Iv1.2a94b24ea5010c98",
clientSecret: "71ff167e340484f06b9e03ff73bb64e4e667f8cb",
}),
],
pages: {
signIn: '/signin',
},
callbacks: {
async session({session, token}) {
let user = await User.findById(token.sub);
session.user.id = token.sub || user?._id?.toString();
session.user.role = user?.role || 'user';
return session;
}
},
session: {
strategy: 'jwt',
},
jwt: {
secret: process.env.JWT_SECRET,
},
secret: process.env.NEXTAUTH_SECRET,
})
错误信息:
.env文件: