Individual component exports with Rollup instead of one massive index.js file? - javascript

I’m working on a proprietary component library built with React and using Rollup to bundle everything. Currently, it’s bundling everything into these files:
dist
├ cjs
│ └ index.js (1.7mb)
└ esm
└ index.js (1.7mb)
My hope is that I could instead have every component be bundled individually so the consuming app doesn’t have to download a huge index.js file, but this may be where my inexperience with Rollup kicks in.
I currently have a single entrypoint for Rollup:
input: [
'src/index.js',
],
My index.js file looks something like this (but with many more components):
import { Badge } from './components/Badge';
import { Button } from './components/Button';
import { CardFooter } from './components/CardFooter';
import { CardHeader } from './components/CardHeader';
import { CardTagList } from './components/CardTagList';
import { CardToolbar } from './components/CardToolbar';
import { CartAnimation } from './components/CartAnimation';
export {
Badge,
BasePrice,
Button,
CardFooter,
CardHeader,
CardTagList,
CardToolbar,
CartAnimation,
};
What do I have to do to ensure that components are each bundled separately and can still be imported in the apps that use the library with:
import { Button } from '#company/component-library';
Here is my full config as it stands today:
import { babel } from '#rollup/plugin-babel';
import { terser } from 'rollup-plugin-terser';
import commonjs from '#rollup/plugin-commonjs';
import dynamicImportVars from '#rollup/plugin-dynamic-import-vars';
import eslint from '#rollup/plugin-eslint';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import stylelint from 'rollup-plugin-stylelint';
import styles from 'rollup-plugin-styles';
require('dotenv').config();
export default {
external: [
'react',
'react-dom',
'styled-components',
],
input: [
'src/index.js',
],
output: [
{
// Bundle into ESM for modern consumers.
// Only ESM build can currently be tree-shaken.
dir: 'dist/esm',
format: 'esm',
},
{
// Bundle into CJS for other consumers.
dir: 'dist/cjs',
format: 'cjs',
},
],
plugins: [
eslint({
include: '**/*.js',
throwOnError: true,
}),
stylelint(),
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**',
}),
resolve({
browser: true,
}),
styles(),
commonjs(),
json(),
dynamicImportVars({}),
terser(),
],
};
Note: Probably not important, but this project is published to npm as a private repo, but currently the app that uses it installs it using a commit hash.

You could try adding the preserveModule
export default {
preserveModules: true,
...
}

I have done some tweek to the rollup config. My problem statement was to export custom elements seperately. Find my custom solution below:
function generateComponentConfig() {
const dir = fs.readdirSync("./src/web-components");
return dir.map(folderName => {
return {
input: [`src/web-components/${folderName}/index.js`],
output: [
{ file: `public/build/wc/${folderName}.mjs`, 'format': 'es' },
{ file: `public/build/wc/${folderName}.js`, 'format': 'umd', name: folderName }
],
plugins: [
svelte({ compilerOptions:{customElement: true}, emitCss: false, include: /\.wc\.svelte$/ }),
svelte({ compilerOptions: {customElement: false}, emitCss: false, exclude: /\.wc\.svelte$/ }),
resolve()
]
};
})};
Use the above function in your export as below
export default [
...generateComponentConfig(), {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js',
},
plugins: plugins(),
watch: {
clearScreen: false,
}}];

Related

Invalid hook call - React. (Duplicated React version in app) when i try npm-link. Rollup.config

I've been stuck on this for like two days. I am trying to make a React component. But after I built the package with rollup.js, I tried to test it with the npm link, but it didn't work.
Yes, I tried to use the npm link in node_modules/react in my lib and it didn't work. Thank for any suggestion.
rollup.config.js
import babel from 'rollup-plugin-babel';
import resolve from '#rollup/plugin-node-resolve';
import external from 'rollup-plugin-peer-deps-external';
import pkg from './package.json';
import path from 'path';
export default [
{
input: 'src/index.js',
external: [...Object.keys(pkg.peerDependencies)],
output: [
{
file: 'dist/index.js',
format: 'cjs',
},
{
file: 'dist/index.es.js',
format: 'es',
exports: "named",
}
],
plugins: [
babel({
exclude: "node_modules/**",
presets: [['#babel/preset-react', {"runtime": "automatic"}]]
}),
external(),
resolve({ dedupe: [...Object.keys(pkg.peerDependencies)] ,moduleDirectory: path.resolve('./node_modules/react'), extensions: ['.js', '.jsx']}),
]
}
]

why css is not work corectly on vite lib mode?

I want to create a new npm package and I have a problem with vite lib mode.
I want my package to export some UI components that has some styles, project works fine on yarn dev but when I build it the style.css file inside dist directory is not used anywhere, so the styles not applied to the components
this is my vite.config.ts file
import { resolve } from "path";
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import dts from "vite-plugin-dts";
export default defineConfig({
plugins: [
react(),
dts({
insertTypesEntry: true,
}),
],
build: {
lib: {
entry: resolve(__dirname, "src/main.tsx"),
name: "MyLib",
fileName: "my-lib",
},
rollupOptions: {
external: ["react", "react-dom"],
output: {
globals: {
react: "React",
"react-dom": "ReactDOM",
},
},
},
},
});
and this is dist folder :
I know I can import my styles separately like :
import Skeleton from "skeleton-sh";
import "skeleton-sh/style";
but I want is to just import package like import Skeleton from "skeleton-sh"; and its import the styles for me

