Reputation: 9379
I'm developing a large React component that I want to import into another React app. (I could have done it all as one big app, but I decided to separate this component into a its own project so that I could focus on the component separately.) It uses its own stylesheets, which it pulls in with "require('path/to/stylesheet.[s]css')".
For development, I serve it with webpack-dev-server which takes care of loading and pre-processing those stylesheets. My problem is that I don't know how to deploy the component so that another app can include it without breaking when the browser encounters those calls to require(path/to/stylesheet).
I've found lots of examples where projects use webpack-dev-server for development, but invoke babel (or other pre-processors) directly in order to deploy components to a dist/ directory, so this seems to be a common practice. But what to do about those invocations of "require('path/to/stylesheet.[s]css')"? Without webpack and its loaders to rely on, they all fail.
Ideally, I'd like to be able to use webpack for both development and production. Then I could deploy my component as a complete bundle and the css would be included in the code. I tried this earlier but it didn't work. It also has the disadvantage of making it hard for the main app to over-ride the styles in the component.
I suppose another way might be to set up my pipeline so that a main.scss includes all the other stylesheets and let Sass output a single style.css file that the consuming app has to include separately. Less elegant, but it makes it easier to override these styles.
I'm still mastering React and its eco-system, so I'd love to know what the best practice is for this in case anyone knows.
Upvotes: 0
Views: 309
Reputation: 136
You need to run webpack and bundle all of your JS/CSS so that it can be consumed in your other project. If you use the correct loaders, the CSS is bundled directly into your JS bundle. Or, you can use a different loader to have webpack generate you a nice style.css file that bundles all your require(/path/to/css) into one file.
There are three or four basic things you need to do (Assuming webpack@3.*):
Be sure to make your bundle.js file the entry point in your package.json
Here is a good example of what you are trying to do: (This example works for server-side rendering as well as browser rendering. The BABEL_ENV lets us only require css files on the browser.)
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV;
console.log('Environment: ', env)
module.exports = {
devtool: 'source-map',
entry: env == 'production' ? './src/components/index.js' : './src/index.js',
output: {
path: env !== 'production' ? require('path').resolve('./dev'): require('path').resolve('./dist'),
filename: 'bundle.js',
publicPath: '/',
library: 'reactPorto',
libraryTarget: 'umd'
},
externals: env == 'production' ? [
'jquery',
'react',
'react-dom',
'react-bootstrap',
/^react-bootstrap\/.+$/,
'classnames',
'dom-helpers',
'react-owl-carousel',
'react-owl-carousel2',
'uncontrollable',
'warning',
'keycode',
'font-awesome'
] : [],
devServer: {
inline: true,
contentBase: './dev',
staticOptions: { index: 'test.html' },
historyApiFallback: {
rewrites:[{ from: /./, to: 'test.html' }],
},
hot: true,
},
plugins: [
// new ExtractTextPlugin({
// filename: 'style.css',
// allChunks: true
// }),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(env || 'development'),
'BABEL_ENV': JSON.stringify(env || 'development')
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
...(env != 'production' ? [new webpack.HotModuleReplacementPlugin()] : []),
...(env == 'production' ? [new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } })] : []),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: [
'es2015',
'react',
'stage-2',
...(env != 'production' ? ['react-hmre'] : [])
],
plugins: []
}
}
},
{
test : /(\.css|\.scss)/,
// exclude: /node_modules/,
// use : ExtractTextPlugin.extract({
// use: [
// 'isomorphic-style-loader',
// {
// loader: 'css-loader',
// options: {
// importLoaders: 1
// }
// },
// 'sass-loader'
// ]
// }),
use: ['iso-morphic-style-loader', 'css-loader', 'sass-loader']
},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml'},
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?mimetype=application/octet-stream"},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader"},
{test: /\.(png|jpg|jpeg)/, loader: 'file-loader' }
]
}
}
Upvotes: 1