vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.94k stars 26.97k forks source link

serverComponentsExternalPackages does not work with workspace packages #43433

Open raftario opened 1 year ago

raftario commented 1 year ago

Verify canary release

Provide environment information

Operating System:
    Platform: win32
    Arch: x64
    Version: Windows 10 Pro
Binaries:
    Node: 18.12.1
    npm: N/A
    Yarn: N/A
    pnpm: N/A
Relevant packages:
    next: 13.0.6-canary.1
    eslint-config-next: N/A
    react: 18.2.0
    react-dom: 18.2.0

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

The experimental serverComponentsExternalPackages config option does not seem to have any effect when specifying workspace packages and webpack still attempts to bundle them. This behaviour is the same with both yarn@3 and pnpm@7.

./native.node
Module parse failed: Unexpected character '�' (1:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)

Expected Behavior

webpack should not attempt to bundle workspace packages specified in serverComponentsExternalPackages.

Link to reproduction - Issues with a link to complete (but minimal) reproduction code will be addressed faster

https://github.com/raftario/next-server-components-external-workspace-packages

To Reproduce

apancutt commented 1 year ago

Same issue. Since I deploy the monorepo as a Docker image I don't want/need to bundle any server dependencies, so I'm doing this…

// apps/my-app/next.config.js

const { readdirSync } = require('node:fs');
const { builtinModules } = require('node:module');
const { join } = require('node:path');

const monorepoModules = (scope = undefined) => {
  const nodeModulesPath = join(__dirname, '..', '..', 'node_modules');
  return readdirSync(scope ? join(nodeModulesPath, scope) : nodeModulesPath, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory() && !dirent.name.startsWith('.'))
    .map((dirent) => scope ? `${scope}/${dirent.name}` : dirent.name)
    .reduce((acc, name) => (
      undefined === scope && name.startsWith('@')
        ? [ ...acc, ...monorepoModules(name) ]
        : [ ...acc, name ]
    ), []);
};

module.exports = {
  experimental: {
    serverComponentsExternalPackages: monorepoModules()
      .concat(builtinModules)
      .concat(builtinModules.map((name) => `node:${name}`)),
  },
  // ...etc
};

Is there a better way to opt-out of bundling server dependencies?

matthieu-beteille commented 11 months ago

any update here?

Edit by maintainers: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

muhammadyusuf-kurbonov commented 8 months ago

So any updates? I can't use @xenova/transformers due this issue. Any workarounds, please.

raftario commented 7 months ago

One possible workaround is editing the webpack config like so in your next.config.js.

webpack: (config) => {
  config.externals.push({
    "PACKAGE_NAME": "commonjs PACKAGE_NAME",
  })
  return config
},

However this is pretty ugly and error prone and having the dedicated config option work properly within monorepos would be much nicer :)

davecarlson commented 6 months ago

A question on this : is a package is used within a package, does it get externalised? Use case:

main next app app lives in apps/frontend prisma lives in packages/database ( @prisma/client andprisma`)

we import prisma like thus: import prisma from@companyname/database`

Will the 2 prisma packages be auto externalised, or do we need to tell it to externalise @companyname/database ?

https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsExternalPackages

I ask because out our vercel output, we get a large bundle warning for 2 of the functions., and it looks to be including prisma

Screenshot 2024-04-24 at 07 34 11
timfish commented 2 months ago

a package is used within a package, does it get externalised?

My testing suggests not!

r34son commented 2 months ago

I guess problem is here https://github.com/vercel/next.js/blob/v14.2.5/packages/next/src/build/handle-externals.ts#L421 Need to adjust regexp to handle more pnpm-like cases

r34son commented 2 months ago

In my case issue was in incorrect exports in package package.json Ensure that you have at least one "default" condition export