nrwl / nx

Smart Monorepos · Fast CI
https://nx.dev
MIT License
23.84k stars 2.38k forks source link

Can't build and publish a React library containing "use client" #19714

Open ajwootto opened 1 year ago

ajwootto commented 1 year ago

Description

Using the default @nx/react library generator with either the rollup or vite bundler ( the two options allowed by the generator), it is not currently possible to preserve "use client" directives that are needed for server components / Next JS app router when the library is built and published.

Building the library with rollup presents a warning that the directive was deliberately stripped out, and Vite does not warn you about anything but doesn't keep the directive in its output.

Motivation

In order to publish libraries for use in React that contain client components for use in a Next JS app router system, the library should include use client directives where applicable. Nx should support these statements out-of-the-box and not strip them out on build.

Suggested Implementation

To be honest, I don't know why the default behaviour of the @nx/react package is to bundle the library files together on build. This disagrees with the approach taken in the @nx/js package where libraries are compiled from Typescript but are left unbundled, with the assumption that the consumer of the library will bring their own bundler. Pre-bundling the library seems unnecessary, and I'm not really sure how use client directives are supposed to be maintained in a pre-bundled output.

Relevant Next JS doc for library authors: https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#advice-for-library-authors

Discussion on Rollup repo about it https://github.com/rollup/rollup/issues/4699

github-actions[bot] commented 6 months ago

This issue has been automatically marked as stale because it hasn't had any activity for 6 months. Many things may have changed within this time. The issue may have already been fixed or it may not be relevant anymore. If at this point, this is still an issue, please respond with updated information. It will be closed in 21 days if no further activity occurs. Thanks for being a part of the Nx community! 🙏

ajwootto commented 6 months ago

not stale

hiWaldoDavid commented 6 months ago

I ran into this issue yesterday and spent quite a bit of time searching for a solution. I'll post mine here for anyone else that gets stuck.

This is what I have:

Object.defineProperty(exports, "__esModule", { value: true });

function getRollupOptions(options) {
  const defaultGlobals = {
    react: 'React',
    'react-dom': 'ReactDOM',
    'styled-components': 'styled',
    '@emotion/react': 'emotionReact',
    '@emotion/styled': 'emotionStyled',
  };

  if (Array.isArray(options.output)) {
    options.output.forEach((output) => {
      output.preserveModules = true;
      output.globals = { ...output.globals, ...defaultGlobals };
    });
  } else {
    const globals = !options.output?.globals
      ? defaultGlobals
      : { ...options.output.globals, ...defaultGlobals };

    options.output = {
      ...options.output,
      preserveModules: true,
      globals,
    };
  }

  try {
    const url = require('@rollup/plugin-url');
    const svg = require('@svgr/rollup');
    const preserveDirectives = require('rollup-plugin-preserve-directives').preserveDirectives;

    options.plugins = [
      svg({
        svgo: false,
        titleProp: true,
        ref: true,
      }),
      url({
        limit: 10000, // 10kB
      }),
      ...(Array.isArray(options.plugins) ? options.plugins : []),
      preserveDirectives(),
    ];
  } catch {
    console.log('Ignored for React Native');
  }

  options.onwarn = (warning, warn) => {
    if (warning.code !== 'MODULE_LEVEL_DIRECTIVE') {
      warn(warning);
    }
  };

  return options;
}

module.exports = getRollupOptions;

I made a few minor changes, but kept it mostly as I found it in the plugin folder.

This is bundling my library with the 'use client' directives, and without any warnings.

github-actions[bot] commented 2 weeks ago

This issue has been automatically marked as stale because it hasn't had any activity for 6 months. Many things may have changed within this time. The issue may have already been fixed or it may not be relevant anymore. If at this point, this is still an issue, please respond with updated information. It will be closed in 21 days if no further activity occurs. Thanks for being a part of the Nx community! 🙏