如何创建新的reactjs和react-native项目并组织源代码存储库?

时间:2019-10-18 07:48:16

标签: reactjs react-native

我们可以使用以下CLI命令创建一个新的React-Native项目:

  

react-native init AwesomeProject

我们可以对create a new ReactJS project使用npx:

  

npx create-react-app my-app

如果我想使用monorepo在React-Native和ReactJS之间共享代码怎么办? (除了UI渲染代码,还要共享它们)

选项:

1)创建一个新的React-Native项目并手动导入ReactJs文件和文件夹? (不确定如何操作,例如如何管理package.json和node_modules)

2)创建一个新的ReactJS项目并手动导入React-Native文件和文件夹? (不确定如何操作,例如如何管理package.json和node_modules)

3)使用3个仓库(一个用于react-native,一个用于reactjs web,一个用于共享代码),我们将分别在React-Native repo和ReactJs repo中将共享代码作为npm包导入。 -想要使用这种方法,但是由于客户端的限制,我无法上传任何npm软件包,甚至是私有软件包。

还有其他更好/更常见的建议吗?

更新:

根据this tutorial,我们可以创建自己的本地npm软件包。但是,如果软件包已更新(例如,如果我们更改了一些redux代码),则需要每次运行“ npm pack”和“ npm install ../package-name-0.0.0.tgz”。这将很耗时。这是更新本地软件包的正确方法吗?

3 个答案:

答案 0 :(得分:0)

您应该结帐Learna

从具有

的根文件夹开始
/main (root directory)
/main/native (react-native project)
/main/state  (possibly redux or mobx) 
/main/web    (create-react-app) 
/main/VR     (in case you want to consume state here) 

现在,使用此结构,您可以维护一个monorepo,并使您的状态逻辑分离,并使用该状态逻辑的多个UI。

答案 1 :(得分:0)

您可以阅读有关Share React Native components to multiple projects的文章,我建议了3种在项目之间共享代码的方式。

我的案子几乎和你的一样。我有一个 React Native项目,一个 ReactJS Web应用,一个共享库和服务器代码,它们是 Google Cloud Firebase Functions < / em>用于nodejs。我使用了 Babel Metro Bundler 的第三种方法。

方法1:为npm软件包安装Git

我们可以为我们的Library目录创建一个git repo,然后让NPM直接从该repo安装它。可以,但是每次对Library进行更改后,我们都必须同步(提交/推送)git repos,这对于处理本地项目来说不太实际。有关更多详细信息,请检查此Q / A How to install an npm package from GitHub directly?

方法2:Git submodules

Git子模块是在项目中共享代码的一种非常好的方法,它需要经常更改。我一直在寻找这种解决方案,当我看到使用这种方法的潜力时,我感到很兴奋,但是后来我以为我对git子模块不是很熟悉,当然也不想做任何事情并弄乱git repos和然后很难解决git问题。如果您熟悉使用git子模块,那么这就是方法。

方法3(Babel,Metro):将.babelrc模块resolver插件用于React,并将Metro Bundler解析器用于React Native

我们可以使用module-resolver包来配置目录别名。我们通常为RN和ReactJS创建两个项目,并初始化firebase函数项目,而不必将Library初始化为nodejs项目:

目录结构:

MyProject-RNApp\
MyProject-ReactJSApp\
MyProject-Backend\
MyProject-Library\

每个使用的软件包,必须为将要使用的项目安装。例如,如果我们的库中有一个使用validator的通用函数,那么对于每个使用它的节点项目,我们都必须npm install打包。

为所有Babel项目配置module-resolver

首先在.babelrc内,我们为每个目录定义别名。在这里,我们可以添加RN应用程序根目录之外的目录:

{
  "presets": ["module:metro-react-native-babel-preset"],
  "env": {
    "production": {
      "plugins": ["transform-remove-console", "react-native-paper/babel"]
    }
  },
  "plugins": [
    "@babel/plugin-transform-runtime",
    [
      "module-resolver",
      {
        "root": ["./"],
        "extensions": [".js", ".jsx", ".ts", ".tsx"],
        "stripExtensions": [".js", ".jsx", ".ts", ".tsx"],
        "alias": {
          "@components": "./components",
          "@screens": "./screens",
          "@utils": "./utils",
          "@data": "./data",
          "@assets": "./assets",
          "@app": "./",
          "@myprojectlib": "../MyProject-Library",
          "@myprojecti18n": "../MyProject-Library/i18n/rn",
          "@myprojectbackend": "../MyProject-Backend/firebase/functions",
        }
      }
    ]
  ]
}

在这里,您必须小心路径,但是相对路径也可以正常工作。另外,在配置 RN 项目时,您不必为每个软件包添加别名,因为您将在下面使用 Metro Bundler 配置进行此操作。您只需要为 ReachJS Backend Babel项目创建包别名:

