在为一个项目锁定了一个古老的技术堆栈几年之后,我终于有机会探索更多当前的框架并涉足 React 和 Webpack。到目前为止,这在很大程度上是一种令人耳目一新且令人愉快的体验,但是我在使用 Webpack 时遇到了一些困难,我希望蜂巢思维可以帮助解决。
我一直在仔细研究 Webpack 2.0 文档并进行了非常详尽的搜索,但结果很短(我只提出了这个问题,它很接近,但我不确定它是否适用)。那里缺乏信息使我认为我正在考虑以下两种情况之一:
- 我正在尝试做的事情是疯狂的。
- 我正在尝试做的事情很简单,以至于它应该是不费吹灰之力的。
...然而,我在这里。
我正在寻找的简短版本是一种基于环境变量将某些 JSX 组件排除在 Webpack 构建/捆绑包中的方法。目前,无论依赖关系树根据imported
条目 js 向前的内容应该是什么样子,Webpack 似乎都希望将所有内容捆绑在项目文件夹中。
我有点假设这是默认行为,因为它有一定的意义——应用程序可能需要处于初始状态以外的状态的组件。但是,在这种情况下,我们的“应用程序”是完全无状态的。
为了提供一些背景知识,以下是该项目的一些粗略要求:
- 项目包含一组组件,这些组件可以组装到一个页面中,并根据配置文件给出一个主题。
- 这些组件中的每一个都包含自己的模块化 CSS,用 SASS 编写。
- 每个导出的页面都是静态的,并且捆绑包实际上已从导出目录中删除。(是的,如果项目以简单地渲染一系列单一的、静态的页面结束,React 有点过头了。项目的未来状态将包括在此之上的 UI,React 应该非常适合,但是-- 所以最好现在用 JSX 编写这些组件。)
- CSS 是从包中提取的
extract-text-webpack-plugin
- 在最终导出的元素上没有直接内联样式,这不是可以更改的要求。 - 作为页面主题信息的一部分,设置了 SASS 变量,然后 SASS 将这些变量用于每个 JSX 组件。
- 只有在给定页面的配置文件中引用的 JSX 组件的 SASS 变量才会被编译和传递,
sass-loader
以在编译 CSS 时使用。
这就是事情发生的地方:
假设我有 5 个 JSX 组件,方便地命名为component_1
、component_2
、component_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>
);
},
});
现在假设我们有两个页面:
page_1
包含component_1
和component_2
page_2
包含component_3
,component_4
, 和component_5
这些页面都是使用一个通用layout
组件构建的,该组件以如下方式决定使用哪些块:
return (
<html lang='en'>
<body>
{this.props.components.map((object, i) => {
const Block = component_templates[object.component_name];
return <Block key={i}{...PAGE_DATA.components[i]} />;
})}
</body>
</html>
);
上面迭代了一个包含我需要的 JSX 组件(对于给定页面)的对象,现在以以下方式创建它:
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;
}
所以一般流程是:
- 从页面配置中收集包含的组件列表。
- 创建一个
require
对每个此类组件执行 a 的对象,并使用组件名称作为键存储结果。 - 单步执行该对象并将这些 JSX 组件中的每一个都包含到
layout
.
所以,如果我只是遵循依赖树,这应该一切正常。然而,Webpack 试图包含我们所有的组件,而不管layout
实际加载的是什么。由于我只为页面上实际使用的组件加载 SASS 变量,这会导致 Webpack在尝试处理与未使用模块关联的 SASS 文件undefined variable
时抛出错误。sass-loader
这里需要注意的一点是:静态页面渲染得很好,甚至可以在 Webpack 的开发服务器中工作……我只是遇到了很多错误,而 Webpack 则很适合。
我最初的想法是,可以在我用于 JSX 文件的加载器的配置中找到解决方案,如果 Webpack 试图加载所有内容,我可能只需要告诉加载器不加载什么。我为此使用了`babel-loader:
{ test: /\.jsx?$/,
loader: 'babel-loader',
exclude: [
'./path/to/components/component_1/',
],
query: { presets: ['es2015', 'react'] }
},
那里的exclude
条目是新的,并且似乎不起作用。
所以这有点像中篇小说,但我想在信息太多的一面犯错,而不是太少。我错过了一些简单的事情,还是想做一些疯狂的事情?两个都?
如何让未使用的组件不被 Webpack 处理?