Rollup + Typescript: lib/index.js concatenated modules in final output - javascript

I am creating a build process for a library we have published on NPM. We are migrating from webpack to rollup for treeshaking and ESM support.
The issue we are facing is that when we analyze the final bundle, I can see exactly what we are importing from the node_modules I cannot see the same for the main index.js and our own components/files
If I only compile the library using typescript, this the following output:
tsconfig.json
{
"include": ["src"],
"exclude": [
"lib",
"**/*.stories.tsx",
"**/*.stories.ts",
"**/*.test.ts",
"**/*.test.tsx",
"**/__mocks__/*",
"node_modules"
],
"compilerOptions": {
"noImplicitAny": false,
"noImplicitReturns": false,
"noImplicitThis": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"target": "es5",
"module": "ESNext",
"moduleResolution": "node",
"lib": ["es6", "dom", "es2016", "es2017"],
"sourceMap": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"jsx": "react",
"allowJs": false,
"suppressImplicitAnyIndexErrors": true,
"esModuleInterop": true
}
}
If I build using Rollup, this is the output:
rollup.config.js
import pkg from './package.json';
import typescript from 'rollup-plugin-typescript2';
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import external from 'rollup-plugin-peer-deps-external';
import { terser } from 'rollup-plugin-terser';
/**
* Config tweaked from: https://www.pluralsight.com/guides/react-typescript-module-create
*/
export default {
input: 'src/index.ts',
output: [
{ file: pkg.main, format: 'cjs', sourcemap: true, exports: 'named' },
{ file: pkg.module, format: 'es', sourcemap: true, exports: 'named' },
],
plugins: [
external(), // prevents from bundling peer dependencies
resolve(), // bundles third party dependencies we've installed in node_modules.
typescript({
rollupCommonJSResolveHack: true,
clean: true,
}),
commonjs({
// compiles js files into commonjs
include: /node_modules/,
namedExports: {
'node_modules/react/react.js': ['Children', 'Component', 'PropTypes', 'createElement'],
'node_modules/react-dom/index.js': ['render'],
'node_modules/react-dates/index.js': [
'DayPickerRangeController',
'CalendarInfoPositionShape',
'DateRangePicker',
'SingleDatePicker',
],
'node_modules/xss/lib/index.js': ['DEFAULT', 'whiteList'],
'node_modules/uuid/index.js': ['v4'],
},
}),
terser(), // uglify and minification of bundle
],
};
I want to be able to achieve the first result (the one using the TSC compiler) where I can keep the library project structure, but using rollup building process to take advantage of treeshaking and minification process.
What am I missing from my configuration?

you can trying by replacing your plugin's filed by the code as below:
nodeResolve({
browser: true,
dedup: ['react', 'react-dom'],
extensions,
}),
postcss({
extract: join(outputDir, 'index.css'),
modules: {
generateScopedName: cssScopeName,
},
namedExports: cssExportName,
plugins: [
postcssImport(),
],
}),
typescript({
allowNonTsExtensions: true,
useTsconfigDeclarationDir: true,
objectHashIgnoreUnknownHack: true,
tsconfigDefaults: {
compilerOptions: {
baseUrl: sourceDir,
target: 'esnext',
jsx: 'preserve',
emitDecoratorMetadata: true,
allowSyntheticDefaultImports: true,
experimentalDecorators: true,
paths: {
[[pkg.name, "*"].join("/")]: [join(outputDir, pkg.name, "*")]
}
},
}
}),
commonjs({
include: [resolve(rootPath, 'node_modules/**')],
exclude: [resolve(rootPath, 'node_modules/process-es6/**')],
namedExports:{
[resolve(rootPath, 'node_modules/react/index.js')]: [
"Children",
"Component",
"PropTypes",
"createRef",
"useEffect",
"useState",
"useContext",
"useRef", ],
[resolve(rootPath, "node_modules/react-dom/index.js")]: ["render", "findDOMNode"],
[resolve(rootPath, "node_modules/react-is/index.js")]: ["isValidElementType"]
},
}),
babel({
babelrc: false,
extensions,
presets: [
[ '#babel/preset-env', { modules: false } ],
[ '#babel/preset-react' ],
],
}),
......

Related

How to bundle .ts and .js files build in one file using rollup

