Next.js项目使用mysql2时出现net和tls模块找不到的问题
问题描述
基于Node.js开发Next.js(12.2.2版本)项目,安装mysql2包后,Vercel部署无异常,但本地访问contacts-section.jsx页面时,出现无法解析net和tls模块的错误。已尝试删除重装node_modules、替换mysql2为mysql包,问题仍未解决。
数据库连接代码(database/index.js)
const mysql = require('mysql2') const pool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DBNAME, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); pool.getConnection((err, conn) => { if (err) console.log(err) console.log("Connected successfully") }) module.exports = pool.promise()
页面组件代码(contacts-section.jsx)
import Link from 'next/link'; import React, { useEffect, useState } from 'react'; import ContactForm from './contact-form'; import pool from '../../database/index' const ContactsSection = () => { const [row, setRow] = useState({}); useEffect(() => { const fetchData = async () => { try { const [rows, fields] = await pool.query("SELECT * FROM company"); setRow(rows[0]); // Sadece bir satır alıyorsanız } catch (error) { console.error('Error fetching data:', error); } }; fetchData(); }, []); return ( <section className="contact__area pt-80 pb-80"> <div className="container"> <div className="row wow fadeInUp" data-wow-delay=".3s"> <div className="col-lg-6"> <div className="contact__info-wrapper mb-30"> <div className="section__title-one mb-20"> <span>{"// Bize Ulaşın"}</span> <h2>Temasa Geç</h2> </div> <div className="contact__info-item"> <div className="contact__info-icon"> <i className="fa-solid fa-comment"></i> </div> <div className="contact__info-content"> <span>Dilediğiniz Zaman Arayın</span> <h5><a href="tel:05325470421">{row.phone}</a></h5> </div> </div> <div className="contact__info-item"> <div className="contact__info-icon"> <i className="fa-solid fa-envelope-open"></i> </div> <div className="contact__info-content"> <span>Email Gönder</span> <h5><a href="mailto:info@bursateknikhizmet.com">info@bursateknikhizmet.com</a></h5> </div> </div> <div className="contact__info-item"> <div className="contact__info-icon"> <i className="fa-solid fa-location-arrow"></i> </div> <div className="contact__info-content"> <span>Bizi Ziyaret Et</span> <h5><Link href="https://www.google.com/maps/@23.8272409,90.3665795,11z?hl=en" ><div >Demirtaş Cumhuriyet, 204. Sk. D:No.6, 16245 Osmangazi/Bursa</div></Link></h5> </div> </div> </div> </div> <div className="col-lg-6"> <ContactForm /> </div> </div> </div> </section> ); }; export default ContactsSection;
错误信息
./node_modules/mysql2/lib/connection.js:18:0 Module not found: Can't resolve 'net' and 'tls' Import trace for requested module: ./node_modules/mysql2/index.js ./database/index.js ./components/contact/contacts-section.jsx ./components/contact/index.jsx ./pages/iletisim.jsx https://nextjs.org/docs/messages/module-not-found
package.json配置
{ "name": "gardomia", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@popperjs/core": "^2.11.5", "@reduxjs/toolkit": "^1.8.3", "bootstrap": "^5.1.3", "formik": "^2.2.9", "mysql2": "^3.7.1", "next": "^12.2.2", "now": "^21.0.1", "react": "18.2.0", "react-countup": "^6.3.0", "react-dom": "18.2.0", "react-intersection-observer": "^9.4.0", "react-paginate": "^8.1.3", "react-redux": "^8.0.2", "react-slick": "^0.29.0", "react-toastify": "^9.0.7", "redux-persist": "^6.0.0", "swiper": "^8.3.2", "yup": "^0.32.11" }, "devDependencies": { "@vercel/next": "^4.1.0", "eslint": "8.20.0", "eslint-config-next": "12.2.2", "sass": "^1.70.0" } }
解决方案
问题核心是:mysql2依赖Node.js核心模块net和tls,这些模块仅在Node.js环境存在,浏览器环境不支持。你直接在客户端组件中导入数据库连接,Next.js编译客户端代码时会尝试打包这些专属模块,导致报错。Vercel部署正常是因为生产环境自动将数据库逻辑隔离到服务端,但本地开发编译逻辑更严格。
1. 创建API路由处理数据库请求
在pages/api目录下新建company-info.js,把数据库查询逻辑移到这里(API路由默认运行在服务端):
import pool from '../../database/index'; export default async function handler(req, res) { if (req.method === 'GET') { try { const [rows] = await pool.query("SELECT * FROM company"); res.status(200).json(rows[0]); } catch (error) { console.error('数据库查询错误:', error); res.status(500).json({ error: '获取数据失败' }); } } else { res.setHeader('Allow', ['GET']); res.status(405).end(`Method ${req.method} Not Allowed`); } }
2. 修改客户端组件,通过API获取数据
修改contacts-section.jsx,移除直接导入的pool,改用fetch调用API路由:
import Link from 'next/link'; import React, { useEffect, useState } from 'react'; import ContactForm from './contact-form'; const ContactsSection = () => { const [row, setRow] = useState({}); useEffect(() => { const fetchData = async () => { try { const response = await fetch('/api/company-info'); if (!response.ok) throw new Error('请求失败'); const data = await response.json(); setRow(data); } catch (error) { console.error('获取数据失败:', error); } }; fetchData(); }, []); // 原渲染代码保持不变 }; export default ContactsSection;
3. 本地验证
删除缓存文件后重新安装依赖并启动:
rm -rf node_modules .next npm install npm run dev
可选方案:用服务端渲染获取数据
如果不需要客户端动态请求,也可以在页面的getServerSideProps中直接查询数据库,把数据传给组件:
// pages/iletisim.jsx import ContactsSection from '../components/contact/contacts-section'; import pool from '../database/index'; export async function getServerSideProps() { try { const [rows] = await pool.query("SELECT * FROM company"); return { props: { companyInfo: rows[0] } }; } catch (error) { console.error('查询失败:', error); return { props: { companyInfo: {} } }; } } export default function Iletisim({ companyInfo }) { return <ContactsSection companyInfo={companyInfo} />; }
然后修改ContactsSection组件,直接使用props中的companyInfo,无需在useEffect中请求API。
内容的提问来源于stack exchange,提问作者Yunus Bilecen
相关产品推荐
相关产品推荐

