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

React Native转Web运行报错:Module parse failed 求助解决方案

问题

执行npm run web将React Native应用运行在Web端时,出现以下错误:

ERROR in ./App.js 8:4 Module parse failed: Unexpected token (8:4) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders | const App = () => { | return ( <> | | {/* @ ./index.web.js 1:261-277

按文档操作后仍出现该错误,项目配置文件如下:

webpack.config.js

const path = require('path');
const webpack = require('webpack');

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

// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
  // test: /\.(js)|(jsx)$/,
  test: /\.js$|jsx/,
  // Add every directory that needs to be compiled by Babel during the build.
  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,
      // The 'metro-react-native-babel-preset' preset is recommended to match React Native's packager
      presets: ['module:metro-react-native-babel-preset'],
      // Re-write paths to import only the modules needed by the app
      plugins: [
        'react-native-web',
        [
          'module-resolver',
          {
            alias: {
              '^react-native$': 'react-native-web',
            },
          },
        ],
      ],
    },
  },
};

// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png|svg)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
      esModule: false,
    },
  },
};

module.exports = {
  entry: [
    // load any web API polyfills
    // path.resolve(appDirectory, 'polyfills-web.js'),
    // your web-specific entry file
    path.resolve(appDirectory, 'index.web.js'),
  ],

  // configures where the build ends up
  output: {
    filename: 'bundle.web.js',
    path: path.resolve(appDirectory, 'dist'),
  },

  // ...the rest of your config

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

  resolve: {
    // This will only alias the exact import "react-native"
    alias: {
      'react-native$': 'react-native-web',
    },
    // If you're working on a multi-platform React Native app, web-specific
    // module implementations should be written in files using the extension
    // `.web.js`.
    extensions: ['.web.js', '.js', '.jsx'],
  },
};

App.js

import LogoImage from "./Atoms/LogoImage";
import react from React
import SignInButton from "./Atoms/SignInButton";
import { Button, TextInput, View } from "react-native";

const App = () => {
  return (
    <>
      <LogoImage />
      {/* <InputField />
      <InputField /> */}
      <SignInButton />
    </>
  );
};

// const InputField = () => {
//   return (
//   <View>
//     <TextInput 
//     style={{height: 40,

//       borderWidth: 1,
//       }}
//     />
//     <Button title="press"/>
//   </View>
// )}

export default App;

package.json

{
  "name": "AwesomeProject",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "web": "webpack serve -d source-map --mode development --config \"./web/webpack.config.js\" --color --hot",
    "build:web": "webpack --mode production --config \"./web/webpack.config.js\" --hot"
  },
  "dependencies": {
    "react": "18.1.0",
    "react-dom": "^18.2.0",
    "react-native": "0.70.6",
    "react-native-web": "^0.18.10"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^2.0.0",
    "ajv": "^7.2.4",
    "babel-jest": "^26.6.3",
    "babel-loader": "^9.1.0",
    "babel-plugin-module-resolver": "^4.1.0",
    "babel-plugin-react-native-web": "^0.18.10",
    "eslint": "^7.32.0",
    "jest": "^26.6.3",
    "metro-react-native-babel-preset": "0.72.3",
    "react-test-renderer": "18.1.0",
    "url-loader": "^4.1.1",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0",
    "webpack-dev-server": "^4.11.1",
    "webpack-merge": "^5.8.0"
  },
  "jest": {
    "preset": "react-native-web"
  }
}

babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
};

.flowconfig

[ignore]
; We fork some components by platform
.*/*[.]android.js

; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/

; Ignore polyfills
node_modules/react-native/Libraries/polyfills/.*

; Flow doesn't support platforms
.*/Libraries/Utilities/LoadingView.js

.*/node_modules/resolve/test/resolver/malformed_package_json/package\.json$

[untyped]
.*/node_modules/@react-native-community/cli/.*/.*

[include]

[libs]
node_modules/react-native/interface.js
node_modules/react-native/flow/

[options]
emoji=true

exact_by_default=true

format.bracket_spacing=false

module.file_ext=.js
module.file_ext=.json
module.file_ext=.ios.js

munge_underscores=true

module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'

suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FlowFixMeProps
suppress_type=$FlowFixMeState

# Alias the package name
module.name_mapper='^react-native$' -> 'react-native-web'

# Point flow to the 'module' field by default
module.system.node.main_field=module
module.system.node.main_field=main

[lints]
sketchy-null-number=warn
sketchy-null-mixed=warn
sketchy-number=warn
untyped-type-import=warn
nonstrict-import=warn
deprecated-type=warn
unsafe-getters-setters=warn
unnecessary-invariant=warn

[strict]
deprecated-type
nonstrict-import
sketchy-null
unclear-type
unsafe-getters-setters
untyped-import
untyped-type-import

[version]
^0.182.0
解决方案

该错误源于Webpack无法解析JSX语法,同时配置中存在几处需要修正的问题:

1. 修正Webpack的Babel Loader匹配规则

当前test: /\.js$|jsx/的正则写法错误,无法正确匹配.jsx文件,且会导致.js文件匹配逻辑异常。修改为正确的正则表达式,并确保根目录下的App.js被纳入Babel处理范围:

修改webpack.config.js中的babelLoaderConfiguration:

const babelLoaderConfiguration = {
  test: /\.(js|jsx)$/, // 修正正则表达式
  include: [
    path.resolve(appDirectory, 'index.web.js'),
    path.resolve(appDirectory, '.'), // 新增该行,确保根目录文件被处理
    path.resolve(appDirectory, 'src'),
    path.resolve(appDirectory, 'node_modules/react-native-uncompiled'),
  ],
  // 其余配置保持不变
};

2. 修复App.js中的React导入错误

App.js中React导入写法错误,导致React无法被正确识别,进而影响JSX解析:

// 错误写法
import react from React

// 修改为正确写法
import React from 'react'

3. 确保Babel配置支持JSX解析

为确保Babel能正确处理JSX语法,在babel.config.js中添加@babel/preset-react预设:

module.exports = {
  presets: [
    'module:metro-react-native-babel-preset',
    '@babel/preset-react' // 新增该预设
  ],
};

同时安装该依赖:

npm install --save-dev @babel/preset-react

4. 验证Webpack的resolve配置

确认resolve.extensions已包含.jsx,当前配置已满足要求:

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

完成以上修改后,重新执行npm run web即可正常编译运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:31:09