やりたいこと
外部CSSフレームワークのCSSを自分のjsにbundleせずに読み込みたい。
例えばBootstrapのCSSを使いたいけど、自分のReactコンポーネントではcss-modules
やreact-css-modules
を使いたいので、vendorとは分けたいという場合の忘備録。
- 必要なものをインストール
npm install --save webpack webpack-cli css-loader extract-text-webpack-plugin@next react-css-modules css-modules
1. vendorのscssファイルをまとめたものを用意する。
/vendor/css/import.scss
2. 自分のscssファイルは各自コンポーネントで読み込む。
src/index.js
とかでimport styles from './index.scss';
で使う。
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './index.scss';
class App extends React.Component {
render() {
return (
<div className={styles.main}>
<h1>Hello React World</h1>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector('#main'));
3. webpackのentryとoutputを編集。
entry: {
bundle: './src/index.js',
vendor: './vendor/css/import.scss',
},
output: {
path: dist,
filename: '[name].js',
},
4. cssのruleを設定する。
vendorのcssはmodulesをfalseにして、extract-text-webpack-plugin
でjsとcssを分割する。
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractCSS = new ExtractTextPlugin({ filename: '[name].css', allChunks: true });
// bundle
const bundleSassRule = {
test: /\.(css|scss)$/,
exclude: fs.realpathSync('./vendor'),
use: extractCSS.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
url: true,
localIdentName: '[name]__[local]--[hash:base64:5]',
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
outputStyle: 'expanded',
sourceComments: true,
indentWidth: 2,
},
},
],
})
};
// vendor
const vendorSassRule = {
test: /\.(css|scss)$/,
include: fs.realpathSync('./vendor'),
use: extractCSS.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
outputStyle: 'expanded',
sourceComments: true,
indentWidth: 2,
},
},
],
})
};
module.exports = {
module: {
rules: [jsRule, bundleSassRule, vendorSassRule ...],
},
};
これで以下のファイルが出力されるはず。
bundle.js
bundle.css
vendor.js
vendor.css
あとはhtmlでbundle.jsとbundle.css、vendor.cssを読み込めばOK。
その他
entry で vendor: './vendor/css/import.scss',
を指定しているのにvendor.jsができちゃう問題はissueにも上がっていますが、解決方法はないようです。
とはいえ、今どきはstyled-component使うか・・・。