I am trying to make a UI library that contained code in .jsx , now I want to make the new components in typescript (.tsx), is there a way to bundle my code in one file after running the build command.
My rollup config
import external from "rollup-plugin-peer-deps-external";
import resolve from "#rollup/plugin-node-resolve";
import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import babel from "rollup-plugin-babel";
import { DEFAULT_EXTENSIONS } from "#babel/core";
export default [
{
input: "./src/index.js",
output: [
{
file: "dist/index.js",
format: "cjs",
},
{
file: "dist/index.es.js",
format: "es",
exports: "named",
},
],
plugins: [
postcss({
plugins: [],
minimize: true,
}),
babel({
exclude: "node_modules/**",
presets: ["#babel/preset-react"],
extensions: [
...DEFAULT_EXTENSIONS,
".ts",
".tsx"
],
plugins: [
[
"transform-react-remove-prop-types",
{
removeImport: true,
additionalLibraries: ["react-style-proptype"],
},
],
typescript({
include: "src/**/*.{js,ts}"
})
],
}),
external(),
resolve(),
terser(),
],
},
{
input: "./src/index.ts",
output: [
{
file: "dist/index.js",
format: "cjs",
},
{
file: "dist/index.es.js",
format: "es",
exports: "named",
}
],
plugins: [typescript()]
}
];
my tsconfig.json
{
"compilerOptions": {
"target": "ES2016",
"module": "ES2020",
"moduleResolution": "node",
"allowJs": true,
"noEmitOnError": true,
"jsx": "react",
"allowSyntheticDefaultImports": true,
"lib": ["ES2015"],
"strict": true,
"esModuleInterop": false,
"outDir": "./dist",
"rootDir": "./"
}
,
"include": ["./src/**/*.ts"]
// "include": ["./src/**/*.ts", "src/components/Tag/index.tsx"]
}
Current issues : The build file contains code only of my ts files
package being used to add ts support : "rollup-plugin-typescript2"
build command : "build-lib": "rollup -c"

`Cannot read properties of undefined` for enum after bundling with webpack

I have a React Library that I want to make buildable using Webpack. The library is written using Typescript. It seems everything is working, but for some reason enums aren't.
When I install the library into my React App, I find Cannot read properties of undefined in the browser console for the enum.
I've tried looking in the outputted bundle and it does appear that the enum is being compiled into the bundle. I feel like I must have a misconfiguration somewhere. Before I was able to bundle with microbundle-crl which we're moving from in favour of Webpack.
Here is my webpack.config.js file:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const DtsBundleWebpack = require('dts-bundle-webpack');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
resolve: {
extensions: ['.tsx', '.ts', '.json', 'jsx', '.js'],
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, //Extract css into files
'css-loader', // Turns css into commonjs
],
},
{
test: /\.pcss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader', // Turns css into commonjs
'postcss-loader'
]
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: 'randomcompany-components.css' }),
new DtsBundleWebpack({
name: '#randomcompany/components',
main: './dist/src/index.d.ts',
out: '../index.d.ts',
}),
],
};
My tsconfig.json is as follows:
{
"compilerOptions": {
"outDir": "dist",
"module": "esnext",
"lib": ["dom", "esnext"],
"types": ["react", "react-scripts"],
"moduleResolution": "node",
"jsx": "react",
"sourceMap": true,
"declaration": true,
"declarationDir": "dist",
"esModuleInterop": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"isolatedModules": true,
"preserveConstEnums": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"include": ["src", "src/lang"],
"exclude": ["node_modules", "dist", "src/stories"]
}
My enum is in this format:
export enum Test {
TestOne = "Test One",
TestTwo = "Test Two",
TestThree = "Test Three"
};
export default Test;
You should write it like below:
const Test = {
TestOne: "Test One",
TestTwo: "Test Two",
TestThree: "Test Three",
};
export default Test;
But in my opinion, using enum makes your bundle file a little bit heavy, just advise. use simple JavaScript objects.

How to build a npm lib with subfolders like MateriaUI using Rollup.js

Im trying to build my lib and export the components like MaterialUI way:
But, the only thing I can do, is that:
Im using rollup.js and typescript. I notice that d.ts and type.ts files have been exported in the component folder but the component itself is exported in main folder.
Can someone help me to fix it?
My rollup.js config:
import commonjs from '#rollup/plugin-commonjs'
import resolve from '#rollup/plugin-node-resolve'
import replace from '#rollup/plugin-replace'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import typescript from 'rollup-plugin-typescript2'
import postcss from 'rollup-plugin-postcss'
import { terser } from 'rollup-plugin-terser'
import del from 'rollup-plugin-delete'
import includePaths from 'rollup-plugin-includepaths'
/* css imports */
import pkg from './package.json'
export default {
input: ['./src/index.ts', './src/TestComponent/index.tsx'],
output: [
{
dir: 'dist/esm',
format: 'esm',
sourcemap: true,
exports: 'named',
strict: false,
plugins: [terser()]
}
],
plugins: [
includePaths({ paths: ['./src'] }),
typescript({
}),
peerDepsExternal(),
resolve(),
commonjs(),
del({
targets: ['dist/*']
}),
postcss({
modules: true,
extract: false,
namedExports: true,
writeDefinitions: true,
}),
replace({
preventAssignment: true,
ENV: JSON.stringify(process.env)
}),
],
external: Object.keys(pkg.peerDependencies)
}
My tsconfig.json file:
{
"compilerOptions": {
"declaration": true,
"declarationDir": "dist",
"outDir": "dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017"],
"sourceMap": true,
"allowJs": false,
"jsx": "react",
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"plugins": [{ "name": "typescript-plugin-css-modules" }]
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"dist",
"src/**/*.stories.tsx",
"src/**/*.test.tsx"
]
}
My folder's structure:
Ps: I'd like to export only the components to import like
import TestComponent from '#ind/package/esm/TestComponent'
and
import {TestComponent} from '#ind/package/esm'
Late reply, but for anyone stumbling on this the most straightforward way I found was to use the preserveModules option: Instead of creating as few chunks as possible, this mode will create separate chunks for all modules using the original module names as file names.
It does respects the file's relative path, components/Test.jsx ends up in dist/components/Test.js.
This issue also suggests you can map things in input directly; but that doesn't seem to work when using rollup programmatically:
export default {
input: {
'module1': 'src/module1.js',
'foo/module2': 'src/foo/module2.js',
'foo/bar/module3': 'src/foo/bar/module3.js',
},
output: {
format: cjs,
dir: 'dist'
}
}

