如何将依赖于 Styled Components 的 React 组件库提供给另一个也具有 Styled Comopnents 依赖项的库?

Posted

技术标签:

【中文标题】如何将依赖于 Styled Components 的 React 组件库提供给另一个也具有 Styled Comopnents 依赖项的库?【英文标题】:How to serve a React component library dependent on Styled Components to another library that also has a Styled Comopnents dependency? 【发布时间】:2019-04-06 03:00:40 【问题描述】:

我最近将我正在开发的内部组件库转换为样式化组件。该组件库在 package.json 中将 Styled Components 列为 peerDep 和 devDep。从那里我将 Styled Comopnents 导入到每个需要样式的组件中。到目前为止,一切都很好。

我有一个 Create React App (CRA) 应用程序,它也将 Styled Comopnents 作为常规依赖项导入。我需要它才能为这个特定项目构建一次性组件。但是我还需要能够导入我的组件库来为这个基于 CRA 的新应用构建核心组件。

现在这是我的问题:我通过直接链接到 package.json (file:../component-lib) 中的组件库,在此 CRA 应用程序中测试我最近转换的基于样式化组件的组件库。我已经安装了我的所有部门,从组件库中导入了组件,在 CRA 项目中构建了一个新的项目特定的样式化组件,然后在本地运行它却看到了同样的错误:“看起来有几个 'styled- “我已经阅读了该部分的文档,并学会了不使用 npm 链接并将 SC 作为我的组件库中的 peerDep 和 devDep 服务。

由于我在 CRA 项目中运行多个实例,因此我认为此问题不允许我访问我从组件库传递到自定义 ThemeProvider 的主题道具?

这个问题肯定是因为我缺乏依赖管理方面的知识。我只是想知道是否有其他人遇到过类似的问题,或者我应该怎么做才能避免重复的 Styled Comopnents 实例?

组件库索引

export  default as Button  from "./components/Button";

export 
  default as CustomThemeProvider
 from "./components/utils/CustomThemeProvider";

组件库 package.json

"scripts": 
    "build": "nwb build-react-component --copy-files",
    "clean": "nwb clean-module && npm clean-demo",
    "start": "nwb serve-react-demo",
    "lint": "eslint src/**",
    "test": "nwb test-react",
    "styleguide": "styleguidist server",
    "styleguide:build": "styleguidist build",
    "test:coverage": "nwb test-react --coverage",
    "test:watch": "nwb test-react --server",
    "publish": "npm run build && npm publish"
,
"dependencies": 
    "@rebass/grid": "^6.0.0-4",
    "prop-types": "^15.6.0",
    "react-portal": "^4.1.2"
,
"peerDependencies": 
    "react": "16.x",
    "styled-components": "^4.0.3"
,
"devDependencies": 
    "babel-eslint": "^8.2.2",
    "eslint": "^4.18.2",
    "eslint-plugin-react": "^7.7.0"
    "prettier": "1.14.3",
    "nwb": "0.22.x",
    "react": "^16.4.0",
    "react-dom": "^16.4.0",
    "react-styleguidist": "^7.2.0",
    "styled-components": "^4.0.3"
,

组件库 NWB 配置

module.exports = 
  type: "react-component",
  npm: 
    esModules: false,
    umd: false,
  ,
  babel: 
    stage: 1
  
;

CRA 项目包.json

"dependencies": 
  "component-library": "0.16.6",
  "react": "^16.6.0",
  "react-dom": "^16.6.0",
  "react-scripts": "2.1.0",
  "styled-components": "^4.0.3"
,

【问题讨论】:

请显示您的组件库包的(可能简化的)index.js,也许还有组件库的完整 package.json。我试过你描述的场景没有问题。 我假设你正在使用 webpack 来捆绑你的组件库?我怀疑这是您构建组件库的配置中的某些内容,导致样式组件包含在构建输出中。 继续并在您的问题中包含 nwb.config 内容。 另外,对于您的组件库 package.json,您没有包含脚本部分。我认为这将帮助我了解如何配置 nwb。 使用 nwb 我能够重现您的问题 - 抱怨样式组件的多个实例并且主题似乎无法正常工作。还不确定修复方法。 【参考方案1】:

我现在面临同样的问题,但我仍然不确定。我可以正确或不正确地修复它,所以请不要将此答案作为有保证的解决方案。 您可以尝试两件事。

第一个出现在styled-components FAQs 部分中。他们建议使用别名配置 Webpack(我假设您也在使用 Webpack),以便它始终在您指定的任何位置查找 styled-components 依赖项。这应该避免有多个样式组件实例,但到目前为止我无法为我完成这项工作。

