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配置,做两处调整:
- 修正test正则的写法,精准匹配.js、.jsx后缀文件
- 在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
相关产品推荐
相关产品推荐

