I would like to properly load css and icons into my web component, right now styles are loaded but icons are not. Here is my web component:
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App.js";
import preactbase from "primereact/resources/primereact.css";
import preacttheme from "primereact/resources/themes/lara-light-blue/theme.css";
import picons from "primeicons/primeicons.css";
class Dumb extends HTMLElement {
constructor() {
super();
console.log("HEY");
this._shadowRoot = this.attachShadow({ mode: "open" });
var style = document.createElement("style");
style.textContent = preactbase + preacttheme + picons;
var mountPoint = document.createElement("div");
this._shadowRoot.appendChild(style);
this._shadowRoot.appendChild(mountPoint);
var reactroot = createRoot(mountPoint);
reactroot.render(<App />);
}
connectedCallback() {}
}
window.customElements.define("dumb-app", Dumb);
As you can see, I am trying to wrap a minimal react spa which uses primeicons. App.js file is straightforward:
import "primeicons/primeicons.css";
import { Button } from "primereact/button";
function App() {
return (
<div>
<h1>Hello from React!</h1>
<i className="pi pi-check"></i>
<br></br>
<Button label="webcomponent" icon="pi pi-check" />
</div>
);
}
export default App;
I am using webpack with the following configuration:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const pkg = require("./package.json");
const commonPaths = require("./build-utils/config/commonPaths.js");
const isDebug = !process.argv.includes("release");
const port = process.env.PORT || 3000;
module.exports = {
entry: commonPaths.entryPath,
output: {
uniqueName: pkg.name,
publicPath: "/",
path: commonPaths.outputPath,
filename: `${pkg.version}/js/[name].[chunkhash:8].js`,
chunkFilename: `${pkg.version}/js/[name].[chunkhash:8].js`,
assetModuleFilename: isDebug ? `assets/[path][name].[contenthash:8][ext]` : `assets/[name].[contenthash:8][ext]`,
crossOriginLoading: "anonymous",
},
plugins: [
new HtmlWebpackPlugin({
template: "public/index.html",
filename: "index.html",
}),
],
devServer: {
port,
static: {
directory: commonPaths.outputPath,
},
historyApiFallback: {
index: "index.html",
},
webSocketServer: false,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
// Important: css-loader first (resolves url()), then to-string-loader
test: /\.css$/i,
use: [
{
loader: "to-string-loader",
},
{
loader: "css-loader",
options: { url: true },
},
],
},
{
// Inline modern webfonts into CSS (no network requests)
test: /\.(woff|woff2)$/i,
type: "asset/inline",
},
{
// Other assets (images, etc.)
test: /\.(png|jpg|jpeg|gif|svg|eot|ttf)$/i,
type: "asset/resource",
generator: {
filename: "assets/[name].[hash][ext]",
},
},
],
},
resolve: {
extensions: ["*", ".js", ".jsx"],
},
};
And this is the package.json:
{
"name": "y",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode production",
"start": "webpack serve --mode development"
},
"author": "",
"license": "ISC",
"dependencies": {
"@babel/preset-react": "^7.27.1",
"primeicons": "^7.0.0",
"primereact": "^10.9.7",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"to-string-loader": "^1.2.0"
},
"devDependencies": {
"@babel/core": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"babel-loader": "^10.0.0",
"css-loader": "^7.1.2",
"html-webpack-plugin": "^5.6.4",
"raw-loader": "^4.0.2",
"style-loader": "^4.0.0",
"webpack": "^5.101.3",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.2"
}
}
I can see what I am missing. I can see the <style> element filled with, I guess, all the styles I import, but no icon is redered. Full project can be fount here, thank you!