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

Yarn Monorepo中如何在Expo应用里导入TypeScript函数

问题描述

用Yarn Workspaces搭建了monorepo,其中包含一个TypeScript编写的组件及工具函数包ui-base,希望在裸Expo应用中直接导入使用,但系统会尝试从node_modules导入该包,同时报TypeScript语法解析错误,需要调整配置实现直接从项目源码导入。

错误信息

ERROR in ../../node_modules/ui-base/src/utils/sizeHelper.ts 3:17
Module parse failed: Unexpected token (3:17)
File was processed with these loaders:
 * ../../node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| import { Dimensions } from "react-native";
| 
> const vh = (value: number) => (Dimensions.get("window").height / 100) * value;
| 
| const vw = (value: number) => (Dimensions.get("window").width / 100) * value;

web compiled with 6 errors

现有配置文件

根目录 package.json

{
  "name": "omnijs",
  "version": "0.1.0",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "packageManager": "yarn@3.5.0"
}

根目录 tsconfig.json

{
    "compilerOptions": {
        "strictNullChecks": true,
        "noUncheckedIndexedAccess": true,
        "paths": {
            "ui-base/*": ["./packages/ui-base/*"]
        }
    },
    "extends": "expo/tsconfig.base"
}

ui-base 包的 package.json

{
    "name": "ui-base",
    "version": "1.0.0",
    "description": "",
    "main": "./src/index.ts",
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
        "@tsconfig/recommended": "^1.0.1",
        "babel-preset-expo": "~9.5.0",
        "prettier": "3.0.0",
        "react": "18.2.0",
        "react-native": "0.72.3",
        "react-native-reanimated": "^3.4.1",
        "styled-components": "5.3.11",
        "tsup": "^7.2.0"
    }
}

Expo应用的 tsconfig.json

{
  "extends": "../../tsconfig"
}

Expo应用的 package.json

{
  "name": "@omnijs/flix",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "expo start --dev-client",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@tanstack/react-query": "^4.32.6",
    "@tanstack/router": "^0.0.1-beta.53",
    "axios": "^1.4.0",
    "expo": "~49.0.5",
    "expo-splash-screen": "~0.20.4",
    "expo-status-bar": "~1.6.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.72.3",
    "react-native-web": "~0.19.6",
    "ui-base": "*",
    "zustand": "^4.4.1"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-typescript": "^7.22.5",
    "@expo/webpack-config": "^18.1.2",
    "@types/expo": "^33.0.1",
    "@types/react": "^18.2.18",
    "@types/react-native": "^0.72.2",
    "prettier": "^3.0.1",
    "typescript": "^5.1.6"
  },
  "private": true
}

Expo应用的 metro.config.js

// Learn more https://docs.expo.dev/guides/monorepos
// Learn more https://docs.expo.io/guides/customizing-metro
/**
 * @type {import('expo/metro-config')}
 */
const {getDefaultConfig} = require('expo/metro-config');
const path = require('path');

// Find the project and workspace directories
const projectRoot = __dirname;
// This can be replaced with `find-yarn-workspace-root`
const workspaceRoot = path.resolve(projectRoot, '../..');

const config = getDefaultConfig(projectRoot);

// 1. Watch all files within the monorepo
config.watchFolders = [workspaceRoot];
// 2. Let Metro know where to resolve packages and in what order
config.resolver.nodeModulesPaths = [
  path.resolve(projectRoot, 'node_modules'),
  path.resolve(workspaceRoot, 'node_modules'),
];
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
config.resolver.disableHierarchicalLookup = true;

module.exports = config;
解决方案

问题核心是Expo Web使用的Webpack未将ui-base识别为需要编译的源码,而是从node_modules加载了未转译的TypeScript文件,导致解析失败。需通过以下配置调整解决:

1. 配置Webpack编译本地包源码

在Expo项目根目录创建webpack.config.js,让Webpack处理ui-base的TypeScript文件:

const createExpoWebpackConfigAsync = require('@expo/webpack-config');

module.exports = async function (env, argv) {
  const config = await createExpoWebpackConfigAsync(env, argv);
  
  // 添加规则,编译ui-base的TS/TSX文件
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    include: /packages\/ui-base/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: ['babel-preset-expo'],
        },
      },
      'ts-loader',
    ],
  });

  // 让Webpack直接解析ui-base的源码目录,跳过node_modules
  config.resolve.alias['ui-base'] = require('path').resolve(__dirname, '../../packages/ui-base/src');

  return config;
};

2. 完善ui-base包的配置

  • 在ui-base的package.json中添加类型定义字段:
    "types": "./src/index.ts",
    
  • 创建packages/ui-base/tsconfig.json,规范TypeScript编译配置:
    {
      "extends": "@tsconfig/recommended/tsconfig.json",
      "compilerOptions": {
        "jsx": "react-native",
        "module": "ESNext",
        "target": "ESNext",
        "moduleResolution": "node",
        "esModuleInterop": true,
        "skipLibCheck": true,
        "strict": true,
        "outDir": "./dist"
      },
      "include": ["src/**/*"],
      "exclude": ["node_modules"]
    }
    

3. 优化Metro配置(适配Native端)

在现有metro.config.js中添加TS/TSX文件扩展名支持:

// 在module.exports前添加
config.resolver.sourceExts.push('ts', 'tsx');

4. 重启服务并验证

执行以下命令重新安装依赖并清除缓存启动服务:

yarn install
yarn start --web --clear

内容的提问来源于stack exchange,提问作者Thiago Lino Gomes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:20:55