节点模块中样式化组件的多个实例

时间:2018-11-23 00:54:36

标签: reactjs npm webpack styled-components webpack-4

我正在为可共享的UI组件创建一个单独的存储库。我正在使用styled-component。当我使用npm link在本地发布软件包时。抛出错误。

enter image description here

错误已说明here

Project
 |
 +-- node_modules
    |
    +-- styled-component v4.0.2
    |
    +-- ui-component 
        |
        +-- styled-component v4.1.1

有几种方法可以修复它,就像在link中提到的那样。

  1. npm dedupe(不适用于开发环境,因为它不能与npm link一起很好地工作)。
  2. 设置Webpack(某些项目将使用create-react-app,因此他们无权访问webpack)。

虽然有两个想法,但我有两个想法。

首先,两种解决方案都迫使最终用户在您的终端做某事。我希望使其像其他npm软件包一样在其中安装和使用,而无需告诉用户在配置级别做些什么。

第二,为什么我必须这样做。我已经在webpack中设置了所有内容。我要求webpack不要对特定的软件包使用它自己的依赖关系,而要使用最终用户软件包。

其他npm包的工作方式取决于父依赖关系,但它们在开发过程中使用自己的依赖关系。像react

这是我可共享的UI组件库中的文件。

Package.json

{
  "name": "ui-component",
  "version": "1.0.0",
  "description": "Shareable web UI component",
  "main": "build/index.js",
  "scripts": {
    "dev": "start-storybook -p 6006",
    "build": "webpack",
    "build:storybook": "build-storybook",
    "test": "jest --env=jsdom",
    "lint": "eslint"
  },
  "jest": {
    "coverageThreshold": {
      "global": {
        "branches": 80,
        "functions": 80,
        "lines": 80,
        "statements": 80
      }
    },
    "collectCoverageFrom": [
      "src/**/*.{js,jsx}",
      "!storybook-static/**/*.{js,jsx}",
      "!congif/**/*.{js,jsx}"
    ],
    "setupFiles": [
      "<rootDir>/src/enzymeSetup.js"
    ],
    "testMatch": [
      "<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
    ],
    "testEnvironment": "node",
    "testURL": "http://localhost",
    "transform": {
      "^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest"
    },
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>/__tests__/setup/"
    ],
    "moduleNameMapper": {
      "^@theme": "<rootDir>/src/theme.js",
      "^@validation": "<rootDir>/src/validation/index.js",
      "^@helper": "<rootDir>/src/helper.js"
    },
    "moduleFileExtensions": [
      "web.js",
      "js",
      "json",
      "web.jsx",
      "jsx",
      "node",
      "mjs"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": [
      "npm run lint --fix",
      "cross-env CI=true npm test -- --coverage --bail --findRelatedTests"
    ]
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@material-ui/core": "^3.5.1",
    "@material-ui/icons": "^3.0.1",
    "react": "^16.6.3",
    "react-router-dom": "^4.3.1",
    "styled-components": "^4.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.1.6",
    "babel-core": "7.0.0-bridge.0",
    "@babel/preset-env": "^7.1.6",
    "@babel/preset-react": "^7.0.0",
    "@storybook/addon-actions": "^4.0.7",
    "@storybook/addon-centered": "^4.0.7",
    "@storybook/addon-info": "^4.0.7",
    "@storybook/addon-links": "^4.0.7",
    "@storybook/addon-options": "^4.0.7",
    "@storybook/addons": "^4.0.7",
    "@storybook/components": "^4.0.7",
    "@storybook/react": "^4.0.7",
    "babel-eslint": "^9.0.0",
    "babel-jest": "^23.6.0",
    "babel-loader": "^8.0.4",
    "css-loader": "^1.0.1",
    "enzyme": "^3.7.0",
    "enzyme-adapter-react-16": "^1.6.0",
    "eslint": "^5.9.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "^6.1.2",
    "eslint-plugin-react": "^7.11.1",
    "file-loader": "^2.0.0",
    "husky": "^1.1.2",
    "jest": "^23.6.0",
    "lint-staged": "^8.0.4",
    "react-dom": "^16.6.3",
    "react-router-dom": "^4.3.1",
    "storybook-styled-components": "^1.1.2",
    "style-loader": "^0.23.1",
    "webpack": "^4.26.0",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10"
  },
  "peerDependencies": {
    "react": "^16.5.2",
    "styled-components": "^4.1.1"
  }
}

Webpack

const path = require ('path');

module.exports = {
  entry: {
    main: './src/index.js',
  },
  output: {
    path: path.resolve(__dirname, './build'),
    filename: 'index.js',
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: [{
          loader: 'babel-loader',
        }],
      }
    ],
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          chunks: 'all',
        }
      }
    }
  },
  plugins: [],
  resolve: {
    alias: {
      '@theme': path.resolve(__dirname, './src/theme.js'),
      '@validation': path.resolve(__dirname, './src/validation/index.js'),
      '@helper': path.resolve(__dirname, './src/helper.js'),
    }
  },
  externals: {
    'react': 'commonjs react', // this line is just to use the React dependency of our parent-testing-project instead of using our own React.
    'styled-components': 'commonjs styled-components' // this line is just to use the React dependency of our parent-testing-project instead of using our own styled-component.
  }
}

我的父应用程序正在使用styled-components ^4.0.2,而我的可共享ui库则使用样式组件“ styled-components”:“ ^ 4.1.1”。

我在peerDependencieswebpack中都有一个条目。奋斗超过一天的人,将不胜感激。

3 个答案:

答案 0 :(得分:1)

请参阅正式的样式化组件文档中的this FAQ entry。在大多数情况下,向webpack配置添加别名足以解决该问题:

  resolve: {
+   alias: {
+     "styled-components": path.resolve("./node_modules", "styled-components"),
+   }
  }

答案 1 :(得分:0)

我花费了数小时尝试各种方法来克服这个问题,包括styled-components文档中的所有内容,但都没有运气。直到我找到this suggestion on GitHub,一切都没有。

在Webpack配置中添加以下内容,可以告诉它对所有入口点使用单个运行时,而不是为每个入口点创建新的运行时。

optimization: {
  runtimeChunk: {
    name: "vendor"
},
....

答案 2 :(得分:0)

我也遇到了这个问题,以某种方式,我认为您有时无法加载styled-components的两个版本,即使它们是相同版本,例如。 4.4.1

所以最后,我必须使用peerDependencies,幸运的是我可以控制所有存储库,因此我将styled-components移到了peerDependencies的核心库中。然后仅依靠实施仓库中的一个副本。

我仍然可以闻到这里的气味,但是到目前为止,我只能让ThemeProvider在不同的存储库中以这种方式工作。