floroz
floroz

Reputation: 413

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

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: TSC Compile 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 Outcome

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?

Upvotes: 1

Views: 1889

Answers (1)

ManSour
ManSour

Reputation: 11

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' ],
        ],
      }),
......

Upvotes: 0

Related Questions