Rollup React Library Output Multiple Build Folders? - reactjs

I have created a React Library with rollup, however, I have a large number of components that get exported so the file size is relatively large.
So in a project where I import the library doing the following;
import { ComponentExampleOne, ComponentExampleTwo } from 'my-react-library';
It imports the whole index file outputted via rollup (including all other components and any 3rd party dependencies), so when a user first hits the page with the import above they need to download the whole file, which is a lot bigger than I would like it to be.
For the likes of lodash where I just want to access a single function and not the entire library, I would do the following;
import isEmpty from 'lodash/isEmpty';
I want to achieve similar functionality with rollup so I can do something like
import { ComponentExampleOne } from 'my-react-library/examples';
import { ButtonRed } from 'my-react-library/buttons';
So I only import what is exported in the index.js file within an examples and buttons folder with this is as my folder structure in my library.
my-react-library/
-src/
--index.js
--examples/
---ComponentExampleOne.js
---ComponentExampleTwo.js
---ComponentExampleThree.js
---index.js
--buttons/
---ButtonRed.js
---ButtonGreen.js
---ButtonBlue.js
---index.js
I have no idea to achieve this with rollup?
This is my current rollup.config.js
import babel from 'rollup-plugin-babel';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import postcss from 'rollup-plugin-postcss';
import filesize from 'rollup-plugin-filesize';
import localResolve from 'rollup-plugin-local-resolve';
import json from 'rollup-plugin-json';
import pkg from './package.json';
import externals from 'rollup-plugin-node-externals';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
import image from 'rollup-plugin-inline-image';
import { terser } from 'rollup-plugin-terser';
const config = {
input: 'src/index.js',
watch: {
chokidar: {
usePolling: true,
paths: 'src/**'
}
},
output: [
{
file: pkg.browser,
format: 'umd',
name: 'Example'
},
{
file: pkg.main,
format: 'cjs',
name: 'Example'
},
{
file: pkg.module,
format: 'es'
},
],
external: Object.keys(pkg.peerDependencies || {}),
plugins: [
globals(),
builtins(),
externals(),
babel({ exclude: 'node_modules/**', presets: ['#babel/env', '#babel/preset-react'] }),
commonjs({
include: "node_modules/**",
namedExports: {
// left-hand side can be an absolute path, a path
// relative to the current directory, or the name
// of a module in node_modules
'node_modules/formik/node_modules/scheduler/index.js': ['unstable_runWithPriority'],
}
}),
peerDepsExternal(),
postcss({ extract: true }),
json({ include: 'node_modules/**' }),
localResolve(),
resolve({
browser: true,
dedupe: ['react', 'react-dom'],
}),
filesize(),
image(),
terser()
]
};
export default config;
Any help would be greatly appreciated.

You don't really need to do that if you use named exports and any modern bundler for building the app.
When Rollup detects you are not using some export it will be removed due to tree-shaking.
If you still want to do it pass an object with the different entries you want to the input option:
// ...
const config = {
input: {
examples: 'examples/entry/file.js',
buttons: 'buttons/entry/file.js'
},
// ...
}

Related

css module support using react Rolllup

I'm working on building out a react package (not app) and have run into my introduction to using rollup which, as I understand it, the equivalent to using webpack for react app development.
As I'm moving my code over I've run into a snag where I can't seem to work out the configuration to allow for css/scss module support, e.g.,
import React from "react";
import styles from "./Button.css"; <--- TS2307: Cannot find module './Button.css' or its corresponding type declarations.
my configuration looks like this:
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import typescript from "#rollup/plugin-typescript";
import postcss from "rollup-plugin-postcss";
import dts from "rollup-plugin-dts";
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(),
postcss({
extract: false,
modules: true,
use: ['sass'],
}),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" })
]
},
{
input: "dist/esm/types/index.d.ts",
output: [{ file: "dist/index.d.ts", format: "esm" }],
plugins: [dts()],
external: [/\.(css|less|scss)$/]
}
];
but I can't get passed the error:
TS2307: Cannot find module './Button.css' or its corresponding type declarations.
my web research has found some attempts at solving this, but nothing has worked. I can drop the css directly on the component:
import React from "react";
import "./Button.css";
But the assignment doesn't work. Any ideas on solution?

rollup with rexport interfaces and enums as typescript

I have self created library (eg: library-A) which includes a list of interfaces, enums and constants and published as a tar
I have also created another react library (eg: library-B) which consume (library-A) and use rollup to build a dist folder.
However, when I install this react library (library-B) in my main project (project-A), I cannot seem to access the interfaces, enums and constants from (library-A). Are there any ways I can use the interfaces, enums and constants from (library-A) which are re-exported by (library-B)
library-A
export interface PERSON {
name: string;
age: number;
}
export enum GENDER {
male= 'male',
female= 'female'
}
library-B -> rollup.config.js
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import typescript from 'rollup-plugin-typescript2';
import packageJson from './package.json';
const config = {
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true,
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({
tsconfig: 'tsconfig-rollup.json',
}),
postcss(),
],
};
export default config;
library-B -> index.ts
export { GENDER } from 'library-A'; // enum
export type { PERSON, CLASSES } from 'library-A'; // interfaces
project-A -> home.ts
import { GENDER } from "library-B"
GENDER.male // this is not found
If I understand it correctly, you want to access something from lib-A in lib-B and vice versa. I am not sure if this is possible but it appears to me as not a good idea.
I would suggest, if you want to share constants and interfaces in two projects, put them into lib-C and include this lib-C in lib-A and in lib-B.