Rollup doesn't bundle all the files exported in my input src

I have a problem. I'm currently making a component library for react, it works perfectly in storybook. But when I do a npm rollup, or install my package from npm. I look inside the cjs and esm folders and not all my necessary files are there.
Here are my config files:
const packageJson = require("./package.json");
export default [
{
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" }),
],
},
{
input: "dist/esm/types/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
},
];
rollup.config.ts
export * from "./components";
export * from "./core";
export * from "./themes";
export * from "./hooks";
src/index.ts
export { default as GlobalTheme } from "./global-theme";
export { default as LightTheme } from "./light-theme";
export { default as DarkTheme } from "./dark-theme";
themes/index.ts
When I try to use my library in another project it gives me a lot of compile errors :
Failed to parse source map from '...\node_modules\#gitname\LIBRARY_NAME\src\themes\light-theme.ts' file: Error: ENOENT: no such file or directory
and the same message for every single component I created in the library.
I'm honestly stuck, I tried every solution on the internet none worked.
Thank you in advance for your help
It has to do with way you are importing your components. I had exactly the same issue with the same configuration as you have.
In my case I had something like:
{
input: "dist/types/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
}
When you are using the components you have to import from where the actual bundled files are. In my case it was in dist folder. so just import it like so,
Import {Button} from "#yourlib/your-lib/dist"

How to include Tailwind CSS styles from React component library into the app CSS bundle?

G'day,
I am building a React component library with TailwindCSS and ViteJS. The library outputs each component as a separate JS file, for example:
// #components-library/src/ComponentA.jsx
export default function ComponentA() {
return <div className="flex justify-center">Component A</div>;
}
// Bundle Output: #components-library/dist/ComponentA.js
import { j as jsx } from "./jsx-runtime.js";
import "react";
function ComponentA() {
return /* #__PURE__ */ jsx("div", {
className: "flex justify-center",
children: "Component A",
});
}
export { ComponentA as default };
The app that is consuming this components library is also using Tailwind. However, the styles are not applied to the imported component. App-specific styles are working fine.
/* app/src/index.css */
#tailwind base;
#tailwind components;
#tailwind utilities;
// app/src/App.jsx
import CompoenntA from "#component-library/ComponentA";
export default function App() {
return (
<div className="p-10">
<ComponentA />
</div>
);
}
Awaiting expert advice.
Thank you!
Currently, I am also working on a similar project as like as you. I have built my component library with rollup. It generated a CSS file then imported that CSS file to my main package.
My Rollup Config
import resolve from "#rollup/plugin-node-resolve";
import babel from "#rollup/plugin-babel";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "#rollup/plugin-typescript";
import { terser } from "rollup-plugin-terser";
import external from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import swc from "rollup-plugin-swc";
import filesize from "rollup-plugin-filesize";
const packageJson = require("./package.json");
export default [
{
input: "index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: false,
name: "#ht/components",
},
{
file: packageJson.module,
format: "esm",
sourcemap: false,
},
],
plugins: [
babel({
// this is needed because we're using TypeScript
babelHelpers: "bundled",
extensions: [".ts", ".tsx"],
}),
external(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
postcss({
config: {
path: "./postcss.config.js",
},
extensions: [".css"],
minimize: true,
extract: "lib.css",
}),
swc({
jsc: {
parser: {
syntax: "typescript",
},
target: "es2018",
},
}),
terser(),
filesize(),
],
},
];
Main Package's index
import "#ht/components/dist/cjs/lib.css";
import "./assets/css/tailwind.css";
You should add the path of the component to the tailwind.config.js.
In my case, my component library is symlinked to the current project using yarn link and the same problem was happening. Here is what I added in tailwind.config.js:
module.exports = {
// use content instead of purge if using tailiwind v3
purge: [
"./src/**/*.{js,jsx,ts,tsx}",
"./public/index.html",
// this line fixed the issue for me
"./node_modules/{component-library-name}/src/**/*.{js,jsx,ts,tsx}"
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {}
},
variants: {
extend: {}
},
plugins: []
};

rollupjs dynamic require not bundling

I've a component library with an Atom component that have an external lib for do a specific task. This external lib (imported in this component) have a dynamic svg import like that:
require('../flags/' + countryCode.toLowerCase() + '.svg') and I can compile it without any error. But when I use this lib give me that error: Can't resolve '../flags'.
There's my rollup.config.js
import { nodeResolve } from "#rollup/plugin-node-resolve";
import postcss from "rollup-plugin-postcss";
import babel from '#rollup/plugin-babel';
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import commonjs from '#rollup/plugin-commonjs';
import svg from 'rollup-plugin-svg'
import path from 'path'
export default {
input: "src/index.js",
output: {
file: "lib/bundle.js",
format: "cjs",
},
external: [
'react',
'react-dom',
'prop-types',
],
plugins: [
peerDepsExternal(),
nodeResolve({
extensions: [".jsx", ".js"],
}),
postcss({
extract: true,
namedExports: true,
extensions: ['.sass', '.scss'],
modules: true,
use: [
[
'sass', {
includePaths: [path.resolve('node_modules')]
}
]
]
}),
babel({
babelHelpers: 'runtime',
exclude: 'node_modules/**',
}),
commonjs(),
svg()
],
};
How I can fix this problem? I cannot change the dynamic import because it's an external lib, any other solution?
Have you tried:
...,
commonjs({
dynamicRequireTargets: 'path/to/your/file'
}),
...

Categories