全局css应该放在每个组件还是根组件(webpack条目文件)中?

时间:2017-08-08 07:17:13

标签: css reactjs webpack

我想知道如果我有一个经常在我的组件中使用的外部CSS文件,我应该在每个组件或根组件中导入这个外部CSS吗?

对于每个组件:

import React from 'react'
import '../font.css'

class MyComponent extends React.Component {
  render() {
    return <div className="fa fa-bandcamp"></div>;
  }
}

这是不言自明的:因为我想使用&#39; fa fa-bandcamp&#39;,我导入&#39; ../ font.css&#39;。

这种方法就像编程JS或任何其他编程语言一样。如果我们需要依赖项,我们也会在该文件中导入它,例如:

import global from 'global'
import util from 'util'

global.foo
global.bar
util.bar
util.bar
// ...

然而,我的同事告诉我,永远不应该在每个依赖组件中导入全局css,而应该将其导入到根组件或webpack的条目文件中,例如:

// in each component
import React from 'react'
// import '../font.css'

class MyComponent extends React.Component {
  render() {
    return <div className="fa fa-bandcamp"></div>;
  }
}

// in entry file (root component)
import React from 'react'
import '../font.css'

class App extends React.Component {
  render() {
    return <div>{this.props.children}</div>;
  }
}

每种解决方案的优缺点是什么?我想听听更多建议并感谢您的帮助。

3 个答案:

答案 0 :(得分:6)

我会在您使用它的时间和地点导入font.css文件(但不完全按照您的建议,请参见下文),而不仅仅是在根组件中。我建议这是因为当你决定代码拆分时,你只希望CSS存在于使用它的包中。

如果导入位于根组件中,则可能会删除使用fa fa-bandcamp类的所有组件,但导入仍保留在根目录中(因为您忘记了它并且不在组件旁边)并且你正在捆绑在CSS中甚至不在使用它的块中。

相反,在组件级别导入时,您最终可能会遇到使用这些类并忘记导入font.css的情况,因为另一个组件已经导入了全局CSS。看起来它可以工作但是如果你编码拆分你可能会发现你的块没有正确的字体,因为CSS导入在另一个块中。在这种情况下,在root中导入它将解决您的问题!

我会做什么:

我认为任何全球性的CSS都很糟糕,你应该使用类似CSS modules的东西。所以我要更进一步,创建一个<Text/>组件,如:

import React from 'react'
import '../font.css'
export default ({ className, children, tagName: TagName }) => <TagName className={`fa fa-bandcamp ${className}`>{ children }</TagName>;

现在,您可以安全地使用所有组件中的<Text tagName="span">Hey!</Text>,因为:

  • 您不再需要一直导入CSS。
  • 如果您对代码进行拆分或删除所有<Text/>,则不会留下包含您忘记的根目录中未使用的CSS导入的捆绑包。
  • 无法使用这些类而忘记导入CSS。
  • 一切都很好,并以模块化方式封装,您的捆绑包尽可能高效。

我不会将这种策略用于像reset.css那样的东西。明显。

TL; DR摘要

根级别 - 潜在的低效代码拆分。更难以维护,因为CSS不会与使用它的组件一起生存。

个别组件级别 - 一直难以导入。如果忘记导入全局CSS,最终可能会使用一个不存在于块中的类,这样会很脆弱。

<强>&#34;文本&#34;组件 - 太棒了。只要确保每个人都通过这个组件使用fa类,一切都很好。模块化。易于维护。的鲁棒性。

答案 1 :(得分:2)

在全球空间中添加css非常简单,只需开箱即用。

如果您需要,可以使用webpack轻松导入style!css!sass导入的每个组件文件中的css文件{/ 1}}。

它允许您以下列方式简单地导入和使用React组件中的样式: .scss

import styles from './mycomponent.scss';

以下是各自的装载机: export default props => <button className={styles.mycomponent.button} />

style-loader css-loader sass-loader 将在开发期间处理热负载,并在生产构建时将输出的样式(这些样式编译到组件模块中)捆绑在一起。

