Sass 无法使webpack完全忽略不必要的JSX组件

Sass 无法使webpack完全忽略不必要的JSX组件,sass,webpack,extract-text-plugin,Sass,Webpack,Extract Text Plugin,为了一个项目,我花了几年时间锁定在一个古老的技术堆栈中,终于有机会探索更多的最新框架,并深入了解React和Webpack。到目前为止,这在很大程度上是一次令人耳目一新和愉快的经历,但我在使用网页时遇到了一些困难,我希望蜂巢思维能够帮助解决这些问题 我一直在仔细阅读Webpack2.0文档,搜索得非常彻底,结果很短(我只找到了一个问题,很接近,但我不确定它是否适用)。由于缺乏信息,我认为我正在考虑以下两种情况之一: 我想做的是疯狂的 我想做的是基本的,不需要动脑筋 …然而,我在这里 我正在寻找的

为了一个项目,我花了几年时间锁定在一个古老的技术堆栈中,终于有机会探索更多的最新框架,并深入了解React和Webpack。到目前为止,这在很大程度上是一次令人耳目一新和愉快的经历,但我在使用网页时遇到了一些困难,我希望蜂巢思维能够帮助解决这些问题

我一直在仔细阅读Webpack2.0文档,搜索得非常彻底,结果很短(我只找到了一个问题,很接近,但我不确定它是否适用)。由于缺乏信息,我认为我正在考虑以下两种情况之一:

  • 我想做的是疯狂的
  • 我想做的是基本的,不需要动脑筋
  • …然而,我在这里

    我正在寻找的简短版本是一种基于环境变量将某些JSX组件排除在Webpack构建/捆绑包之外的方法。目前,无论依赖关系树是什么样子,基于从条目js forward导入的内容,Webpack似乎希望捆绑项目文件夹中的所有内容

    我假设这是默认行为,因为它有一定的意义——应用程序可能需要处于初始状态以外的状态的组件。不过,在这种情况下,我们的“应用程序”是完全无状态的

    为了提供一些背景信息,以下是该项目的一些粗略要求:

    • 项目包含一个组件桶,这些组件可以组装成一个页面,并根据配置文件给出一个主题
    • 每个组件都包含自己的模块化CSS,用SASS编写
    • 每个导出的页面都是静态的,包实际上会从导出目录中删除。(是的,如果项目结束时只是呈现一系列单一的、静态的页面,那么React有点过分了。项目的未来状态将包括一个UI,而React应该非常适合这个UI,因此最好现在就用JSX编写这些组件。)
    • CSS是使用
      extract text webpack plugin
      从捆绑包中提取的-在最终导出中,没有样式直接内联到元素上,这不是可以更改的要求
    • 作为页面主题信息的一部分,将设置SASS变量,然后SASS将这些变量用于每个JSX组件
    • 只有在给定页面的配置文件中引用的JSX组件的SASS变量才被编译并通过
      SASS加载程序
      传递,以便在编译CSS时使用
    这里是故障的地方:

    假设我有5个JSX组件,方便地命名为
    组件1
    组件2
    组件3
    ,等等。其中每一个都有一个与其关联的匹配的
    .scss
    文件,包括以下方式:

    import React from 'react';
    import styles from './styles.scss';
    
    module.exports = React.createClass({
    
      propTypes: {
        foo: React.PropTypes.string.isRequired,
      },
    
      render: function () {
    
        return (
          <section className={`myClass`}>
            <Stuff {...props} />
          </section>
        );
      },
    });
    
    load_components() {
      let component_templates = {};
      let get_component = function(component_name) {
        return require(`../path/to/components/${component_name}/template.jsx`);
      }
      for (let i = 0; i < this.included_components.length; i++) {
        let component = this.included_components[i];
        component_templates[component] = get_component(component);
      }
      return component_templates;
    }
    
    上面迭代了一个对象,该对象包含我所需的JSX组件(对于给定的页面),该对象现在是以以下方式创建的:

    import React from 'react';
    import styles from './styles.scss';
    
    module.exports = React.createClass({
    
      propTypes: {
        foo: React.PropTypes.string.isRequired,
      },
    
      render: function () {
    
        return (
          <section className={`myClass`}>
            <Stuff {...props} />
          </section>
        );
      },
    });
    
    load_components() {
      let component_templates = {};
      let get_component = function(component_name) {
        return require(`../path/to/components/${component_name}/template.jsx`);
      }
      for (let i = 0; i < this.included_components.length; i++) {
        let component = this.included_components[i];
        component_templates[component] = get_component(component);
      }
      return component_templates;
    }
    
    那里的
    exclude
    条目是新的,似乎不起作用

    这是一部中篇小说,但我想在信息太多方面犯错误,而不是信息太少。我是错过了一些简单的事情,还是试图做一些疯狂的事情?两者都有

    如何使未使用的组件不被Webpack处理?

    TL;博士 不要在
    require
    中使用表达式,并使用多个入口点,每个页面一个入口点


    详细答案 Webpack似乎希望捆绑项目文件夹中的所有内容

    事实并非如此,webpack只包含您导入的内容,这是静态确定的。事实上,很多刚接触webpack的人一开始都很困惑,webpack不仅仅包含整个项目。但在你的情况下,你遇到了一个边缘案件。问题在于您使用
    require
    的方式,特别是此功能:

    let get_component = function(component_name) {
      return require(`../path/to/components/${component_name}/template.jsx`);
    }
    
    您正在尝试根据参数将组件导入函数。webpack如何在编译时知道应该包含哪些组件?嗯,webpack不做任何程序流分析,因此唯一的可能性是包含所有可能与表达式匹配的组件

    您很幸运,webpack首先允许您这样做,因为只向
    require
    传递一个变量将失败。例如:

    function requireExpression(component) {
      return require(component);
    }
    
    requireExpression('./components/a/template.jsx');
    
    将在编译时向您发出此警告,即使很容易看出需要哪些组件(稍后在运行时失败):

    但因为webpack不做程序流分析,所以它看不到这一点,即使它做了,你也可以在任何地方使用该功能,即使用户输入,这基本上是一个失败的原因

    有关更多详细信息,请参阅官方文件

    Webpack试图包含我们的所有组件,而不管实际加载的布局是什么

    既然您知道了为什么webpack需要所有组件,那么理解为什么您的想法行不通,坦白说,过于复杂也很重要

    如果我理解正确的话,您有一个多页应用程序,其中每个页面都应该有一个单独的包,其中只包含必要的组件。但是您真正要做的是在运行时只使用所需的组件,所以从技术上讲,您有一个包含所有页面的包,但您只使用其中一个,这对于单页面应用程序(SPA)来说是非常好的。不知何故,您希望webpack知道您正在使用哪一个,它只能通过运行它才能知道,所以在编译时它肯定无法知道

    问题的根源在于您在运行时(在程序的执行过程中)做出决策,而应该在编译时进行决策。解决方案是使用多个入口点,如中所示。你所知道的
    Critical dependency: the request of a dependency is an expression
    
    entry: {
      pageOne: './src/pageOne.jsx',
      pageTwo: './src/pageTwo.jsx',
      // ...
    },
    output: {
      filename: '[name].bundle.js'
    }