Create web components using React.
npm i react-shadowed
npx create-react-app my-app --template typescript
cd my-app
npm install @craco/craco react-shadowed
Edit ./package.json
, replacing existing calls to react-scripts
with calls to craco
in scripts
.
"scripts": {
- "start": "react-scripts start",
+ "start": "craco start",
- "build": "react-scripts build",
+ "build": "craco build"
- "test": "react-scripts test",
+ "test": "craco test"
}
Create ./craco.config.js
and configure style-loader
to pass styles into react-shadowed
which will inject them into Shadow DOM rather than the host page.
const { getLoader, loaderByName } = require('@craco/craco');
module.exports = {
webpack: {
configure: (config) => {
const { isFound, match } = getLoader(
config,
loaderByName('style-loader')
);
if (isFound) {
match.parent[match.index] = {
loader: 'style-loader',
options: {
insert: function (element) {
require('react-shadowed').addStyleElement(element);
},
},
};
}
return config;
},
},
};
Replace the contents of index.tsx
with:
import { createWebComponent } from 'react-shadowed';
import './index.css';
createWebComponent('my-hello', { name: String }, async () => {
// the components and React itself are lazy loaded upon instantiation of a component to reduce initial bundle size
// initial bundle size is ~25KB
const { default: React } = await import('react');
const { Hello } = await import('./components/Hello');
// host attributes are parsed and passed through as props
return ({ name }) => (
<React.StrictMode>
<Hello name={name ?? 'Anonymous'} />
</React.StrictMode>
);
});
Add the components to your index.html
<app-hello name="Joe"></app-hello>
<!-- Hello, Joe -->
<app-hello name="Jane"></app-hello>
<!-- Hello, Jane -->
Run it
npm run start
Follow the Install Tailwind CSS with Create React App guide to add Tailwind CSS to your Web Components. Nothing special needs to be done to work with react-shadowed
.