'Create React Component Library using CRACO with Create React App
I need to create a React Component Library, I want to use CRA as I want to refer to the code of the main application which is also written using CRA.
I tried babel but that only converts the JS code leaving all other files (CSS, SVG) as it is and the user of my library is not on CRA hence SVG support is not there.
// babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = ["@babel/preset-env", "@babel/preset-react"];
const plugins = ["macros"];
return {
presets,
plugins,
};
};
// package.json
{
"scripts": {
"clean": "rimraf dist/babel",
"build": "npm run clean && cross-env NODE_ENV=production babel src/lib --out-dir dist/babel --copy-files --ignore __tests__,spec.js,test.js",
}
}
I tried parcel also but that is forcing me to change my syntax of including SVG.
//.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.svg": [
"...",
"@parcel/transformer-svg-react"
]
}
}
So I tried CRACO also and used the below configurations but that is outputting JS and CSS separately and I am not able to merge them or auto-include when importing the component. I tried removing the mini-css-extract-plugin from loaders as well but not working.
//craco.config.js
const path = require("path");
const EsmWebpackPlugin = require("@purtuga/esm-webpack-plugin");
module.exports = {
webpack: {
configure: (config, { paths }) => {
//* Remove mini-css-extract-plugin from loaders
// config?.module?.rules[1].oneOf.forEach((sett) => {
// if (sett.use) {
// sett.use = sett.use.filter((u) => {
// if (u.loader && typeof u.loader === "string" && u.loader.includes("mini-css-extract-plugin")) {
// return false;
// }
// return true;
// });
// }
// });
const isEsm = process.argv.includes("--esm") ? true : false;
paths.appBuild = config.output.path = path.resolve(isEsm ? "./dist/esm" : "./dist/cjs");
// Set separate entry point when building the widget lib
// https://webpack.js.org/concepts/entry-points
config.entry = `${paths.appSrc}/lib/index.js`;
// Output a "window" module and define its name via the library key.
// This key will be what is referenced when the hub looks for
// the correct module to dynamically load after the bundle is
// injected into the DOM
// https://webpack.js.org/configuration/output
config.output.library = "swimBookForm";
config.output.libraryExport = isEsm ? undefined : "default";
config.output.libraryTarget = isEsm ? "var" : "umd";
config.output.filename = "main.js";
// Because this is being injected in the hub's index.html,
// we don't need the HTML plugin
config.plugins = config.plugins.filter(
(plugin) => plugin.constructor.name !== "HtmlWebpackPlugin"
// && plugin.constructor.name !== "MiniCssExtractPlugin"
);
// If we're including custom CSS, make sure it's bundle easily identified
const cssPluginIdx = config.plugins.map((p) => p.constructor.name).indexOf("MiniCssExtractPlugin");
if (cssPluginIdx !== -1) {
config.plugins[cssPluginIdx].options.filename = "../main.css";
}
// Exclude shared dependencies to reduce bundle size
// https://webpack.js.org/configuration/externals
config.externals = isEsm ? [] : ["react"];
// Consolidate bundle instead of creating chunks
delete config.optimization;
return config;
},
plugins: {
add: process.argv.includes("--esm") ? [new EsmWebpackPlugin()] : [],
// remove: ["MiniCssExtractPlugin"],
},
},
};
package.json
{
...
"scripts": {
"start": "react-scripts start",
"build": "craco build && craco build --esm",
"test": "craco test --env=jsdom",
"build:web": "react-scripts build"
},
...
}
What changes should I make in CRA using CRACO to make it compatible with outputting React Component Library? I am sticking with CRA and want an extended solution to it because I want to use the features provided by it eg. a simple toolchain to maintain, out-of-the-box features like CSS modules, SVG components, etc. Also, having a CRA-based solution means it'll be (most probably) compatible with upcoming cool CRA features as well.
For example we can take this repo as an example, I want to make this repo to be eligible to be used as per the given example.
Solution 1:[1]
Your question is not really clear. I suppose you want to create an npm package and embed your react component library in it.
so refer to how to create npm package.
Otherwise, if you know how to create react components, nothing more than creating a library folder with your react components. And import the components when they need to be used.
you seem being to have pb with svg usage or bundle usage of svg files? it depends on what you want to do if these svg files, if they are only needed for css features ? Or if you want to manipulate dom svg content ?
if you want to keep files as it is, and not being bundled , then put them in the public folder.
your package.json should be modified like that
{
...
"scripts": {
"start": "craco start",
"build": "craco build && craco build --esm",
"test": "craco test --env=jsdom",
"build:web": "craco build"
},
...
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | sancelot |
