如何在将 React 与电子结合使用时分离渲染器和主进程依赖关系?

Posted

技术标签:

【中文标题】如何在将 React 与电子结合使用时分离渲染器和主进程依赖关系?【英文标题】:How to separate renderer and main process dependency while using React with electron? 【发布时间】:2021-12-22 19:05:36 【问题描述】:

我有 React Web 应用程序,我正在尝试将其作为桌面应用程序进行互操作。我所有的 React 依赖项都由 webpack 在生产中捆绑,因此我不需要将这些节点模块包含在 app.asar 中,这会不必要地增加我的生产构建的大小。

现在我的问题是它阻止我包含主进程依赖项,因为我有规则排除 package.json 中的 node_modules 我如何分离要由电子生成器包含的主进程依赖项但忽略渲染进程依赖。我是电子新手,所以任何帮助对我来说都很有价值。

我的 package.json 看起来像这样:

  "name": "app-name",
  "version": "0.16.2",
  "private": true,
  "main": "public/electron.js",
  "repository": "github repo",
  "homepage": "./",
  "build": 
    "appId": "com.appname",
    "productName": "productName",
    "copyright": "copyright",
    "dmg": 
      "background": null,
      "backgroundColor": "#ffffff",
      "window": 
        "width": "400",
        "height": "300"
      ,
      "contents": [
          "x": 100,
          "y": 100
        ,
        
          "x": 300,
          "y": 100,
          "type": "link",
          "path": "/Applications"
        
      ]
    ,
    "nsis": 
      "createDesktopShortcut": "always",
      "installerIcon": "./resources/icon.ico"
    ,
    "mac": 
      "target": "dmg",
      "category": "public.app-category.business",
      "icon": "./resources/icon.icns"
    ,
    "win": 
      "target": "nsis",
      "extraResources": [
        "./*.dll",
        "!./exclude-me.dll"
      ]
    ,
    "linux": 
      "maintainer": "maintainer",
      "target": "deb",
      "category": "Utility"
    ,

    "files": [
      "./build/**/*",
      "!node_modules"
    ],
    "directories": 
      "buildResources": "resources"
    ,
    "publish": 
      "provider": "github"
    
  ,
  "scripts": 
    "generate:meta": "node ./internals/scripts/generate-meta.js",
    "start": "REACT_APP_CURRENT_GIT_SHA=`git rev-parse --short HEAD` craco start",
    "electron:dev": "concurrently \"env-cmd -f .env.electron yarn start\" \"wait-on http://localhost:3002 && electron .\"",
    "electron:prod": "yarn build:staging && electron-builder",
    "electron:release": "electron-builder -p 'onTagOrDraft'",
    "postinstall": "electron-builder install-app-deps",
    "start:windows": "git rev-parse --short HEAD >sha.txt && set /p REACT_APP_CURRENT_GIT_SHA= < sha.txt && del sha.txt && craco start",
    "start:prod": "env-cmd -f .env.production yarn start",
    "start:dev": "env-cmd -f .env.staging yarn start",
    "build": "yarn generate:meta && REACT_APP_CURRENT_GIT_SHA=`git rev-parse --short HEAD` craco build",
    "build:staging": "env-cmd -f .env.staging yarn build",
    "build:prod": "env-cmd -f .env.production yarn build",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx --quiet",
    "lint-fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
    "test": "craco test",
    "eject": "craco eject",
    "generate": "graphql-codegen --config codegen.yml",
    "extract-translations": "i18next",
    "analyze": "cross-env REACT_APP_INTERACTIVE_ANALYZE=1 yarn build"
  ,
  "husky": 
    "hooks": 
      "pre-push": "yarn lint",
      "pre-commit": "pretty-quick --staged"
    
  ,
  "eslintConfig": 
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  ,
  "browserslist": 
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  ,
  "dependencies": 
    "@ant-design/icons": "^4.6.2",
    "@apollo/client": "^3.3.16",
    "@hookform/resolvers": "^2.4.0",
    "@sentry/browser": "^6.13.3",
    "@sentry/tracing": "^6.13.3",
    "@stripe/react-stripe-js": "^1.4.1",
    "@stripe/stripe-js": "^1.15.0",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "@twilio/voice-sdk": "^2.0.1",
    "@types/react-beautiful-dnd": "^13.1.1",
    "@types/react-color": "^3.0.5",
    "@types/react-highlight-words": "^0.16.3",
    "@types/react-responsive": "^8.0.2",
    "@welldone-software/why-did-you-render": "^6.1.1",
    "antd": "^4.15.4",
    "apollo-link-token-refresh": "^0.3.2",
    "apollo-upload-client": "^15.0.0",
    "apollo3-cache-persist": "^0.9.1",
    "craco-less": "^1.18.0",
    "date-fns": "^2.16.1",
    "dompurify": "^2.2.6",
    "electron-is-dev": "^2.0.0",
    "electron-updater": "^4.3.9",
    "env-cmd": "^10.1.0",
    "fernet": "^0.4.0",
    "firebase": "^9.1.1",
    "graphql": "^15.5.0",
    "history": "^5.0.0",
    "husky": "^4.3.0",
    "i18next": "^19.8.7",
    "i18next-browser-languagedetector": "^6.0.1",
    "i18next-http-backend": "^1.1.0",
    "immer": "^8.0.1",
    "jspdf": "^2.3.1",
    "jwt-decode": "^3.1.2",
    "libphonenumber-js": "^1.9.6",
    "linkify-html": "^3.0.2",
    "linkifyjs": "^3.0.1",
    "lint-staged": "^10.5.3",
    "lodash.debounce": "^4.0.8",
    "lodash.get": "^4.4.2",
    "lodash.isempty": "^4.4.0",
    "lodash.omit": "^4.5.0",
    "lodash.startswith": "^4.2.1",
    "npm-watch": "^0.11.0",
    "papaparse": "^5.3.0",
    "prettier": "^2.2.1",
    "rc-picker": "^2.5.15",
    "react": "^17.0.1",
    "react-beautiful-dnd": "^13.1.0",
    "react-color": "^2.19.3",
    "react-copy-to-clipboard": "^5.0.3",
    "react-dom": "^17.0.1",
    "react-draggable": "^4.4.3",
    "react-flag-kit": "^0.3.1",
    "react-h5-audio-player": "^3.6.1",
    "react-highlight-words": "^0.17.0",
    "react-hook-form": "^7.4.0",
    "react-i18next": "^11.8.6",
    "react-icons": "^4.1.0",
    "react-mic": "^12.4.6",
    "react-perfect-scrollbar": "^1.5.8",
    "react-phone-input-2": "^2.13.9",
    "react-responsive": "^8.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.2",
    "react-scroll": "^1.8.2",
    "react-select": "^4.3.0",
    "react-use-intercom": "^1.3.0",
    "react-window": "^1.8.6",
    "secure-ls": "^1.2.6",
    "socket.io-client": "^3.0.4",
    "styled-components": "^5.2.3",
    "subscriptions-transport-ws": "^0.9.18",
    "typescript": "^4.1.2",
    "web-vitals": "^0.2.4",
    "workbox-background-sync": "^6.3.0",
    "workbox-broadcast-update": "^6.3.0",
    "workbox-cacheable-response": "^6.3.0",
    "workbox-core": "^6.3.0",
    "workbox-expiration": "^6.3.0",
    "workbox-precaching": "^6.3.0",
    "workbox-routing": "^6.3.0",
    "workbox-strategies": "^6.3.0",
    "xlsx": "^0.17.0",
    "yup": "^0.32.5"
  ,
  "devDependencies": 
    "@babel/plugin-proposal-decorators": "^7.12.1",
    "@craco/craco": "^6.2.0",
    "@graphql-codegen/cli": "1.20.1",
    "@graphql-codegen/fragment-matcher": "2.0.1",
    "@graphql-codegen/introspection": "1.18.1",
    "@graphql-codegen/typescript": "^1.20.2",
    "@graphql-codegen/typescript-document-nodes": "1.17.9",
    "@graphql-codegen/typescript-graphql-files-modules": "^1.18.1",
    "@graphql-codegen/typescript-operations": "1.17.14",
    "@graphql-codegen/typescript-react-apollo": "2.2.1",
    "@types/apollo-upload-client": "^14.1.0",
    "@types/dompurify": "^2.2.1",
    "@types/emoji-mart": "^3.0.4",
    "@types/jest": "^26.0.15",
    "@types/lodash.debounce": "^4.0.6",
    "@types/lodash.get": "^4.4.6",
    "@types/lodash.isempty": "^4.4.6",
    "@types/lodash.omit": "^4.5.6",
    "@types/lodash.startswith": "^4.2.6",
    "@types/node": "^12.0.0",
    "@types/papaparse": "^5.2.4",
    "@types/react": "^16.9.53",
    "@types/react-copy-to-clipboard": "^5.0.0",
    "@types/react-dom": "^16.9.8",
    "@types/react-mic": "^12.4.2",
    "@types/react-router-dom": "^5.1.6",
    "@types/react-scroll": "^1.8.2",
    "@types/react-select": "^4.0.13",
    "@types/react-window": "^1.8.2",
    "@types/requestidlecallback": "^0.3.1",
    "@types/socket.io-client": "^1.4.34",
    "@types/styled-components": "^5.1.4",
    "@typescript-eslint/eslint-plugin": "^4.14.1",
    "@typescript-eslint/parser": "^4.14.1",
    "babel-plugin-import": "^1.13.3",
    "compression-webpack-plugin": "6.1.1",
    "concurrently": "^6.3.0",
    "craco-swc": "^0.1.0",
    "cross-env": "^7.0.3",
    "electron": "^15.2.0",
    "electron-builder": "^22.13.1",
    "eslint-config-airbnb": "18.2.1",
    "eslint-config-airbnb-typescript": "^12.0.0",
    "eslint-config-prettier": "^7.2.0",
    "eslint-plugin-import": "^2.22.1",
    "eslint-plugin-jest": "^24.1.3",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-react": "^7.21.5",
    "eslint-plugin-react-hooks": "^1.7.0",
    "i18next-parser": "^3.6.0",
    "less": "^3.12.2",
    "prettier-eslint": "^12.0.0",
    "pretty-quick": "^3.1.0",
    "simple-progress-webpack-plugin": "^2.0.0",
    "wait-on": "^6.0.0",
    "webpack-bundle-analyzer": "^4.4.2",
    "webpackbar": "^5.0.0-3"
  ,
  "description": "description",
  "author": "author"
 ```


【问题讨论】:

【参考方案1】:

如果这些依赖项使用 webpack 打包,您可以安全地将它们移动到 devDependencies,它们不包含在最终应用程序的 node_modules

【讨论】:

由于我必须先使用 webpack 构建,如果我包含 dev 上的所有依赖项,webpack 将不会包含生产构建中的那些。我正在尝试为 Web 和桌面使用相同的代码库。谢谢你的回答。 Webpack 在生产环境中包含我的 devDependencies,我可以看看你的 webpack 配置吗?

以上是关于如何在将 React 与电子结合使用时分离渲染器和主进程依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章

如何在胶合时分离(带有空格)字符串,使用数组中的键来检查它是否粘合?

Array.map 中的 React 功能组件在将函数作为道具传递时总是重新渲染

散列更改时分离和重新附加元素

如何将 React 钩子(useContext、useEffect)与 Apollo 反应钩子(useQuery)结合起来

使用 API 的 React 中发生了太多的重新渲染

使用 React.js + Express.js 发送电子邮件