You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vite开发复用组件时Next.js Link报push相关TypeError的问题

问题描述

发布用Vite开发的可复用React组件后,复用时报错:

TypeError: Cannot read properties of null (reading 'push')

组件代码:

import React from "react";
import Link from "next/link";

const ShowText = ({title})=>{
    return(
        <Link href="/blog">{title}</Link>
    )
}

export default ShowText

组件仅依赖Next.js的Link组件,以下是相关配置:

package.json

{
  "name": "my-component-name",
  "version": "0.0.5",
  "description": "",
  "license": "MIT",
  "author": "",
  "keywords": [],
  "files": [
    "dist",
    "README.md"
  ],
  "main": "./dist/my-component.umd.js",
  "module": "./dist/my-component.es.js",
  "exports": {
    ".": {
      "import": "./dist/my-component.es.js",
      "require": "./dist/my-component.umd.js"
    }
  },
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "test": "vitest run",
    "watch": "vitest",
    "coverage": "vitest run --coverage"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "eslintConfig": {
    "env": {
      "browser": true,
      "node": true,
      "es2020": true
    },
    "extends": [
      "eslint:recommended",
      "plugin:react/recommended"
    ],
    "parserOptions": {
      "sourceType": "module"
    }
  },
  "devDependencies": {
    "@testing-library/dom": "^8.16.0",
    "@testing-library/react": "^13.3.0",
    "@vitejs/plugin-react": "^2.0.0",
    "c8": "^7.12.0",
    "eslint-plugin-react": "^7.30.1",
    "jsdom": "^20.0.0",
    "next": "12.1.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-test-renderer": "^18.2.0",
    "vite": "^3.0.3",
    "eslint": "8.17.0",
    "eslint-config-next": "12.1.6",
    "vitest": "^0.19.1"
  }
}

vite.config.js

import path from 'path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/lib/index.jsx'),
      name: 'my-component-mohammad',
      fileName: (format) => `my-component.${format}.js`
    },
    rollupOptions: {
      external: ['react', 'react-dom','next'],
      output: {
        globals: {
          react: 'React'
        }
      }
    }
  },
  plugins: [react()]
})
问题分析

核心原因是Next.js的Link组件强依赖Next.js的路由上下文(Router实例),当前配置存在两个关键问题:

  1. next被标记为external,意味着组件不会打包Next.js代码,完全依赖使用组件的项目提供Next.js环境。如果使用组件的项目不是Next.js项目,或者Next.js路由上下文未正确初始化,Link找不到Router实例就会抛出Cannot read 'push' of null错误。
  2. package.json中next仅在devDependencies里,发布后不会被安装,且未声明peerDependencies告知使用者需要手动安装Next.js,导致依赖缺失或版本不兼容。
修复方案

根据组件的使用场景,有两种修复方式:

方式一:让组件兼容非Next.js项目

修改组件,允许使用者传入自定义链接组件,不再强依赖Next.js的Link:

import React from "react";

const ShowText = ({ title, LinkComponent = 'a' }) => {
    return (
        <LinkComponent href="/blog">{title}</LinkComponent>
    )
}

export default ShowText

使用时,Next.js项目可以传入next/link:

import ShowText from 'my-component-name';
import Link from 'next/link';

<ShowText title="Blog" LinkComponent={Link} />

非Next.js项目直接使用默认的a标签即可。

方式二:组件仅针对Next.js项目使用

如果组件只打算在Next.js项目中复用,需要调整配置确保依赖正确:

  1. 在package.json中添加peerDependencies,声明对Next.js和React的版本要求,让使用者明确需要安装的依赖:
"peerDependencies": {
  "next": "^12.0.0 || ^13.0.0",
  "react": "^17.0.0 || ^18.0.0",
  "react-dom": "^17.0.0 || ^18.0.0"
}
  1. 保留vite.config.js中的external: ['react', 'react-dom','next']配置,因为peerDependencies的包由使用者项目提供,不需要打包进组件。
  2. 确保使用者的Next.js项目中_app.js/_app.tsx保留了默认路由上下文(默认Next.js项目已包含,自定义_app时不要移除相关Provider)。

内容的提问来源于stack exchange,提问作者Mohammad Miras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 13:54:37