Problems with rollupjs configuration

When building my TypeScript project (all node modules are up to date) with the following configuration I get a error message called "Error: When building multiple chunks, the output.dir option must be used, not output.file."
Can anyone help? Thanks.
// [EDIT: I've simplified this configuration as the original
// one caused some misunderstandings]
// rollup.config.js
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
import { uglify } from 'rollup-plugin-uglify'
import gzip from 'rollup-plugin-gzip'
export default {
input: 'src/main/my-project.ts',
output: {
file: 'dist/my-project.umd.production.js',
format: 'umd',
name: 'MyProject',
sourcemap: false,
globals: {
'react': 'React'
}
},
external: ['react'],
plugins: [
resolve(),
commonjs(),
typescript({
exclude: 'node_modules/**'
}),
uglify(),
gzip()
]
}
This is my tsconfig.json in case it may be important.
The build script is started by rollup --c rollup.config.js:
{
"compilerOptions": {
"target": "ES5",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"downlevelIteration": true,
"sourceMap": true,
"lib": ["es5", "es6", "dom"],
"esModuleInterop": true,
"baseUrl": ".",
"typeRoots": [
"node_modules/#types"
],
"types": [
"node", "react", "react-dom", "mocha", "chai"
]
},
"files": [
"src/main/my-project.ts"
],
"include": [
"./src/**/*.ts*"
]
}
I had a similar issue and as a fix I needed to specify the output module in package.json
{
...
"module": "./dist/index.esm.js",
...
}
And it's aligned with the rollup config:
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'esm' },
]
For all those how are still struggling to get this issue fixed and you are using dynamic imports in the component than you should add inlineDynamicImports: true just above output object
It seems that the configuration wasn't the problem, but there was still something wrong with the versions of my node modules.
After I did the following, everything worked fine again:
> ncu -u
> npm update
> npm install

Angular 2 tree shaking with webpack 2

I'm trying to reduce the size of my angular 2 application by applying tree shaking technique.
I'm using webpack 2.1.0-beta.22, angular 2 rc6 and typescript 2.0.2.
Here is my tsconfig.json:
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"removeComments": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"exclude": [
"node_modules"
]
webpack.config:
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['ts', 'angular2-template-loader']
}
]
},
plugins: {
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
beautify: false,
compress: { screw_ie8: true },
comments: false,
screw_ie8: true,
sourceMap: true
})
}
Bundle size before tree shaking was ~ 1.7MB, and after tree shaking size became ~ 1.8MB.
What do I do wrong?

Categories

Resources