我一直在尝试让 SendGrid 与我的 React 应用程序一起工作。我已经创建了一个配置文件,我用它来通过 SignUp.jsx 中的注册表单发送我的电子邮件。目前我在客户端创建的 /utlis 文件夹中有 emailConfig。当我尝试运行我的应用程序时,我不断收到两条错误消息。
错误信息 1
./node_modules/@sendgrid/helpers/classes/attachment.js 中的错误 9:11-24
未找到模块:错误:无法解析“/Users/user/Developer”中的“fs” 文件/app/client/node_modules/@sendgrid/helpers/classes'
错误消息 2
./node_modules/@sendgrid/helpers/classes/attachment.js 中的错误 10:13-28
找不到模块:错误:无法解析“路径” '/用户/用户/开发者 文件/app/client/node_modules/@sendgrid/helpers/classes'
突破性变化:webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.
如果你想包含一个 polyfill,你需要:
- 添加后备 'resolve.fallback: { "path": require.resolve("path-browserify") }'
- install 'path-browserify' 如果你不想包含 polyfill,你可以使用这样的空模块:resolve.fallback: { "path": 假}
我是否应该将它放在我的 /server/utils 文件夹中,而不是 emailConfig.js 并创建某种系统链接,或者我缺少什么导致此消息。我最初尝试创建一个系统链接,但无法正常工作。
我已经在下面附上了我的文件夹结构,package.json(client)、package.json(sever)、SignUp.jsx 和 emailConfig.js
文件夹结构
emailConfig.js
package.json(客户端)
App
/client
/src
/components
/signup
/SignUp.jsx
/utils
/emailConfig.js
/sever
package.json(服务器)
"name": "app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@sendgrid/mail": "^7.7.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.3.3",
"emailjs-com": "^3.2.0",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"yup": "^1.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
SignUp.jsx
{
"name": "app-server",
"version": "1.0.0",
"description": "backhend of kinkbucket",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js",
"build": "react-scripts build",
"eject": "react-scripts eject"
},
"author": "Ainsley",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongoose": "^6.9.2"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
emailConfig.js
import React, { useState } from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import emailjs from "emailjs-com";
import emailConfig from "../../utils/emailConfig.js";
import "./signUp.css";
const validationSchema = Yup.object().shape({
username: Yup.string().required("Required"),
email: Yup.string().email("Invalid email").required("Required"),
password: Yup.string().required("Required"),
confirmPassword: Yup.string().oneOf(
[Yup.ref("password"), null],
"Passwords must match"
),
});
const SignUp = () => {
const [showPassword, setShowPassword] = useState(false);
const history = useNavigate();
const formik = useFormik({
initialValues: {
username: "",
email: "",
password: "",
confirmPassword: "",
},
validationSchema,
onSubmit: async (values) => {
try {
const response = await axios.post("/api/users/signup", values);
const userId = response.data._id;
const token = response.data.token;
// Send verification email
emailjs
.send(
emailConfig.SERVICE_ID,
emailConfig.TEMPLATE_ID,
{
to_name: values.username,
message: `Please click this link to verify your email address: https://YOUR_DOMAIN/verify/${userId}/${token}`,
to_email: values.email,
},
emailConfig.USER_ID
)
.then(
(result) => {
console.log(result.text);
},
(error) => {
console.log(error.text);
}
);
history.push("/");
} catch (err) {
console.log(err);
}
},
});
const { values, errors, touched, handleChange, handleBlur, handleSubmit } =
formik;
const handleSignUp = (e) => {
e.preventDefault();
handleSubmit();
};
return (
<div className="signup-container">
<form onSubmit={handleSubmit} className="signup-form">
<h2>Sign Up</h2>
<div className="form-control">
<label htmlFor="username">Username</label>
<input
type="text"
id="username"
name="username"
value={values.username}
onChange={handleChange}
onBlur={handleBlur}
/>
{touched.username && errors.username && (
<div className="error">{errors.username}</div>
)}
</div>
<div className="form-control">
<label htmlFor="email">Email</label>
<input
type="email"
id="email"
name="email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
{touched.email && errors.email && (
<div className="error">{errors.email}</div>
)}
</div>
<div className="form-control password-input">
<label htmlFor="password">Password</label>
<input
type={showPassword ? "text" : "password"}
id="password"
name="password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
/>
<button
type="button"
className="toggle-password"
onClick={() => setShowPassword(!showPassword)}
>
<FontAwesomeIcon icon={showPassword ? faEyeSlash : faEye} />
</button>
{touched.password && errors.password && (
<div className="error">{errors.password}</div>
)}
</div>
<div className="form-control">
<label htmlFor="confirmPassword">Confirm Password</label>
<input
type="password"
id="confirmPassword"
name="confirmPassword"
value={values.confirmPassword}
onChange={handleChange}
onBlur={handleBlur}
/>
{touched.confirmPassword && errors.confirmPassword && (
<div className="error">{errors.confirmPassword}</div>
)}
</div>
<div className="form-control">
<input type="checkbox" id="terms" name="terms" />
<label htmlFor="terms">I agree to the terms and conditions</label>
</div>
<div className="form-actions">
<button
type="submit"
className="signup-button"
disabled={!formik.isValid}
onClick={handleSignUp}
>
Sign Up
</button>
</div>
</form>
</div>
);
};
export default SignUp;