Rollup ESM generates broken imports

I want to bundle a typescript react App as a component into a ES module or UMD.
But the generated ES bundle produces an invalid module js.
On bundle it gives me this hints. But I cant find any solution for this.
(!) Missing global variable names
Use output.globals to specify browser global variable names corresponding to external modules
http (guessing 'http')
...
inside the esm js bundle there are imports like these:
import http from 'http';
import https from 'https';
import url from 'url';
import require$$0 from 'stream';
...
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
And after adding it to the browser:
<script type="module" src="./index.esm.js"></script>
I got the error about the missing relative imports:
Uncaught TypeError: Failed to resolve module specifier "http". Relative references must start with either "/", "./", or "../".
Iam surely have mistakes on my rollup configuration, but I cant find the spot and happy and thankful about any hints.
...
Of course I have nodemodule imports in my app like:
import {observer} from 'mobx-react';
But rollup should handle this. Dont he?
Here is my rollup.config:
import pkg from './package.json';
import nodeResolve from "#rollup/plugin-node-resolve";
import typescript from "rollup-plugin-typescript2";
import image from "#rollup/plugin-image";
import styles from "rollup-plugin-styles";
import commonjs from "#rollup/plugin-commonjs";
import replace from "#rollup/plugin-replace";
import json from '#rollup/plugin-json';
import babel from '#rollup/plugin-babel';
import copy from "rollup-plugin-copy";
import del from "rollup-plugin-delete";
export default {
input: pkg.source,
output: [
{
file: pkg.module,
format: 'es',
sourcemap: false
},
{
file: "dist/index.umd.js",
format: 'umd',
sourcemap: true
},
],
plugins: [
del({targets: 'dist/*'}),
nodeResolve({
mainFields: ['jsnext:main', 'module', 'main'],
dedupe: [ 'react', 'react-dom' ]
}),
replace({
preventAssignment: false,
'process.env.NODE_ENV': JSON.stringify('development'),
__buildDate__: () => JSON.stringify(new Date())
}),
json(),
typescript(),
styles(),
copy({
targets: [
{src: 'public/**/*', dest: 'dist'}
]
}),
babel({ //disabled cause WebComponent integration
presets: ["#babel/preset-react"],
exclude: 'node_modules/**',
babelHelpers: 'bundled'
}),
commonjs(),
image()
]
};
I had a similar issue (though with stream module, not http), and for me the solution was to set browser: true in nodeResolve within rollup.config:
export default [
{
input: '...',
plugins: [
nodeResolve({
'browser': true,
}),
commonjs(),
],
output: {
...
}
}
];
From description of a flag:
browser
Type: Boolean
Default: false
If true, instructs the plugin to use the browser module resolutions in package.json and adds 'browser' to exportConditions if it is not present so browser conditionals in exports are applied. If false, any browser properties in package files will be ignored. Alternatively, a value of 'browser' can be added to both the mainFields and exportConditions options, however this option takes precedence over mainFields.

How do I make React components import extracted scss modules files with Rollup?

I'm making a React Component Library with Rollup with the following component setup:
//component A
import styles from './stylesA.module.scss'
const ComponentA = () => {
return(
<div className={styles.red}>Component A Styled</div>
)
}
export { ComponentA }
//stylesA.module.scss
.red {
color: red;
}
How do I configure Rollup so that my output components auto-import the generated .css files into my component? Note that I don't want the styles to be bundled into the .js files nor do I want to import the styles manually when I import the final package with import 'my-library/dist/stylesA.css'
My rollup.config.js looks like this for the moment:
// rollup.config.js
import resolve from '#rollup/plugin-node-resolve';
import babel from '#rollup/plugin-babel';
import postcss from 'rollup-plugin-postcss';
import pkg from './package.json'
export default {
input: 'src/index.js',
output: [{
dir: './dist',
format: 'cjs'
}],
plugins: [
resolve(),
babel({
exclude: 'node_modules/**',
babelHelpers: 'bundled'
}),
postcss({
modules: true,
extract: true,
minimize: true
})
],
external: Object.keys(pkg.peerDependencies || {})
};

Making package with React + TS + Storybook + Rollup problems

I'm making my own design system with React + Typescript + Storybook + Rollup.
Before publishing my lib to NPM, I wanted to test this lib in my local env.
I built my project and install like npm i ../my_lib.
I wanted to import my Button component, so I wrote a Login page.
import React from "react";
import { Button } from "#myLib/ui/src";
const Login = () => {
return (
<div>
<Button>Hello</Button>
</div>
);
};
export default Login;
In VSCode, there's no error.
But I started my dev server, this message occured.
Module parse failed: Unexpected token (1:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export interface IconProps {
| size?: number;
| fillColor?: string;
I think the rollup.config.js has problem. I tried many cases, but only interface got error.
Here is my rollup.config.js.
import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import typescript from 'rollup-plugin-typescript2';
import pkg from './package.json';
import svgr from '#svgr/rollup';
import url from 'rollup-plugin-url';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
process.env.BABEL_ENV = 'production';
export default {
input: './src/index.ts',
plugins: [
peerDepsExternal(),
resolve({ extensions }),
commonjs({
include: 'node_modules/**',
}),
typescript({ useTsconfigDeclarationDir: true }),
babel({ extensions, include: ['src/**/*'], runtimeHelpers: true }),
url(),
svgr(),
],
output: [
{
file: pkg.main,
format: 'es',
},
],
};
Is there any wrong field in my config file?

Resources