I'm making a tree shaken component library in React with webpack@5.24.2 and mini-css-extract-plugin@1.3.9 that has to work for client side rendering and server side rendering. I want to be able to do the following, create "N" components in the library, each with their specific "SCSS" files, something like this:
// KhalComponent.tsx
import React from 'react';
import './KhalComponent.scss';
const KhalComponent = () => {
return <div className="khal-component">Khal Component</div>;
};
export default KhalComponent;
// KhalComponent.scss
.khal-component {
padding: 2rem;
background: red;
}
and when an external project does the following:
import KhalComponent from 'some-library/KhalComponent'
it gets the component along with its styles. I have this working with style-loader
but I've read that this isn't a correct configuration for production AND it DOESN'T work with SSR (using NextJS) since with style-loader
it tries to inject the styles adding them with document.createElement (document doesn't exist in the server side). So I tried migrating to using mini-css-extract-plugin
to achieve this client side AND server side. I see that mini-css-extract-plugin
does create the separate CSS files but (as far as I can tell) it doesn't let the corresponding JS file (KhalComponent.js) know that it NEEDS to load the CSS whenever KhalComponent is imported in another project.
I'm not generating an HTML file in this external component library since its just to import components JS and CSS content.
The webpack config is the following:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const entries = require('./entries');
const LIB_NAME = 'lib';
module.exports = {
entry: entries,
output: {
filename: '[name].js',
path: path.resolve(__dirname, LIB_NAME),
},
plugins: [new CleanWebpackPlugin(), new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
],
},
externals: [
{
react: 'react',
'react-dom': 'react-dom',
},
],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
devtool: 'source-map',
devServer: {
contentBase: './lib',
hot: true,
},
};
and entries.js
is:
const path = require('path');
const SRC_DIR = path.resolve('src');
module.exports = {
// Components
KhalComponent: path.join(SRC_DIR, 'KhalComponent'),
LinkComponent: path.join(SRC_DIR, 'LinkComponent'),
};
What am I missing or what tools should I use to do this? Thank you very much in advance!