I am currently working on a React widget using Tailwind CSS, and I’ve configured the postcss-prefix-selector plugin in my webpack setup to generate unique prefixes for the Tailwind class names. The generated CSS file shows the expected prefixes, but when I embed my widget in a project that already uses Tailwind CSS, the prefixed class names are not automatically applied to the HTML elements in the widget.
Here is a snippet of my webpack configuration:
const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
const tailwindConfig = isProduction ? 'chat-bot-tailwind.config.js' : 'tailwind.config.js'
const publicPath = '/'
module.exports = {
// Entry point, from where all extraction should be made
entry: './src/chat-bot-widget.js',
// Init webpack rules to collect js, jsx, css files
resolve: {
extensions: ['.js', '.jsx', '.ts', '.css'],
preferRelative: true,
alias: {
toolComponents: path.resolve(__dirname, '../src/toolComponents'),
helpers: path.resolve(__dirname, '../src/helpers'),
components: path.resolve(__dirname, '../src/components'),
settings: path.resolve(__dirname, '../src/settings.json'),
images: path.resolve(__dirname, '../src/images'),
permissions: path.resolve(__dirname, '../src/app/permissions.json'),
'constants.js': path.resolve(__dirname, '../src/constants.js'),
constants: path.resolve(__dirname, '../src/constants'),
app: path.resolve(__dirname, '../src/app'),
views: path.resolve(__dirname, '../src/views'),
},
},
module: {
rules: [
{
// Extract and Transpile ES6+ in to ES5
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /.svg$/,
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
{
test: /.css$/,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: {
'postcss-prefix-selector': {
prefix: '.my-prefix',
transform(prefix, selector, prefixedSelector, filePath, rule) {
if (selector.match(/^(html|body)/)) {
return selector.replace(/^([^s]*)/, `$1 ${prefix}`)
}
if (filePath.match(/node_modules/)) {
return selector // Do not prefix styles imported from node_modules
}
const annotation = rule.prev()
if (
annotation?.type === 'comment' &&
annotation.text.trim() === 'no-prefix'
) {
return selector // Do not prefix style rules that are preceded by: /* no-prefix */
}
return prefixedSelector
},
},
},
},
},
},
],
},
{
test: /.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
// Extract CSS files
test: /.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},
// https://webpack.js.org/configuration/output/
output: {
path: path.resolve(__dirname, '../chat-bot-widget-dist'),
filename: 'chat-bot-widget.js',
chunkFilename: 'chat-bot-widget.chunk.js',
// Output library name
library: 'ChatBotWidget',
libraryTarget: 'umd',
publicPath: publicPath,
libraryExport: 'default',
},
// https://webpack.js.org/configuration/dev-server/
devServer: {
static: {
directory: path.join(__dirname, '../chat-bot-widget-public'),
},
hot: true,
compress: true,
port: 9001,
},
// https://webpack.js.org/configuration/plugins/
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './chat-bot-widget-public/index.html',
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
// new MiniCssExtractPlugin({
// filename: 'widget.css',
// chunkFilename: 'widget.css',
// }),
],
// https://webpack.js.org/configuration/optimization/
optimization: {
minimizer: [
(compiler) => {
const TerserPlugin = require('terser-webpack-plugin')
new TerserPlugin({
terserOptions: {
compress: {},
},
}).apply(compiler)
},
],
},
}
Despite this configuration, the prefixed class names are not being automatically applied to the HTML elements when embedded in a project.
I want to ensure that the prefixed class names are automatically applied to the HTML elements in my widget, preventing style conflicts in the host project. What steps or configurations am I missing to achieve this?
Any guidance or suggestions would be greatly appreciated