[ReactJS] ist das Javascript-Framework von Facebook. Es ist Open Source. !!!Webpack Webpack ist ein sogenannter Transpiler, der Javascript Code parsed und für das Web, dem Browser oder zum Debugging packt. [ReactJS] kommt mit einer internen Konfiguration von Webpack. Sobald man etwas ändern möchte, braucht man eine "webpack.config.js" im Projekt. {{{ module: { rules: [{ test: /\.jsx$/i, include: path.resolve(__dirname, "src"), use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env", ["@babel/preset-react", {"runtime": "automatic"}] ] } } }, { test: /\.ts$/i, include: path.resolve(__dirname, "src"), use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env", "@babel/typescript" ] } } }, { test: /\.js$/i, include: path.resolve(__dirname, "src"), use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env" ] } } }, { test: /\.css$/i, include: [ path.resolve(__dirname, "src"), path.resolve(__dirname, "node_modules") ], use: ["style-loader", "css-loader", "postcss-loader"] }, { test: /\.(png|svg|jpe?g|gif|woff2?|ttf|eot)$/, use: "file-loader" }] }, resolve: { extensions: [".js", ".jsx", ".css", ".ts"] } }}} !!!Typescript Komponenten .tsx [ReactJS] kann auch mit Typescript kombiniert werden. Dazu muss in der webpack.config.js folgende Regel für den Babel-Loader konfiguriert werden: {{{ { test: /\.(jsx|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env", ["@babel/preset-react", {"runtime": "automatic"}], "@babel/preset-typescript" ] } } } }}} Zusätzlich muss in der TS-Config angegeben werden, dass es sich um Extended Javascript handelt: {{{ { "compilerOptions": { "jsx": "react-jsx" } } }}} !!!Typescript nur Typen generieren Der Typescript-Compiler hat eine eigene Konfiguration: {{{ { "compilerOptions": { "target": "es5", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "preserve" }, "include": [ "src" ] } }}} !!!Tailwind-Config Tailwind ist ein Style-Framework, welches versucht ohne Stylesheets auszukommen. Für [ReactJS] wird meist eine Konfiguration benötigt: {{{ /** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], theme: { extend: {}, }, plugins: [], } }}} !!!Typescript mit Decorators Von Typescript sind sehr viele Varianten mit sogenannten Decorators (Annotationen etc.) im Umlauf. Folgende Konfiguration unterstützt einige davon. webpack.config.js: {{{ use: { loader: "babel-loader", options: { presets: [ "@babel/preset-env", "@babel/preset-typescript", ["@babel/preset-react", {runtime: "automatic"}] ], plugins: [ "@babel/syntax-dynamic-import", ["@babel/plugin-proposal-decorators", {version: "2023-05", decoratorAutoAccessors: true}], "@babel/plugin-proposal-object-rest-spread", ["@babel/plugin-transform-class-properties"] ] } }}} tsconfig.json: {{{ { "compilerOptions": { "jsx": "react-jsx", "experimentalDecorators": true, "emitDecoratorMetadata": true, "target": "ESNext", "moduleResolution": "node" } } }}} __Hinweis:__ Viele Konfigurationen sind inkonsistent. Es ist schwierig herauszufinden, welche Kombinationen dieser Plugins mit welchen Parametern zusammen arbeiten. !!!LitJS Adapter Folgender Adapter vereinfacht das Einbinden von LitJS-Komponenten: {{{ import {createComponent} from "@lit/react"; import React from "react"; export function lit(tag) { return createComponent({ tagName: customElements.getName(tag), elementClass: tag, react: React }); } export default function Lit({tag, children, ...props}) { const Element = lit(tag); return <Element {...props}>{children}</Element>; } }}} Oder in Typescript: {{{ import {ReactWebComponent, createComponent} from "@lit/react"; import React from "react"; declare var customElements: any; type Constructor<T> = { new (): T; }; type LitProps<I> = { tag: Constructor<I>, children: React.ReactNode, rest: any[] }; type AnyComponent = (props: any) => React.ReactElement; export function lit<I extends HTMLElement>(tag: Constructor<I>): ReactWebComponent<I> { return createComponent({ tagName: customElements.getName(tag), elementClass: tag, react: React }); } export default function Lit<I extends HTMLElement>({tag, children, ...rest}: LitProps<I>): React.ReactElement { const Element: AnyComponent = lit(tag) as AnyComponent; return <Element {...rest}>{children}</Element>; } }}}