Change Dynamic loaded Svg path in Rollup - reactjs

I am using rollup for configuring my React build. In one of the components, I am lazyloading svg file and integrating it to the component JSX using the svgr plugin. I am facing an issue as my svg file is currently inside the same component where it is getting consumed. After build, its SVG path is changing but not changing at the place where it is imported into the component.
My component file:
ImportedIconRef.current = await import(`./svg/${icon}.svg`).then((h) => {
return h.default;
});
Code folder:
Src
|- components
|- Icon
|- svg
|- index.tsx
Build Folder:
Build
|- Assets
|-svg
|- index.js
After Build I am getting an error for unable to find svg on path './svg'
My rollup config:
export default {
input: process.env.STORYBOOKMODE === 'public' ? 'src/publicIndex.ts' : 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM'
},
exports: 'named'
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM'
},
exports: 'named'
}
],
external: ['react', 'react-dom', 'react-is'],
plugins: [
resolve(),
image({
include: /\.(gif)$/
}),
typescript({
useTsconfigDeclarationDir: true
}),
postcss({
extract: 'main.css',
minimize: 'main.css'
}),
svgr({
svgoConfig: {
plugins: [{ removeTitle: false }, { removeViewBox: false }]
}
}),
copy({
targets: [
{
src: 'src/components/Icon/svg',
dest: 'build/assets'
}
]
})
]
}

Related

Rollup when bundling multiple files the output.dir option must be used

My Rollup Config worked in Rollup version 2. I try to migrate the rollup package to Version 3.15.0.
Rollup claims that i need the output.dir option instead of using output.file. How can i achieve the same behaviour with using the output.dir option.
Problems with rollupjs configuration
this post doesnt really help me.
rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import typescript from '#rollup/plugin-typescript';
import dts from 'rollup-plugin-dts';
const packageJson = require('./package.json');
export default [
{
external: ['react', 'react-dom'],
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
},
],
plugins: [resolve(), commonjs(), typescript({ tsconfig: './tsconfig.json' })],
},
{
external: ['react', 'react-dom'],
input: 'dist/esm/index.d.ts',
output: [{ file: 'dist/index.d.ts', format: 'esm' }],
plugins: [dts()],
},
];
I tried to split the output object:
{
input: 'src/index.ts',
output:
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
},
},
{
input: 'src/index.ts',
output:
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
},
}
Since the "inlineDynamicsInports" is deprecated this is not an option

Fail to integrate scss in my rollup build

