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

React Native Web集成react-native-vector-icons时Web构建报错

react-native-web 引入 react-native-vector-icons 构建报JSX解析错误

问题描述

基于react-native + react-native-web开发跨端应用,按照react-native-vector-icons官方文档指引引入依赖后,Web端构建抛出如下错误:

ERROR in ./node_modules/react-native-vector-icons/lib/create-icon-set.js 91:8
Module parse failed: Unexpected token (91:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
| 
|       return (
>         <Text selectable={false} {...props}>
|           {glyph}
|           {children}
 @ ./node_modules/react-native-vector-icons/FontAwesome.js 6:0-50 9:16-29
 @ ./src/App.js 1:1549-1597
 @ ./index.web.js 1:261-281

当前webpack.config.js配置如下:

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const appDirectory = path.resolve(__dirname, '../')

const babelLoaderConfiguration = {
  test: /\.(js)|(jsx)$/,
  include: [
    path.resolve(appDirectory, 'index.web.js'),
    path.resolve(appDirectory, 'src'),
    path.resolve(appDirectory, 'node_modules/react-native-uncompiled'),
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [
        'react-native-web',
        [
          'module-resolver',
          {
            alias: {
              '^react-native$': 'react-native-web',
            },
          },
        ],
      ],
    },
  },
}

const HtmlWebpackPluginConfig = {
  filename: 'index.html',
  template: path.resolve(appDirectory, 'index.html'),
}

const copyWebpackPluginConfig = {
  patterns: [
    {
      from: path.resolve(appDirectory, 'assets/fonts/'),
      to: path.resolve(appDirectory, 'public/assets/fonts'),
      noErrorOnMissing: true,
    },
    {
      from: path.resolve(appDirectory, 'assets/images/'),
      to: path.resolve(appDirectory, 'public/assets/images'),
      noErrorOnMissing: true,
    },
  ],
}

const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png|svg)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
      esModule: false,
    },
  },
}

const iconFontLoaderConfiguration = {
  test: /\.ttf$/,
  loader: 'url-loader',
  include: path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
}

module.exports = {
  entry: [path.resolve(appDirectory, 'index.web.js')],

  output: {
    filename: 'bundle.[contenthash].web.js',
    path: path.resolve(appDirectory, 'public'),
  },

  module: {
    rules: [
      babelLoaderConfiguration,
      imageLoaderConfiguration,
      iconFontLoaderConfiguration,
    ],
  },

  devServer: {
    host: '0.0.0.0',
  },

  plugins: [
    new HtmlWebpackPlugin(HtmlWebpackPluginConfig),
    new CopyWebpackPlugin(copyWebpackPluginConfig),
  ],

  resolve: {
    alias: {
      'react-native$': 'react-native-web',
      '@api': path.resolve(appDirectory, 'src/api/'),
      '@entities': path.resolve(appDirectory, 'src/entities/'),
      '@utils': path.resolve(appDirectory, 'src/utils/'),
      '@components': path.resolve(appDirectory, 'src/components/'),
      '@theme': path.resolve(appDirectory, 'src/theme/'),
      '@constants': path.resolve(appDirectory, 'src/constants/'),
      '@screens': path.resolve(appDirectory, 'src/screens'),
    },

    extensions: ['.web.js', '.js', '.jsx'],
  },
}

已尝试将字体配置中的url-loader替换为file-loader、ttf-loader,报错完全一致,问题未解决。

根因分析

报错核心原因是babel-loader未覆盖react-native-vector-icons包内的JS/JSX文件:

  • 当前babel-loader的include配置仅包含业务源码、入口文件、react-native-uncompiled三个路径,没有把react-native-vector-icons纳入转译范围
  • react-native-vector-icons的源码中包含JSX语法,webpack拿到未转译的JSX代码时无法识别,直接抛出语法解析错误
  • 替换字体loader属于无效排查:字体loader仅负责处理.ttf格式的字体文件,和JS/JSX代码转译完全无关,自然无法解决该报错

解决方案

修改babelLoaderConfiguration配置,做两处调整:

  1. 修正test正则的写法,精准匹配.js、.jsx后缀文件
  2. 在include数组中新增react-native-vector-icons的包路径,让babel-loader转译该包内的代码

修改后的babelLoaderConfiguration配置如下:

const babelLoaderConfiguration = {
  // 修正正则写法
  test: /\.(js|jsx)$/,
  include: [
    path.resolve(appDirectory, 'index.web.js'),
    path.resolve(appDirectory, 'src'),
    path.resolve(appDirectory, 'node_modules/react-native-uncompiled'),
    // 新增图标库路径
    path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [
        'react-native-web',
        [
          'module-resolver',
          {
            alias: {
              '^react-native$': 'react-native-web',
            },
          },
        ],
      ],
    },
  },
}

补充校验:原有iconFontLoaderConfiguration配置已正确匹配.ttf文件且覆盖了图标库路径,无需额外修改;配置修改完成后重启webpack构建服务,报错即可消除。如果后续出现图标字体404问题,再检查静态资源拷贝规则和字体引用路径即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:54:24