developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8.05k stars 362 forks source link

'use client' #1049

Open clementroche opened 1 year ago

clementroche commented 1 year ago

Hi, I'm the maintainer of react-lenis package and some people complain about using the library in next.js app context usage. In fact it requires 'use client' directive on top of the file but I noticed that it's ignored by microbundle "Module level directives cause errors when bundled, 'use client' was ignored." Do you have a solution for that ?

https://github.com/studio-freight/lenis/issues/170

rschristian commented 1 year ago

Does 'use client' still end up in your bundle?

Edit: It does not. I'm wondering if this is something Microbundle should support though, as directives are per-file, so if you were to say bundle a bunch of components with Microbundle, all would be affected by that directive. I'm not sure what the expected behavior here would be.

developit commented 1 year ago

The only way I can think of to do this would be to string-replace "use client" to something Terser will never minify/inline/fold, then string-replace it back after minification. There are very few replacements that would work for this, but an empty destructured variable declaration is one of them (Terser simply preserves it as-is).

// replace directive with a side effecting statement to keep it in-place during minification:
code = code.replace(/(\{[\n\s]*)(['"])use client\2([;\s])/g, `$1var{}=_USE_CLIENT_$3`);

// then minify:
let minified = (await terser.minify(code)).code;

// then replace the statement back:
minified = minified.replace(/(\{[\n\s]*)var\s*{\s*}\s*=\s*_USE_CLIENT_([;\s])/g, `$1"use client"$2`);
clementroche commented 1 year ago

any solution planned @developit ?

this might become a real issue once maintainer switch to Next.js app folder see next.js notice https://nextjs.org/docs/getting-started/react-essentials#third-party-packages

ForsakenHarmony commented 1 year ago

terser also has compress.directives which could be set to false

@clementroche does it help to add a mangle.json file with the following content?

{
  "minify": {
    "compress": {
      "directives": false,
    }
  }
}

We might also need rollup-plugin-preserve-directives 🤔

Also see the rollup issue about the subject: https://github.com/rollup/rollup/issues/4699

clementroche commented 1 year ago

Now i realise that the issue comes from rollup itself not directly from microbundle, i'm gonna take a look at the thread you shared, thank you

clementroche commented 1 year ago

I tried both solutions @ForsakenHarmony, still have this warning Module level directives cause errors when bundled, 'use client' was ignored.

pretty sure rollup.config.js is ignored by microbundle, right ?

rschristian commented 1 year ago

pretty sure rollup.config.js is ignored by microbundle, right ?

Yes, Microbundle's Rollup configuration is not open to configuration. However, you can of course patch Microbundle's config from node_modules to test out various solutions, if you didn't want to clone Microbundle & dev with the test suite.

Stan-Stani commented 1 year ago

Personally, I would just like a way to silence that error for now.

Having a thousand lines like this,

Module level directives cause errors when bundled, 'use client' was ignored.
Module level directives cause errors when bundled, 'use client' was ignored.       
Module level directives cause errors when bundled, 'use client' was ignored.
Module level directives cause errors when bundled, 'use client' was ignored.
Module level directives cause errors when bundled, 'use client' was ignored.
Module level directives cause errors when bundled, 'use client' was ignored.

makes it hard to find when there are actual errors that prevent bundling.

I'm trying to figure out how to directly patch microbundle.js in node_modules, where the config lives, but I think I'm running into issues with yarn caching the files so my edits aren't causing changes :(.

gtjamesa commented 1 year ago

I'm trying to figure out how to directly patch microbundle.js in node_modules, where the config lives, but I think I'm running into issues with yarn caching the files so my edits aren't causing changes :(.

You can edit the relevant files then use patch-package to create a patch that you can track in version control. It will be reapplied on install

rschristian commented 1 year ago

I'm trying to figure out how to directly patch microbundle.js in node_modules, where the config lives, but I think I'm running into issues with yarn caching the files so my edits aren't causing changes :(.

Sorry, I didn't see this. Make sure you're editing node_modules/microbundle/dist/cli.js, rather than node_modules/microbundle/dist/microbundle.js. The former is the CLI app, latter is for programmatic usage.

Yarn v1 has no caching, no idea about v2+ though.