{
  "plugins": [
    [
      "module-resolver",
      {
        "root": "../",
        "alias": {
          "@app": "./resources/js/app",
          "@graphics": "./resources/js/app/graphics",
          "@styles": "./resources/js/app/styles",
          "@components": "./resources/js/app/components",
          "@screens": "./resources/js/app/screens",
          "@panels": "./resources/js/app/panels",
          "@stores": "./resources/js/app/stores",
          "@utils": "./resources/js/app/utils",
          "@dialogs": "./resources/js/app/dialogs",
          "@data": "./resources/js/app/data",
          "@myprojectlib": process.env.MYPROJECT_LIBRARY_PATH,
          "@myprojectbrain": process.env.MYPROJECT_BRAIN_PATH,
          "@myprojecti18n": `${process.env.MYPROJECT_LIBRARY_PATH}/i18n`,

          // Add module paths for external myproject, else it wont work!

          "react": "./node_modules/react",
          "react-flag-icon-css": "./node_modules/react-flag-icon-css",
          "react-hot-loader": "./node_modules/react-hot-loader",
          "react-localization": "./node_modules/react-localization",
          "prop-types": "./node_modules/prop-types",
          "@material-ui/pickers": "./node_modules/@material-ui/pickers",
          "@material-ui/core": "./node_modules/@material-ui/core",
          "classnames": "./node_modules/classnames",
          "qs": "./node_modules/qs",
          "luxon": "./node_modules/luxon",
          "@babel/runtime": "./node_modules/@babel/runtime",
        }
      }
    ]
  ]
}

然后针对 RN ,我们在项目根目录中创建一个metro.config.js文件,以便配置RN Metro Bundler来解析每个目录和共享的npm软件包,如下所示:

var path = require("path");
var config = {
  projectRoot: path.resolve(__dirname),
  watchFolders: [
    // Let's add the root folder to the watcher
    // for live reload purpose
    path.resolve(__dirname, "../MyProject-Library"),
    path.resolve(__dirname, "../MyProject-Backend")
  ],
  resolver: {
    sourceExts: ['js', 'jsx', 'ts', 'tsx'],
    extraNodeModules: {
      // Here I reference my upper folder
      "myprojectlib": path.resolve(__dirname, "../MyProject-Library"),
      "myprojectbackend": path.resolve(__dirname, "../MyProject-Backend/firebase/functions"),

      // Important, those are all the dependencies
      // asked by the "../MyProject-Library" but which
      // are not present in the ROOT/node_modules
      // So install it in your RN project and reference them here

      // "expo": path.resolve(__dirname, "node_modules/expo"),
      // "lodash.merge": path.resolve(__dirname, "node_modules/lodash.merge"),
      "dinero.js": path.resolve(__dirname, "node_modules/dinero.js"),
      "luxon": path.resolve(__dirname, "node_modules/luxon"),
      "validator": path.resolve(__dirname, "node_modules/validator"),
      "react-native-reanimated": path.resolve(__dirname, "node_modules/react-native-reanimated"),
      "react-native-gesture-handler": path.resolve(__dirname, "node_modules/react-native-gesture-handler"),
      "react-native-vector-icons": path.resolve(__dirname, "node_modules/react-native-vector-icons"),
      "react-native-navigation": path.resolve(__dirname, "node_modules/react-native-navigation"),
      "react-native-firebase": path.resolve(__dirname, "node_modules/react-native-firebase"),

      "prop-types": path.resolve(__dirname, "node_modules/prop-types"),
      "react-native": path.resolve(__dirname, "node_modules/react-native"),
      "react": path.resolve(__dirname, "node_modules/react"),
      "@babel/runtime": path.resolve(__dirname, "node_modules/@babel/runtime"),
      "@jsassets": path.resolve(__dirname, "./jsassets"),
      "@data": path.resolve(__dirname, "./data"),
      "@components": path.resolve(__dirname, "./components"),
      "@app": path.resolve(__dirname),
    }
  }
}
module.exports = config;

我们必须在resolver.extraNodeModules中定义每个共享软件包和公共目录;我们甚至必须定义reactreact-native,以便库中的共享代码能够具有组件并访问 React RN 功能。

当我们运行yarn start(或npm run start)时,我们会看到Metro Bundler在所有fc中寻找JS文件。 + RNApp, Library, Backend

Metro Bundler loading

答案 2 :(得分:0)

您可以有3个存储库(如消息中所述)。

示例:

<h1> Class Calculator</h1>
<p>Current grade: <input id="cg" min="1" max="120" 
onchange="computeGrade()"></input></p>
<p>Desired grade: <input id="dg" min="1" max="120" 
onchange="computeGrade()"></input></p>
<p>Final weight: <input id="wof" min="1" max="100" 
onchange="computeGrade()"</input></p>
<p><button>Submit</button></p>
<h2 id="ng"></h2>

每个存储库将包含一个具有不同名称的react-native react common 文件(例如,基本目录名称= package.json的名称)。

此后,您可以从package.json项目中执行npm link ../common,然后将https://github.com/javico2609/flutter-challenges/blob/master/lib/pages/code_examples/pdf_and_csv/pdf.dart链接到npm link项目中,将公共软件包链接到其他存储库中,您将能够像其他任何库一样使用它,这是开发新库的常用方法。

奖金,因为这是一个符号链接,所以对react-native软件包所做的所有更改都将反映在react上(可能需要手动刷新,因为react-native不会刷新{{1} })和common项目。

  

每次运行react-native时都必须再次运行node_modules