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

NextJS 12 + Expo生产构建报错:无法在模块外使用import语句

问题描述

在Next.js 12结合Expo构建生产版本时,出现以下错误:

info  - Creating an optimized production build
info  - Compiled successfully
info  - Collecting page data .node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

/Users/myName/Desktop/Projects/AppName/Frontend/Next/node_modules/expo-modules-core/build/index.js:1
import { DeviceEventEmitter } from 'react-native';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1084:15)
    at Module._compile (node:internal/modules/cjs/loader:1119:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)
    at Module.load (node:internal/modules/cjs/loader:1033:32)
    at Function.Module._load (node:internal/modules/cjs/loader:868:12)
    at Module.require (node:internal/modules/cjs/loader:1057:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.21968 (/Users/myName/Desktop/Projects/AppName/Frontend/Next/apps/next/.next/server/pages/_app.js:1232:18)
    at __webpack_require__ (/Users/myName/Desktop/Projects/AppName/Frontend/Next/apps/next/.next/server/webpack-runtime.js:25:43) {
  type: 'SyntaxError'
}

当前next.config.js配置:

/** @type {import('next').NextConfig} */

const { withNativebase } = require('@native-base/next-adapter');
const withImages = require('next-images');
const { withExpo } = require('@expo/next-adapter');
const withFonts = require('next-fonts');

module.exports = withNativebase({
  dependencies: [
    '@expo/next-adapter',
    'next-images',
    'next-fonts',
    'react-native-vector-icons',
    'react-native-vector-icons-for-web',
    'solito',
    'app',
    '@native-base/icons',
  ],
  plugins: [
    [withFonts, { projectRoot: __dirname }],
    withImages,
    [withExpo, { projectRoot: __dirname }],
  ],
  reactStrictMode: true,
  images: {
    domains: ['localhost'],
  },
  nextConfig: {
    typescript: {
      ignoreBuildErrors: true,
    },
    eslint: {
      ignoreDuringBuilds: true,
    },
    images: {
      disableStaticImages: true,
    },
    projectRoot: __dirname,
    reactStrictMode: true,
    webpack: (config, options) => {
      config.module.rules.map((rule) => {
        if (rule.test !== undefined && rule.test.source.includes('|svg|')) {
          rule.test = new RegExp(rule.test.source.replace('|svg|', '|'));
        }
      });

      config.module.rules.push({
        test: /\.ttf$/,
        loader: 'url-loader',
      });
      config.module.rules.push({
        test: /\.otf$/,
        loader: 'url-loader',
      });
      config.module.rules.push({
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      });
      config.module.rules.push({
        test: /\.mp4$/,
        use: [
          {
            loader: 'url-loader',
          },
        ],
      });
      config.module.rules.push({
        test: /\.html$/,
        loader: 'html-loader',
      });
      config.resolve.alias = {
        ...(config.resolve.alias || {}),
        'react-native$': 'react-native-web',
        '@expo/vector-icons': 'react-native-vector-icons',
      };
      config.resolve.extensions = [
        '.web.js',
        '.web.ts',
        '.web.tsx',
        ...config.resolve.extensions,
      ];

      return config;
    },
  },
});

已尝试使用withTM转译器,但导致字体及大量代码失效;另有相似配置项目可正常运行,目前无法定位问题。


解决方案

1. 核心原因定位

错误源于expo-modules-core使用ES模块语法,但Next.js服务端默认不转译node_modules内的包,服务端以CommonJS环境运行时无法识别import语句。

2. 具体修复步骤

(1)添加转译包配置

在nextConfig中添加transpilePackages,指定需要转译的Expo相关包:

nextConfig: {
  // ...其他原有配置
  transpilePackages: ['expo-modules-core', 'react-native'],
}

(2)调整插件加载顺序

将withExpo移至插件列表最前,确保Expo的配置优先生效:

plugins: [
  [withExpo, { projectRoot: __dirname }],
  [withFonts, { projectRoot: __dirname }],
  withImages,
],

(3)修复SVG规则冲突

替换原有的SVG规则修改逻辑,避免和其他插件的配置冲突:

// 替换原config.module.rules.map(...)部分代码
const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'));
if (fileLoaderRule) {
  fileLoaderRule.exclude = /\.svg$/;
}

(4)添加依赖到nativebase的dependencies列表

将expo-modules-core加入dependencies数组,确保nativebase适配器能正确识别:

dependencies: [
  // ...原有依赖
  'expo-modules-core',
],

3. 完整修改后的next.config.js

/** @type {import('next').NextConfig} */

const { withNativebase } = require('@native-base/next-adapter');
const withImages = require('next-images');
const { withExpo } = require('@expo/next-adapter');
const withFonts = require('next-fonts');

module.exports = withNativebase({
  dependencies: [
    '@expo/next-adapter',
    'next-images',
    'next-fonts',
    'react-native-vector-icons',
    'react-native-vector-icons-for-web',
    'solito',
    'app',
    '@native-base/icons',
    'expo-modules-core',
  ],
  plugins: [
    [withExpo, { projectRoot: __dirname }],
    [withFonts, { projectRoot: __dirname }],
    withImages,
  ],
  reactStrictMode: true,
  images: {
    domains: ['localhost'],
  },
  nextConfig: {
    typescript: {
      ignoreBuildErrors: true,
    },
    eslint: {
      ignoreDuringBuilds: true,
    },
    images: {
      disableStaticImages: true,
    },
    projectRoot: __dirname,
    reactStrictMode: true,
    transpilePackages: ['expo-modules-core', 'react-native'],
    webpack: (config, options) => {
      // 修复SVG规则冲突
      const fileLoaderRule = config.module.rules.find(rule => rule.test && rule.test.test('.svg'));
      if (fileLoaderRule) {
        fileLoaderRule.exclude = /\.svg$/;
      }

      config.module.rules.push({
        test: /\.ttf$/,
        loader: 'url-loader',
      });
      config.module.rules.push({
        test: /\.otf$/,
        loader: 'url-loader',
      });
      config.module.rules.push({
        test: /\.svg$/,
        use: ['@svgr/webpack'],
      });
      config.module.rules.push({
        test: /\.mp4$/,
        use: [
          {
            loader: 'url-loader',
          },
        ],
      });
      config.module.rules.push({
        test: /\.html$/,
        loader: 'html-loader',
      });
      config.resolve.alias = {
        ...(config.resolve.alias || {}),
        'react-native$': 'react-native-web',
        '@expo/vector-icons': 'react-native-vector-icons',
      };
      config.resolve.extensions = [
        '.web.js',
        '.web.ts',
        '.web.tsx',
        ...config.resolve.extensions,
      ];

      return config;
    },
  },
});

4. 额外排查建议

  • 对比正常运行项目的expo-modules-core、react-native-web版本,确保版本一致
  • 删除.next文件夹和node_modules,重新执行npm install和npm run build
  • 检查是否有其他未转译的ES模块依赖,如有可添加到transpilePackages中

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 21:37:02