プロジェクトのために古代の技術スタックに閉じ込められて数年を過ごした後、私はついに最新のフレームワークを探索し、React と Webpack に足を踏み入れる機会を得ました。これまでのところ、大部分はさわやかで楽しい経験でしたが、集合意識が解決してくれることを願って、Webpack でいくつかの問題に出くわしました。
私はWebpack 2.0のドキュメントを熟読しており、SOをかなり徹底的に検索しましたが、不足しています(この質問を取り上げただけで、これは近いですが、それが当てはまるかどうかはわかりません)。このように情報が不足しているため、次の 2 つのシナリオのいずれかを見ていると思います。
- 私がやろうとしていることは正気ではありません。
- 私がやろうとしていることは、簡単にできるという点で初歩的なことです。
...それでも、私はここにいます。
私が探しているものの短いバージョンは、環境変数に基づいて、特定の JSX コンポーネントが Webpack ビルド/バンドルに含まれないようにする方法です。現時点では、エントリ js 以降に基づいて依存関係ツリーがどのように見えるかに関係なくimported
、Webpack はすべてをプロジェクト フォルダーにバンドルしたいと考えているようです。
これはデフォルトの動作であると思います。これには意味があるためです。アプリケーションには、初期状態以外の状態のコンポーネントが必要になる場合があります。ただし、この場合、「アプリケーション」は完全にステートレスです。
背景を説明するために、プロジェクトの大まかな要件を次に示します。
- プロジェクトには、構成ファイルに基づいてページにアセンブルし、テーマを指定できるコンポーネントのバケットが含まれています。
- これらの各コンポーネントには、SASS で記述された独自のモジュラー CSS が含まれています。
- エクスポートされた各ページは静的であり、バンドルは実際にはエクスポート ディレクトリから削除されます。(はい、プロジェクトが一連の単一の静的なページを単にレンダリングするだけで終了する場合、React は少し過剰です。プロジェクトの将来の状態には、これに加えて React がかなり適しているはずの UI が含まれますが、 -- したがって、これらのコンポーネントを今すぐ JSX で作成するのが最善です。)
- CSS は以下を使用してバンドルから
extract-text-webpack-plugin
取得されます。最終的なエクスポートでは、要素にスタイルが直接インライン化されることはありません。これは変更可能な要件ではありません。 - ページのテーマ情報の一部として、SASS 変数が設定され、SASS によって各 JSX コンポーネントに使用されます。
- 特定のページの構成ファイルで参照されている JSX コンポーネントの SASS 変数のみがコンパイルされ
sass-loader
、CSS のコンパイル時に使用するために渡されます。
物事が分解される場所は次のとおりです。
component_1
、、、などの便利なタイトルの5 つの JSX コンポーネントがある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>
);
},
});
ここで、2 つのページがあるとします。
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
そのようなコンポーネントごとに forを実行し、コンポーネント名をキーとして結果を格納するオブジェクトを作成します。- このオブジェクトをステップ実行し、これらの JSX コンポーネントをそれぞれ に含めます
layout
。
したがって、依存関係ツリーに従うだけであれば、これはすべて正常に機能するはずです。ただし、Webpack は、実際に何をロードしているかに関係なく、すべてのコンポーネントを含めようとしています。ページで実際に使用されるコンポーネントの SASS 変数のみをロードしているため、未使用のモジュールに関連付けられた SASS ファイルを処理しようとすると Webpack がエラーをスローします。layout
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 で処理しないようにするにはどうすればよいですか?