What I try to achieve
I'm trying to create a little library for private use - basically just splitting up some code into lib (product) and app (project) code.
All my source code lives in /src folder which contains React, TypeScript and SCSS code. It would be great, if I can use the SCSS imports directly in React like: import './_button.scss';
I have another SCSS file: src/style/_main.scss it includes some mixins, global styles, resets etc.
Config files
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import terser from '#rollup/plugin-terser';
import typescript from '#rollup/plugin-typescript';
import url from '#rollup/plugin-url';
import dts from 'rollup-plugin-dts';
import scss from 'rollup-plugin-scss';
import { format, parse } from 'path';
import pkg from './package.json' assert { type: 'json' };
const getTypesPath = (jsFile) => {
const pathInfo = parse(jsFile);
return format({
...pathInfo,
base: '',
dir: `${pathInfo.dir}/types`,
ext: '.d.ts',
});
};
export default [
{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
interop: 'compat',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
{
file: pkg.module,
format: 'esm',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
],
plugins: [
resolve({ browser: true }),
commonjs({ extensions: ['.js', '.jsx', '.ts', '.tsx'] }),
typescript({ tsconfig: './tsconfig.build.json' }),
url(),
scss({
failOnError: true
}),
json(),
terser(),
],
external: ['react', 'react-dom'],
},
{
input: getTypesPath(pkg.module ?? pkg.main),
output: [{ file: pkg.types, format: 'esm' }],
plugins: [dts()],
},
];
My tsconfig.build.json looks like this:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./types",
"declaration": true,
"declarationDir": "./types",
"allowSyntheticDefaultImports": true
}
}
Where I struggle
The main issue right now is, that it imports my SCSS file in the definition file e.g. button.d.ts looks like:
import type { FunctionComponent } from 'react';
import type { IButtonProps } from './button.type';
import './_button.scss';
export declare const Button: FunctionComponent<IButtonProps>;
[!] RollupError: Could not resolve "./_button.scss" from "build/esm/types/button/button.d.ts"
Which is indeed a problem, but how can I fix it?
I also get the error:
Error:
#use rules must be written before any other rules.
╷
4 │ #use 'src/style/util/mixin';
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
stdin 4:1 root stylesheet
But it does not really make a lot of sense, since my _button.scss partial has this written on the first line.
My Question
How do I make it work so that I can use SCSS in my library? The best case would be that I don't have to touch my original code. I just want to transpile/bundle it so I can use it somewhere else. Any advice?
After hours of probing, I finally made it work.
The issue was, that it bundled all my sass styles and it did not take into account, that I am using the new #use module syntax. Because everything got concatenated into one big file, #use syntax got placed in the middle of the file resulting in an error. Apparently, only the old #import syntax is properly supported by rollup-plugin-scss - or I was just too incapable of making it work.
So I switched to the https://anidetrix.github.io/rollup-plugin-styles/
library to process the files. All I had to do is to use the styles plugin and I set mode: 'inject' it then injected the styles into my [esm|cjs]/index.js file. Upon importing the lib in the app and starting it, the styles got applied.
Besides, I also had to externalize the imports from the index.d.ts.
The updated config file:
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import terser from '#rollup/plugin-terser';
import typescript from '#rollup/plugin-typescript';
import url from '#rollup/plugin-url';
import { format, parse } from 'path';
import dts from 'rollup-plugin-dts';
import external from 'rollup-plugin-peer-deps-external';
import styles from 'rollup-plugin-styles';
import pkg from './package.json' assert { type: 'json' };
const getTypesPath = (jsFile) => {
const pathInfo = parse(jsFile);
return format({
...pathInfo,
base: '',
dir: `${pathInfo.dir}/types`,
ext: '.d.ts',
});
};
export default [
{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
interop: 'compat',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
{
file: pkg.module,
format: 'esm',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
],
external: ['react', 'react-dom'],
plugins: [
external(),
resolve({
browser: true,
}),
url(),
styles({
mode: 'inject'
}),
json(),
commonjs({
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
typescript({
tsconfig: './tsconfig.build.json',
}),
terser(),
],
},
{
input: getTypesPath(pkg.module ?? pkg.main),
output: [
{
file: pkg.types,
format: 'esm',
},
],
external: [/\.(sass|scss|css)$/] /* ignore style files */,
plugins: [dts()],
},
];

Vite - Multiple library entry points

After a few hours, I managed to build my custom library with multiple entry points using vite.
I want to know if there is a better way to solve this problem.
// vite.config.ts
export default defineConfig({
plugins: [react()],
build: {
rollupOptions: {
input: {
index: resolve(__dirname, 'src/index.ts'),
hooks: resolve(__dirname, 'src/hooks.ts'),
},
external: [...Object.keys(peerDependencies), ...Object.keys(dependencies)],
output: [
{
dir: resolve(__dirname, 'dist'),
format: 'es',
entryFileNames: "[name].[format].js",
globals: {
react: 'React',
},
},
{
dir: resolve(__dirname, 'dist'),
format: 'cjs',
entryFileNames: "[name].[format].js",
globals: {
react: 'React',
},
}
],
},
sourcemap: true,
}
})
The build generate this files:

Rollup: inject "import index.css" into the index.ts file

I have a project that I want to create an NPM package from it.
My stack is: React, Typescript, less, and AntD.
When I'm creating a bundle with rollup.js, everything workes fine, but, the import CSS isn't injected to the top of the index.ts that I'm exporting. the only way I was able to have the CSS code in another project is by explicitly importing the CSS file (import "mypackage/dist/index.css").
I'm searching for a way to config rollup to inject the line import "./index.css" to the beginning of the main index.ts file. I have tried a lot of plugins of css/less, with no success.
Here is my current rollup.config.js:
import typescript from "rollup-plugin-typescript2";
import postcss from "rollup-plugin-postcss";
import pkg from "./package.json";
export default {
input: "src/index.tsx",
output: [
{
file: pkg.main,
format: "esm",
exports: 'named',
sourcemap: true,
strict: false,
},
],
plugins: [
postcss({
extensions: ['.less', '.css'],
minimize: true,
modules: true,
use: {
sass: null,
stylus: null,
less: { javascriptEnabled: true },
},
extract: true,
}),
typescript({
objectHashIgnoreUnknownHack: true,
sourceMap: true,
inlineSources: true,
}),
],
external: ["react", "react-dom"],
};

Rollup EMFILE: too many open files, with material-ui icons

I have a design system that is built on top of Material-ui version 5. I use rollup as my bundler.
In one of of the custom components, I import an icon from Mui5 import { Search } from "#material-ui/icons"
When I build using rollup I get the following error which I'm unsure how to fix:
!] Error: Could not load E:\project\node_modules\#material-ui\icons\esm\TransitEnterexitSharp.js
(imported by node_modules\#material-ui\icons\esm\index.js): EMFILE: too many open files, open 'E:\project\node_modules\#material-ui\icons\esm\TransitEnterexitSharp.js'
What config am I missing from rollup? It has the following config:
export default {
input: "src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true
},
{
file: packageJson.module,
format: "esm",
sourcemap: true
}
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
babel({
plugins:
[
// comes from https://material-ui.com/guides/minimizing-bundle-size/#option-2
[
'babel-plugin-import',
{
'libraryName': '#material-ui/core',
'libraryDirectory': 'esm',
'camel2DashComponentName': false
},
'core'
],
[
'babel-plugin-import',
{
'libraryName': '#material-ui/icons',
'libraryDirectory': 'esm',
'camel2DashComponentName': false
},
'icons'
]
],
exclude: 'node_modules/**',
runtimeHelpers: true
}),
typescript({ useTsconfigDeclarationDir: true }),
svgr(),
image(),
copy({
targets: [
{
src: "package.json",
dest: "dist"
}
]
})
]
};
I have also tried playing with umidbekk/babel-plugin-direct-import but to no avail.
Turns out this was fixed in Rollup v2.53.0 that referenced my exact issue https://github.com/rollup/rollup/pull/4170#issue-684709217

Resources