[特殊字符] Next.js Turbo 模式不支持 @svgr/webpack 的原因与解决方案

🧩 背景介绍

在 Next.js 项目中,我们经常希望通过 @svgr/webpack.svg 文件作为 React 组件 引入,像这样使用:

tsx


CopyEdit
import Logo from '@/assets/logo.svg'

export default function Header() {
  return <Logo width={120} />
}

这在传统 Webpack 模式下非常常见,但在 Next.js 15 的 Turbo 模式中却无法使用,原因如下:


❌ 问题说明

现象:

在启用 Turbo 模式后(next build --turbo),你会发现:

  • 无法识别 @svgr/webpack
  • 无法在 next.config.js 中添加 webpack() 自定义配置
  • 报错如:
vbnet


CopyEdit
TypeError: config.module.rules.push is not a function

⚠️ 原因解析:Turbo 模式基于 Rust 构建工具 Turbopack

项目非 Turbo 模式✅ Turbo 模式(Turbopack)
构建引擎Webpack + BabelTurbopack(Rust 编写,Vercel 出品)
插件机制支持 Webpack 插件和 loader暂不支持 Webpack 插件或 loader
构建配置入口支持自定义 webpack(config)不支持自定义 Webpack 配置
插件兼容性@svgr/webpack
等广泛支持
不兼容所有 Webpack 插件

总结:Turbo 模式是全新构建系统,完全抛弃 Webpack 架构,因此所有基于 Webpack 的插件(如 @svgr/webpack)都不生效。


✅ 解决方案

根据你的需求,这里有 3 种可选解决方案:


✅ 方案一:切换为非 Turbo 模式(推荐)

如果你需要 @svgr/webpack,请禁用 Turbo 模式,恢复传统构建方式。

📌 步骤:
  1. 编辑 next.config.js
js


CopyEdit
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/i,
      issuer: /\.[jt]sx?$/,
      use: ['@svgr/webpack'],
    })
    return config
  },
}

module.exports = nextConfig
  1. 添加 svg.d.ts(如果使用 TypeScript):
ts


CopyEdit
// types/svg.d.ts
declare module '*.svg' {
  import * as React from 'react'
  const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
  export default ReactComponent
}
  1. 安装依赖:
bash


CopyEdit
npm install --save-dev @svgr/webpack
  1. 使用方式:
tsx


CopyEdit
import Logo from '@/assets/logo.svg'
export default function Page() {
  return <Logo width={100} />
}
  1. 构建时 **不要加 ****--turbo**
bash


CopyEdit
npm run build         ✅ 正确
npm run build --turbo ❌ 错误

🚧 方案二:使用 <img src="/xxx.svg" /> 代替(兼容 Turbo 模式)

如果你愿意不将 .svg 当作组件处理,可以将 SVG 放在 public/ 文件夹下,用原生 <img /> 标签引入:

tsx


CopyEdit
export default function Page() {
  return <img src="/logo.svg" alt="Logo" width={100} />
}

适合简单展示场景,但不支持 fill/stroke 等 React 属性控制。


🛠️ 方案三:封装 SVG 动态加载组件(仅适合部分情况)

你可以封装一个 SvgIcon 组件,通过 require 加载 SVG 文件:

tsx


CopyEdit
// components/SvgIcon.tsx
'use client'
export function SvgIcon({ name, ...props }: { name: string } & React.SVGProps<SVGSVGElement>) {
  const Icon = require(`../public/${name}.svg`).default
  return <Icon {...props} />
}

// 用法
<SvgIcon name="logo" width={100} />

⚠️ 缺点:本质还是在使用 public/ 下文件,不是真正组件形式,存在兼容性问题。


📌 总结推荐

需求推荐方案
需要使用 SVG 组件(如控制颜色)✅ 非 Turbo 模式
简单展示 SVG 图标<img src="/..." />
想尝试 Turbo 模式暂时避免使用 @svgr/webpack
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值