Next.js导入encrypt-storage报ReferenceError: self is not defined如何解决
解决方案
问题根因
ReferenceError: self is not defined 报错是因为Next.js默认会在服务端执行模块代码,而encrypt-storage依赖浏览器环境的全局对象self/window,服务端运行时不存在该对象,因此直接在模块顶层导入、初始化就会触发报错。
修复步骤
1. 封装客户端侧才初始化的工具
新建utils/encryptStorage.js文件,仅在浏览器环境下初始化加密实例:
let encryptStorage = null; // 仅客户端环境执行初始化逻辑 if (typeof window !== 'undefined') { const { EncryptStorage } = require('encrypt-storage'); // 注意需要加new关键字调用构造函数,这也是原有代码的疏漏点 encryptStorage = new EncryptStorage('你的加密密钥', { storageType: 'localStorage' }); } export default encryptStorage;
2. 仅在客户端执行的逻辑中调用
所有读写操作都要放到客户端执行的生命周期中,禁止在服务端运行的代码(服务端组件、getServerSideProps、getStaticProps、组件顶层同步代码)中直接调用:
Next.js 13+ App Router 示例
// 标记为客户端组件 'use client'; import { useEffect, useState } from 'react'; import encryptStorage from '@/utils/encryptStorage'; export default function DemoPage() { const [userInfo, setUserInfo] = useState(null); useEffect(() => { // 写入数据 const userObj = { name: '测试用户', id: 1001 }; encryptStorage?.setItem('user', userObj); // 读取数据 const storedUser = encryptStorage?.getItem('user'); setUserInfo(storedUser); }, []); return <div>当前用户:{userInfo?.name}</div>; }
Next.js Pages Router 示例
import { useEffect, useState } from 'react'; import encryptStorage from '@/utils/encryptStorage'; export default function DemoPage() { const [userInfo, setUserInfo] = useState(null); useEffect(() => { const userObj = { name: '测试用户', id: 1001 }; encryptStorage?.setItem('user', userObj); const storedUser = encryptStorage?.getItem('user'); setUserInfo(storedUser); }, []); return <div>当前用户:{userInfo?.name}</div>; }
可选:webpack适配配置
如果上述方案还是有打包报错,可以在next.config.js中添加配置,服务端打包时排除该依赖:
/** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config, { isServer }) => { if (isServer) { config.externals.push('encrypt-storage'); } return config; } } module.exports = nextConfig;
注意事项
- 加密密钥不要硬编码在前端代码中,否则加密存储没有实际安全意义,敏感场景建议密钥从服务端动态下发。
- 所有调用
encryptStorage方法的位置都建议加可选链?.,避免服务端渲染阶段实例未初始化报错。
内容的提问来源于stack exchange,提问作者Tushar
相关产品推荐
相关产品推荐