第二个选项是使用替代的 no npm link。显然,当您有符号链接依赖项时(这实际上是 npm link 所做的)。捆绑器的解析器尝试在同一项目中查找依赖项。这也在链接样式组件常见问题部分中提到。 如果您采用这种方法,您应该做的是避免创建一个从 CRA 应用程序指向您的组件库的符号链接,而是复制该文件夹。

有一个名为 wml 的工具可以将组件库的内容复制到 CRA 应用程序的 node_modules 文件夹中。 wml 还能够监视组件库文件夹中的更改,并将更改重新复制到您的 CRA 应用程序的node_modules。所以,我们可以说 wml 是npm link 的替代品。在我最初的尝试中,它对我来说效果很好,所以也许这是你可以尝试的。

小心:wml 中的an issue 会导致项目中的文件在您第一次设置时被删除。这并没有发生在我身上,但我看到其他人遇到了这个问题,所以如果你打算尝试 wml,请确保你已经将所有更改推送到你的源代码版本控制系统。

这些是使用命令行为项目设置 wml 时需要遵循的步骤:

wml add <component-library-folder> <CRA-app-folder>/node_modules/<name-of-component-library>
wml start

理想情况下,我宁愿在不使用任何外部工具的情况下解决此问题,但如果样式组件维护者在其网站上建议的内容无效,则可以作为一种解决方法。

【讨论】:

【参考方案2】:

这只是部分答案,我希望能让您或其他人弄清楚其余部分。我远不是管理这类依赖关系的专家,我正在帮助我加深自己的知识,因为我可能想尽快进行类似的设置。

虽然看起来这应该可以通过 nwb 实现,但我还是直接使用 webpack 以获得更多控制权。即使直接使用 webpack,我也只是做了其中的一部分。当我进行构建时,一切正常,但在 CRA 应用程序的开发模式(npm start)下,styled-components 包仍然被拉入两次,并且样式无法正常工作。这似乎是一个潜在的 webpack 问题,因为开发模式和生产模式的行为如此不同,但它可能与 CRA webpack 开发配置有关,或者(更有可能)是我还不了解的某些方面。

这是一个很好的组件库配置参考示例:https://github.com/kalcifer/webpack-library-example

这是我的测试组件库的 package.json(component-lib3 只是因为尝试了其他几种方法):


  "name": "component-lib3",
  "version": "1.0.7",
  "description": "component-lib3 React component",
  "main": "dist/component-lib3.js",
  "peerDependencies": 
    "react": "^16.6.0",
    "react-dom": "^16.6.0",
    "styled-components": "^4.0.3"
  ,
  "devDependencies": 
    "react": "^16.6.0",
    "react-dom": "^16.6.0",
    "styled-components": "^4.0.3",
    "@babel/core": "^7.1.2",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.4",
    "webpack": "^4.24.0",
    "webpack-cli": "^3.1.2"
  ,
  "scripts": 
    "build": "webpack"
  

这是 webpack.config.js:

var path = require('path');

module.exports = 
  entry: './src/index.js',
  mode: 'production',
  output: 
    path: path.resolve(__dirname, 'dist'),
    filename: 'component-lib3.js',
    libraryTarget: 'umd',
    library: 'component-lib3'
  ,
  externals: 
     "styled-components": 
       commonjs: 'styled-components',
       commonjs2: 'styled-components',
       amd: 'styled-components'
     ,
     "react": 
       commonjs: 'react',
       commonjs2: 'react',
       amd: 'react'
     ,
     "react-dom": 
       commonjs: 'react-dom',
       commonjs2: 'react-dom',
       amd: 'react-dom'
     
  ,
  module: 
    rules: [
      
        test: /\.js$/,
        exclude: /node_modules/,
        use: 
          loader: "babel-loader"
        
      
    ]
  
;

还有.babelrc:


  "presets": ["@babel/preset-env", "@babel/preset-react"]

我尝试了许多变体,但我不明白为什么这不适用于开发模式。

【讨论】:

以上是关于如何将依赖于 Styled Components 的 React 组件库提供给另一个也具有 Styled Comopnents 依赖项的库?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 styled-components 将样式应用于 React Native 中的自定义组件?

styled-components:扩展样式并更改元素类型

如何使用 styled-components 将 prop 传递给 Material-UI 组件

如何将 Nextjs + styled-components 与 material-ui 集成

如何使用 input[type="submit"] 属性将 CSS 转换为 Styled-Components?

Styled-components vs Emotion - 如何在 Styled-components 上重新应用 css`style` 函数