部署Next.js 13到Vercel遇错误:encoding缺失与NextRouter未挂载
部署Next.js 13到Vercel的两个错误解决方案
错误1:Module not found: Can't resolve 'encoding'
问题分析
node-fetch依赖encoding包,但该包未被正确安装为生产依赖(你之前安装的是开发依赖)。
解决步骤
- 安装
encoding为生产依赖:
npm install encoding
- 如果安装后仍报错,在
next.config.js中添加webpack fallback配置:
/** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { config.resolve.fallback = { ...config.resolve.fallback, encoding: require.resolve("encoding"), }; return config; }, }; module.exports = nextConfig;
错误2:NextRouter was not mounted
问题分析
错误来自next-redux-wrapper的useWrappedStore,核心问题有两个:
- 你的
store.js中makeStore函数返回了同一个全局store实例,导致服务器端多请求状态冲突 next-redux-wrapper内部可能依赖旧版next/router,与Next.js 13 App Router不兼容;同时服务器端渲染时调用了依赖客户端Router的钩子
解决步骤
1. 修复store创建逻辑
修改store.js,确保每次调用makeStore都生成新的store实例:
import { combineReducers, configureStore } from "@reduxjs/toolkit"; import { createWrapper, HYDRATE } from "next-redux-wrapper"; import menuReducer from "./slices/menuSlice"; import vehicleReducer from "./slices/vehicleSlice"; import blogReducer from "./slices/blogSlice"; const combinedReducer = combineReducers({ menu: menuReducer, vehicle: vehicleReducer, blog: blogReducer, }); const reducer = (state, action) => { if (action.type === HYDRATE) { const nextState = { ...state, ...action.payload, }; return nextState; } else { return combinedReducer(state, action); } }; // 关键修改:每次调用生成新的store const makeStore = () => configureStore({ reducer }); export const wrapper = createWrapper(makeStore);
2. 升级next-redux-wrapper到兼容版本
安装最新版以支持App Router:
npm install next-redux-wrapper@latest
3. 调整Redux Provider的使用方式
- 创建专门的客户端Redux Provider组件(
app/providers.js):
"use client"; import { wrapper } from "@/store"; import { Provider } from "react-redux"; export function ReduxProvider({ children }) { const { store } = wrapper.useWrappedStore(); return <Provider store={store}>{children}</Provider>; }
- 修改
layout.js,用新的ReduxProvider包裹内容:
import "../styles/globals.css"; import { AuthProvider } from "./AuthProvider"; import { ReduxProvider } from "./providers"; function RootLayout({ children }) { return ( <html> <head /> <body className="max-w-7xl mx-auto"> <ReduxProvider> <AuthProvider>{children}</AuthProvider> </ReduxProvider> </body> </html> ); } export default RootLayout;
- 简化
AuthProvider.js,移除内部的Redux相关代码:
"use client"; import React from "react"; import { SessionProvider } from "next-auth/react"; import { ChakraProvider } from "@chakra-ui/react"; import { SkeletonTheme } from "react-loading-skeleton"; import NextTopLoader from "nextjs-toploader"; export function AuthProvider({ children, ...rest }) { return ( <SessionProvider> <ChakraProvider> <NextTopLoader color="#008080" showSpinner={false} /> {children} </ChakraProvider> </SessionProvider> ); }
备选方案(放弃next-redux-wrapper)
如果上述方案仍无效,可直接在客户端使用Redux,去掉next-redux-wrapper:
修改AuthProvider.js,直接创建客户端store:
"use client"; import React from "react"; import { SessionProvider } from "next-auth/react"; import { ChakraProvider } from "@chakra-ui/react"; import { SkeletonTheme } from "react-loading-skeleton"; import { configureStore } from "@reduxjs/toolkit"; import { Provider } from "react-redux"; import NextTopLoader from "nextjs-toploader"; import combinedReducer from "../store/combinedReducer"; // 导出你的合并reducer const store = configureStore({ reducer: combinedReducer }); export function AuthProvider({ children, ...rest }) { return ( <SessionProvider> <Provider store={store}> <ChakraProvider> <NextTopLoader color="#008080" showSpinner={false} /> {children} </ChakraProvider> </Provider> </SessionProvider> ); }
内容的提问来源于stack exchange,提问作者sanah_tech
相关产品推荐
相关产品推荐