我建议style-loader使用modules option,以确保您的CSS正确确定范围,并且永远不会与外部代码冲突。

答案 2 :(得分:2)

当你的同事说:

时,他们几乎是对的
  

永远不应该在每个依赖组件中导入全局css,而应该将其导入到根组件或webpack的条目文件中

<强>为什么

因为那时你可能最终得到一个内联css文件,举一个例子,在我的一个应用程序中,我使用less,每个导入解析成同一内联到javascript文件的本地副本,生成在我的案例中,bundle.js文件,代码段:


, /* 1381 */
/***/
function(module, exports, __webpack_require__) {

    eval("exports = module.exports = __webpack_require__(625)();\n// imports\nexports.push([
module.id, \"@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700);\", \"\"]);
\n\n// module\nexports.push([module.id, \"/*!\\n * Bootstrap v3.3.7 (http://getbootstrap.com)\\n * 
Copyright 2011-2016 Twitter, Inc.\\n * Licensed under MIT 
(https://github.com/twbs/bootstrap/blob/master/LICENSE)\\n */\\n/*! normalize.css v3.0.3 | MIT License |
 github.com/necolas/normalize.css */\\nhtml 
{\\n  font-family: sans-serif;\\n  -ms-text-size-adjust: 100%;
\\n  -webkit-text-size-adjust: 100%;\\n}\\nbody 
{\\n  margin: 0;\\n}\\narticle,\\naside,\\ndetails,\\nfigcaption,
\\nfigure,\\nfooter,\\nheader,\\nhgroup,\\nmain,\\nmenu,\\nnav,\\nsection,
\\nsummary {\\n  display: block;\\n}\\naudio,\\ncanvas,\\nprogress,
\\nvideo {\\n  display: inline-block;\\n  vertical-align: baseline;\\n}
\\naudio:not([controls]) 
{\\n  display: none;\\n  height: 0;\\n}\\n[hidden],\\ntemplate {\\n  display: none;\\n}\\na {\\n  background-color: transparent;\\n}

   Some more things here...

    /***/
}

一开始就查看bootstrap css许可证?但是它也使用@import url用于在文件中导入的字体css。

因此,每次导入时,它都会一次又一次地包含在模块代码中。

可以使用的东西

如果您使用类似Extract Text Webpcak Plugin的内容,它基本上扫描您的代码并将css提取到一个文件中,这也有助于并行加载。因此解决您的相同的css文件导入多次解决方案

<强>观察

在我的情况下,我的webpack使用less样式,因此我的加载器类似于:

Webpack v1.13。*:

  {
     test: /\.less$/,
     loader: 'style!css!less'
  }

在我的情况下,将其添加到style标记下,但嵌入在javascript函数中。

在您的情况下,您使用的是style-loader,根据定义是:

  

style-loader - 在运行时将由JavaScript模块导出的CSS注入标记

现在,如果您通过在案例中导入相同的global.css来验证,则会创建单个 <style>,这将是一次性定义。

生成时,显示您的bundle.js推送相同内容:

/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__(3)(undefined);
// imports


// module
exports.push([module.i, ".red {\n  color: red;\n}\n\n.blue {\n  color: blue;\n}\n", ""]);

// exports


/***/ }),

这就是为什么在index.html中你会看到bundel.js添加的<style>标签:

function insertStyleElement (options, style) {
   ....
}

<强>结论

  • 全局导入样式

      

    专业人士:如果您拥有bootstrap.cssfont-awesome这样的基础CSS,这是一个很好的做法,因为知道整个应用程序遵守的内容很简单css的规则。

         

    缺点。如果css是常见的,那么我没有看到任何全局导入它的缺点

  • 本地导入样式

      

    专业人员:如果您想要深入了解任何错误,在知道哪个css影响组件的情况下,调试总是容易得多。这些css文件是您要实现的文件。

         

    缺点:如果有border问题的错误,并且在调试时,您意识到它指向本地导入的css文件,但很少有人存在,但是您没有意识到它会影响其他组件,那么它会导致您的UI发生意外更改。此外,在构建期间提取样式会慢得多。