I created a UI Library with CRA. The library is published on npm. Components in the library use SVG, which I use with the syntax of
import {ReactCompoent as Icon} from 'assets / icon'
I want to use the library inside my main app that I create with react 17.0.2 and webpack 5. I add the loaders to Webpack and I can use svg as components inside Main app as -
import CalendarIcon from './Calendar.svg'
and it works.
After I install the library and import the component that use SVG as ReactComponent:
import {BadgeBox} from '@privatelib/ui/lib/src'
the app crashes. With an error of:
WARNING in ./node_modules/@privatelib/ui/lib/src/components/BadgeBox/index.js 107:1697-1707
export 'ReactComponent' (imported as 'CloseIcon') was not found in '../../assets/sm/xsmall-icon.svg' (possible exports: default)
My React UI Library:
components:
import { ReactComponent as CloseIcon } from '../../assets/sm/x-small-icon.svg';
tsconfig file:
{
"compilerOptions": {
"target": "es5",
"baseUrl": "src",
"lib": [
"dom",
"dom.iterable",
"esnext",
"es5",
"es2015",
"es2016"
],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"sourceMap": true,
"declarationMap": true,
"declaration": true,
"outDir": "lib"
},
"types": ["cypress", "cypress-file-upload"],
"include": [
"src/**/*",
"custom.d.ts",
],
}
My Main App:
webpack config:
const HtmlWebPackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const deps = require('./package.json').dependencies;
module.exports = {
output: {
filename: '[name].[contenthash:20].esm.js',
chunkFilename: '[name].[chunkhash:20].esm.js',
hashFunction: 'xxhash64',
pathinfo: false,
crossOriginLoading: false,
clean: true,
publicPath: 'auto',
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
},
devServer: {
port: 3011,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.m?js/,
type: 'javascript/auto',
resolve: {
fullySpecified: false,
},
},
{
test: /\.(css|s[ac]ss)$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack'],
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|)$/i,
type: 'asset/resource',
},
{
test: /\.(woff(2)?|eot|ttf|otf|)$/,
type: 'asset/inline',
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'sidebar',
filename: 'remoteEntry.js',
remotes: {},
exposes: {
'./SideBar': './src/components/Sidebar/index.tsx',
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom'],
},
},
}),
new HtmlWebPackPlugin({
template: './src/index.html',
}),
],
};
babelrc:
{
"presets": ["@babel/preset-typescript", "@babel/preset-react", "@babel/preset-env"],
"plugins": [
["@babel/transform-runtime"],
"babel-plugin-styled-components"
]
}