npm package: @lkexi-oss/nrwl-custom-rollup
Description: This library is intended to be used when packaging libraries for publishing as installable node module that requires `babel` transformation. This can also be used for when compiler is set to `swc` but will not apply any extra setup since setup only applie
Author: Exequiel Ceasar Navarrete
Latest version: 0.0.6

# Nrwl Custom Rollup Setup

This library is intended to be used when packaging libraries for publishing as installable node module that requires `babel`
transformation. This can also be used for when compiler is set to `swc` but will not apply any extra setup since setup
only applies for `babel`-based compilation.

## Installation and Setup

To install, use the following command:

```bash
npm install -d @lkexi-oss/nrwl-custom-rollup
```

To initialize a Nrwl Nx library for packaging via rollup use the following command:

```bash
// NOTE: `targetName` argument is optional. Just for demo purposes
npx nx g @lkexi-oss/nrwl-custom-rollup:init-rollup <workspace-library-name> --targetName=package
```

Running the command above will prepare your library to make packaging setup optimized for both ESM and CSM easier.

Also a new project target will be added to your project.json:

```json
{
  "targets": {
    "package": {
      "executor": "@nrwl/web:rollup",
      "outputs": ["{options.outputPath}"],
      "options": {
        // These are the standard `@nrwl/web:rollup` options
        "project": "libs/utils/package.json",
        "outputPath": "dist/libs/utils",
        "entryFile": "libs/utils/src/index.ts",
        "tsConfig": "libs/utils/tsconfig.lib.rollup.json",
        "compiler": "babel",
        "rollupConfig": "@lkexi-oss/nrwl-custom-rollup/plugins/bundle-rollup",
        "generateExportsField": true,
        "format": ["cjs", "esm"],

        // Options passed to the custom rollup config
        // NOTE: Enables us to preserve the directory structure and provides more efficient way of treeshaking when used
        //       with ESM formats. Can also be used in CJS (CommonJS) formats but you'll have to manually
        //       configure exports/entrypoints in your package.json manually.
        // See: https://nodejs.org/api/packages.html#subpath-imports
        //      https://medium.com/swlh/npm-new-package-json-exports-field-1a7d1f489ccf
        //      https://webpack.js.org/guides/package-exports/
        "preserveModulesForFormat": ["esm"],
        // NOTE: this provides an override for babel plugins when used building CJS using babel. Library's `.babelrc`
        //       is also used for both ESM and CJS builds. This takes priority if the same babel plugin is also used
        //       in the library's .babelrc thus overriding the setup of a specific plugin in `.babelrc`.
        //       should be a path related to the monorepo root which points to a custom babelrc file in JSON format
        //       or can be `null`. Defaults to `null`.
        "cjsBabelRc": null
      }
    }
  }
}
```

## Customization

Nrwl Custom Rollup Setup provides customization via `project.json` `package` target. See [Installation and Setup section](#installation-and-setup)
for properties in the target that can be customized.

Developers can also override the and extend the rollup config by providing a custom path to `targets.package.options.rollupConfig` and
add a custom logic in the boilerplate below:

```javascript
const {
  NormalizedWebRollupOptions,
} = require('@nrwl/web/src/executors/rollup/lib/normalize');
const {
  getRollupConfig,
} = require('@lkexi-oss/nrwl-custom-rollup/plugins/rollup-config');
const { RollupOptions } = require('rollup');

/**
 * @param {RollupOptions} currentConfig
 * @param {NormalizedCustomWebRollupOptions} options
 * @returns NormalizedCustomWebRollupOptions
 */
module.exports = (currentConfig, options) => {
  let newConfig = getRollupConfig(currentConfig, options);

  // provide custom rollup setup here...

  if (newConfig.output.format === 'cjs') {
    // provide custom rollup setup here when building for CJS...
  }

  if (newConfig.output.format === 'esm') {
    // provide custom rollup setup here when building for ESM...
  }

  return newConfig;
};
```

## Extras

### `node_modules` and libs folder nested in my package

This is due to `core-js` being copied over which is an external dependency and it causes to mess up the rollup output
when `preserveModules` is set to `true`. This is fixed in the upcoming [rollup@3 release](https://github.com/rollup/rollup/issues/3684#issuecomment-1200153399) but can be easily fixed by just adding `core-js` to the library's package.json `peerDependencies`.

Or, you can easily fix this by running the `fix-core-js` generator

```bash
npx nx g @lkexi-oss/nrwl-custom-rollup:fix-core-js <workspace-library-name>
```

### `core-js` polyfills for early versions of browser/node.js environments still getting outputted

You can use `.browserslistrc` to control the output of `core-js` polyfills added by babel. Just add it in the
library's directory beside `package.json`. Unfortunately, there's an existing bug in Nrwl or Babel that `.browserslistrc`
doesn't get recognized (https://github.com/nrwl/nx/issues/10304). A workaround for this is to configure the library's
`.babelrc` file as outlined in this [GitHub comment](https://github.com/nrwl/nx/issues/10304#issuecomment-1169927940).

Or, you can easily fix this by running the `fix-core-js` generator

```bash
npx nx g @lkexi-oss/nrwl-custom-rollup:fix-core-js <workspace-library-name> --disable
```

### `@nrwl/web:rollup` executor complains about buildable/publishable dependencies not under the `rootDir`

This can be easily fixed by adding the same `package` targets to all of the project's buildable/publishable library
dependencies. More explanation can be found here https://github.com/nrwl/nx/issues/11289#issuecomment-1195616035.

### My CJS versions are broken due to interop added by Rollup

ESM/CJS interop code added by Rollup breaks references to a NPM module that exposes a function through `module.exports`.
An example of this is [`minimatch`](https://github.com/isaacs/minimatch/blob/6410ef32f59e4842121ca13eefacdf0b3da8533c/minimatch.js#L1).
To fix this, add `esModuleInterop` to your library's TSConfig and set the value to `true`.

Take note that when using `esModuleInterop` in one of your Nrwl Nx libraries, you would need to also enable it in other applications and libraries
within the monorepo that consumes that library.