最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Shared package configuration used in monorepo with react and react native - Stack Overflow

programmeradmin0浏览0评论

I'm a bit desperate for help as I've been fighting with this for days now.

I have 2 different projects, the first one is a single React web app and the second is a monorepo that holds a React web app and a React Native app. I am trying to create a shared package where I can declare shared components and styles and reuse them in the different apps.

This is the tree of my shared package (file contents below):

├── package.json
├── rollup.config.js
├── src
│   ├── native
│   │   ├── Button.tsx
│   │   └── index.ts
│   ├── styles.ts
│   ├── types.ts
│   └── web
│       ├── Button.tsx
│       └── index.ts
├── tsconfig.json

And this is the directory tree of my monorepo (file contents below):

├── package.json
├── packages
│   ├── mobile
│       ├── babel.config.js
│       ├── metro.config.js
│       ├── package.json
│       ├── tsconfig.json
│       └── src
│           ├── components
│   ├── shared
│   │   ├── ...
│   └── web
│       ├── next.config.js
│       ├── package.json
│       ├── tsconfig.json
│       └── src
│           ├── components

I'm building the shared package using npm run build and then publishing the package locally using yalc publish. Then on the monorepo, in each of the apps (web and mobile) I run yalc add @custom-package/common-repo-fe.

When I run the web app I can render a page component that imports the Button from the shared package successfully by using import { Button } from '@custom-package/common-repo-fe/web';.

On the other hand, when I try to run the mobile app (iOS in this case), the page where the Button component is imported (using import { Button } from '@custom-package/common-repo-fe/native';) fails with the following error:

Syntax Error
@cutom-package/common-repo-fe/native could not be found within the project or in these directories: node_modules ../../node_modules
/Users/xuser/projects/frontend/custom-package-client/packages/ mobile/.yalc/@custom-package/common-repo-fe/native
Source
import { authApi } from '@custom-package/shared';
import { Button } from '@custom-package/common-repo-fe/native';

The contents of the files are as follows:

Shared package

  • tsconfig.json
{
  "compilerOptions": {
    "target": "es2018",
    "module": "esnext",
    "lib": ["dom", "esnext"],
    "moduleResolution": "node",
    "jsx": "react",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
  • rollup.config.js
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

const external = [
  'react', 
  'react-dom', 
  'react-native',
];

export default [
  // Web bundle
  {
    input: 'src/web/index.ts',
    output: {
      file: 'dist/web.js',
      format: 'esm',
      sourcemap: true,
    },
    external,
    plugins: [
      typescript({
        tsconfig: './tsconfig.json',
        declaration: true,
      }),
      resolve(),
      commonjs(),
    ]
  },
  // Native bundle (as CommonJS)
  {
    input: 'src/native/index.ts',
    output: {
      file: 'dist/native.js',
      format: 'cjs', // Critical for React Native
      sourcemap: true,
    },
    external,
    plugins: [
      typescript({
        tsconfig: './tsconfig.json',
        declaration: true,
      }),
      resolve(),
      commonjs(),
    ]
  }
];
  • package.json
{
  "name": "@custom-package/common-repo-fe",
  "version": "0.0.1",
  "type": "module",
  "main": "web.js",
  "exports": {
    "./web": "./web.js",
    "./native": "./native.js"
  },
  "files": [
    "dist",
    "web.js",
    "native.js"
  ],
  "scripts": {
    "build": "rollup -c",
    "watch-build": "rollup -c -w",
    "watch-push": "nodemon --watch dist --delay 0.5 --exec 'yalc push'",
    "dev": "concurrently \"npm run watch-build\" \"npm run watch-push\""
  },
  "peerDependencies": {
    "react": ">=18.2.0",
    "react-dom": ">=18.2.0"
  },
  "peerDependenciesMeta": {
    "react-dom": {
      "optional": true
    },
    "react-native": {
      "optional": true
    }
  },
  ...
}

monorepo mobile package

  • metro.config.js
const path = require('path');
const { getDefaultConfig } = require('@react-native/metro-config');

module.exports = (async () => {
  const config = await getDefaultConfig(__dirname);
  
  const yalcPath = path.resolve(__dirname, '.yalc/@custom-package/common-repo-fe');
  
  return {
    ...config,
    resolver: {
      ...config.resolver,
      extraNodeModules: {
        '@custom-package/common-repo-fe': yalcPath,
      },
      assetExts: [
        ...config.resolver.assetExts,
        'png',
        'jpg',
        'jpeg',
        'svg',
        'gif',
      ],
    },
    watchFolders: [
      ...(config.watchFolders || []),
      yalcPath,
    ],
  };
})();

If anybody is able to shed some light into why this would cause issues for the mobile app but not the web app I'd be extremely grateful! And let me know if you need any more context about my configuration if needed.

Thanks in advance.

发布评论

评论列表(0)

  1. 暂无评论