nrwl / nx

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

Nx + Next.JS + output: 'standalone' #14112

Closed jasondavis87 closed 1 year ago

jasondavis87 commented 1 year ago

Current Behavior

When output: 'standalone' is added to the next.config.js:

//@ts-check

// eslint-disable-next-line @typescript-eslint/no-var-requires
const { withNx } = require('@nrwl/next/plugins/with-nx');

/**
 * @type {import('@nrwl/next/plugins/with-nx').WithNxOptions}
 **/
const nextConfig = {
  output: 'standalone',
  nx: {
    // Set this to true if you would like to to use SVGR
    // See: https://github.com/gregberge/svgr
    svgr: false,
  },
};

module.exports = withNx(nextConfig);

you get this error: (nextjs app is called web)

NX   ENOENT: no such file or directory, open '<DEV_FOLDER>/dist/apps/web/.next/standalone/server.js'

Expected Behavior

The build processes successfully with a server.js that can be run to host the site.

Github Repo

No response

Steps to Reproduce

  1. Create the repo
    yarn create nx-workspace --preset=next --appName=web --nxCloud=true --style=css monorepo
    cd monorepo
  2. add output: 'standalone' to the apps/web/next.config.js file:
    
    //@ts-check

// eslint-disable-next-line @typescript-eslint/no-var-requires const { withNx } = require('@nrwl/next/plugins/with-nx');

/**

module.exports = withNx(nextConfig);


3. Run the command: `yarn nx run web:build:production` or `nx build web`

Error message shows:
![Screenshot 2023-01-03 at 11 10 38 AM](https://user-images.githubusercontent.com/21994603/210395894-7089c591-0493-462a-98d7-1d875a1a29d6.png)

### Nx Report

```shell
>  NX   Report complete - copy this into the issue template

   Node : 16.18.1
   OS   : darwin x64
   yarn : 1.22.19

   nx : 15.4.2
   @nrwl/angular : Not Found
   @nrwl/cypress : 15.4.2
   @nrwl/detox : Not Found
   @nrwl/devkit : 15.4.2
   @nrwl/esbuild : Not Found
   @nrwl/eslint-plugin-nx : 15.4.2
   @nrwl/expo : Not Found
   @nrwl/express : Not Found
   @nrwl/jest : 15.4.2
   @nrwl/js : 15.4.2
   @nrwl/linter : 15.4.2
   @nrwl/nest : Not Found
   @nrwl/next : 15.4.2
   @nrwl/node : Not Found
   @nrwl/nx-cloud : 15.0.2
   @nrwl/nx-plugin : Not Found
   @nrwl/react : 15.4.2
   @nrwl/react-native : Not Found
   @nrwl/rollup : 15.4.2
   @nrwl/schematics : Not Found
   @nrwl/storybook : Not Found
   @nrwl/web : 15.4.2
   @nrwl/webpack : 15.4.2
   @nrwl/workspace : 15.4.2
   @nrwl/vite : 15.4.2
   typescript : 4.8.4
   ---------------------------------------
   Local workspace plugins:
   ---------------------------------------
   Community plugins:

Failure Logs

~/Development/2023/monorepo  main  nx build web                                                               ok  16s  11:08:47 AM

> nx run web:build:production

info  - Skipping linting
info  - Checking validity of types
info  - Creating an optimized production build
info  - Compiled successfully
info  - Collecting page data ..
 >  NX   ENOENT: no such file or directory, open '/Users/jason/Development/2023/monorepo/dist/apps/web/.next/standalone/server.js'

   Pass --verbose to see the stacktrace.

 ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  NX   Ran target undefined for project web (14s)

    ✖    1/1 failed
    ✔    0/1 succeeded [0 read from cache]

   View structured, searchable error logs at https://nx.app/runs/V3bl6rnUGV

Additional Information

Not sure if this is related but adding it here: next.config.js - Setting a custom build directory

This may or may not be the reason for the issue. Honestly not sure if it's Next.Js related or NX related but this could be a possible reason why it's not working. I'm not completely familiar with the code so i can't tell.

na-ji commented 1 year ago

Duplicate of #9017

ndcunningham commented 1 year ago

Should be working now. As of v16.3.0 We are now using the Next.js CLI for our build / server executor.

scottrepreneur commented 1 year ago

Hey @ndcunningham, I think this isn't quite right still. I'm having trouble with a standalone build coming out similar to a regular build. Here's a sandbox with a minimum viable repro.

When you remove/comment out the output: 'standalone' next options it renders with the necessary CSS, but the standalone config appears to nest the server.js folder inside another nested dir dist/apps/web/.next/standalone/apps/web/server.js and cannot resolve the necessary CSS for proper display. Not totally sure why this is happening yet, but does seem to be an issue for this build configuration.

Next: 13.4.5 NX: 16.3.2

Lmk if should open another issue here.

sebpalluel commented 1 year ago

Hey @ndcunningham, I think this isn't quite right still. I'm having trouble with a standalone build coming out similar to a regular build. Here's a sandbox with a minimum viable repro.

When you remove/comment out the output: 'standalone' next options it renders with the necessary CSS, but the standalone config appears to nest the server.js folder inside another nested dir dist/apps/web/.next/standalone/apps/web/server.js and cannot resolve the necessary CSS for proper display. Not totally sure why this is happening yet, but does seem to be an issue for this build configuration.

Next: 13.4.5 NX: 16.3.2

Lmk if should open another issue here.

It could explain why I'm having this error on my deployed nextjs app on vercel (build is passing without issues and my local next is working smoothly):

Cannot find module 'styled-jsx/style'
Require stack:
- /var/task/node_modules/.pnpm/next@13.4.6-canary.4_@babel+core@7.22.5_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/require-hook.js
- /var/task/node_modules/.pnpm/next@13.4.6-canary.4_@babel+core@7.22.5_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/server/next-server.js
- /var/task/apps/web/___next_launcher.cjs
Did you forget to add it to "dependencies" in `package.json`?
RequestId: f18d6db4-18c5-4cbc-99c5-a30fd66f404d Error: Runtime exited without providing a reason
Runtime.ExitError
sebpalluel commented 1 year ago

I can confirm that their might be an issue with nx next builder and the 'standalone' mode. Here is the content of my dist/apps/web/.next/standalone build

dist/apps/web/.next/standalone
├── apps
│   └── web
│       ├── pages
│       │   └── api
│       │       └── auth
│       │           └── [...nextauth].ts
│       └── server.js
├── dist
│   └── apps
│       └── web
├── libs
│   ├── features
│   │   ├── account
│   │   │   └── api
│   │   │       └── package.json
│   │   ├── appNav
│   │   │   └── ui
│   │   │       └── package.json
│   │   ├── cart
│   │   │   └── package.json
│   │   ├── organizer
│   │   │   └── event
│   │   │       └── package.json
│   │   ├── pass
│   │   │   └── package.json
│   │   └── settings
│   │       └── package.json
│   ├── gql
│   │   ├── admin
│   │   │   └── api
│   │   │       └── package.json
│   │   └── shared
│   │       └── types
│   │           └── package.json
│   ├── logger
│   │   └── package.json
│   ├── next
│   │   ├── currency
│   │   │   └── package.json
│   │   ├── hasura
│   │   │   ├── fetcher
│   │   │   │   └── package.json
│   │   │   └── utils
│   │   │       └── package.json
│   │   ├── hygraph
│   │   │   └── package.json
│   │   ├── i18n
│   │   │   ├── package.json
│   │   │   └── src
│   │   │       └── messages
│   │   │           ├── en.json
│   │   │           └── fr.json
│   │   ├── next-auth
│   │   │   ├── common
│   │   │   │   └── package.json
│   │   │   └── options
│   │   │       └── package.json
│   │   └── siwe
│   │       └── provider
│   │           └── package.json
│   ├── test-utils
│   │   └── functions
│   │       └── package.json
│   ├── ui
│   │   ├── components
│   │   │   └── package.json
│   │   ├── icons
│   │   │   └── package.json
│   │   └── shared
│   │       └── package.json
│   └── utils
│       └── package.json
├── node_modules
│   ├── @sentry
│   │   └── nextjs -> ../.pnpm/@sentry+nextjs@7.57.0_encoding@0.1.13_next@13.4.9_react@18.2.0_webpack@5.88.1/node_modules/@sentry/nextjs
│   ├── @tanstack
│   │   └── react-query -> ../.pnpm/@tanstack+react-query@4.29.19_react-dom@18.2.0_react@18.2.0/node_modules/@tanstack/react-query
│   ├── chalk -> .pnpm/chalk@4.1.0/node_modules/chalk
│   ├── jsonwebtoken -> .pnpm/jsonwebtoken@9.0.1/node_modules/jsonwebtoken
│   ├── loglevel -> .pnpm/loglevel@1.8.1/node_modules/loglevel
│   ├── loglevel-plugin-prefix -> .pnpm/loglevel-plugin-prefix@0.8.4/node_modules/loglevel-plugin-prefix
│   ├── next -> .pnpm/next@13.4.9_@babel+core@7.22.6_react-dom@18.2.0_react@18.2.0/node_modules/next
│   ├── next-auth -> .pnpm/next-auth@4.22.1_next@13.4.9_nodemailer@6.9.3_react-dom@18.2.0_react@18.2.0/node_modules/next-auth
│   ├── react -> .pnpm/react@18.2.0/node_modules/react
│   ├── react-dom -> .pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom
│   ├── remeda -> .pnpm/remeda@1.23.0/node_modules/remeda
│   └── siwe -> .pnpm/siwe@2.1.4_ethers@5.7.2/node_modules/siwe
└── package.json

62 directories, 27 files

As you can notice a very few node_modules are present and barely any files from my next app and libraries are here. It works normally when not using the standalone mode.

Here is my nx report:


 >  NX   Running global Nx CLI with PNPM may have issues.

   Prefer to use "pnpm" (https://pnpm.io/cli/exec) to execute commands in this workspace.
    TIP  create a shortcut such as: alias pnx="pnpm nx --"

 >  NX   Report complete - copy this into the issue template

   Node   : 20.1.0
   OS     : darwin-arm64
   pnpm   : 8.5.1

   nx                      : 16.5.0
   @nx/js                  : 16.5.0
   @nx/jest                : 16.5.0
   @nx/linter              : 16.5.0
   @nx/workspace           : 16.5.0
   @nx/cypress             : 16.5.0
   @nx/devkit              : 16.5.0
   @nx/eslint-plugin       : 16.5.0
   @nrwl/eslint-plugin-nx  : 16.0.0-beta.1
   @nx/next                : 16.5.0
   @nx/node                : 16.5.0
   @nx/plugin              : 16.5.0
   @nx/react               : 16.5.0
   @nx/rollup              : 16.5.0
   @nx/storybook           : 16.5.0
   @nx/web                 : 16.5.0
   @nx/webpack             : 16.5.0
   nx-cloud                : 16.0.5
   typescript              : 5.1.6
   ---------------------------------------
   Community plugins:
   @nx/eslint-plugin-nx : 16.0.0-beta.1
   ---------------------------------------
   Local workspace plugins:
     @features/organizer/event
     @next/next-auth/options
     @next/next-auth/common
     @test-utils/functions
     @features/account/api
     @gql/anonymous/types
     @next/hasura/fetcher
     @features/appNav/ui
     @next/siwe/provider
     @features/settings
     @test-utils/hasura
     @gql/anonymous/api
     @next/hasura/utils
     @next/react-query
     @test-utils/react
     @gql/shared/types
     @gql/admin/types
     @test-utils/gql
     @gql/user/types
     @next/safe/auth
     @features/cart
     @features/pass
     @next/currency
     @test-utils/db
     @ui/components
     @gql/admin/api
     @next/hygraph
     @next/zustand
     @gql/user/api
     @next/store
     @next/types
     @workspace
     @next/auth
     @next/i18n
     @ui/shared
     @ui/hooks
     @ui/icons
     @ui/theme
     @logger
     @utils
   ---------------------------------------
   The following packages should match the installed version of nx
     - @nrwl/eslint-plugin-nx@16.0.0-beta.1

   To fix this, run `nx migrate nx@16.5.0`

my apps/web/next.config.js:

/* eslint-disable @typescript-eslint/no-var-requires */
const { withNx } = require('@nx/next');
const path = require('path');
const { withSentryConfig } = require('@sentry/nextjs');

/**
 * Don't be scared of the generics here.
 * All they do is to give us autocompletion when using this.
 *
 * @template {import('next').NextConfig} T
 * @param {T} nextI18n - A generic parameter that flows through to the return type
 * @constraint {{import('next').NextConfig}}
 */

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

const withNextIntl = require('next-intl/plugin')('./i18n.ts');

const SENTRY_DSN = process.env.SENTRY_AUTH_TOKEN
  ? null
  : process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;

const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  compiler: {
    // TODO set back when in 'real' prod. For now useful for debug
    // removeConsole:
    //   process.env.VERCEL_ENV === 'production' ||
    //   process.env.NEXT_PUBLIC_VERCEL_ENV === 'production',
    removeConsole: false,
    styledComponents: false,
  },
  /* could improve performance in dev but @ui components no organized like that.
  See that as ref: https://github.com/knitkode/koine/blob/3046607d655a3cfa1e3b3438f1aef168fbdc6ad5/packages/next/config/index.ts#L251
  https://nextjs.org/blog/next-13-1#import-resolution-for-smaller-bundles
  And this thread n
  + this article: https://medium.com/@yashashr/next-js-optimization-for-better-performance-part-1-material-ui-mui-configs-plugins-6fdc48a4e984
  */
  modularizeImports: {
    //Need to update structure of @ui/components to make it work
    // '@ui/components/?(((\\w*)?/?)*)': {
    //   transform: '@ui/components/{{ matches.[1] }}/{{member}}',
    // },
  },
  transpilePackages: ['@ui/components', '@ui/theme', '@ui/icons'],
  images: {
    domains: ['media.graphassets.com'],
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'picsum.photos',
        port: '',
        pathname: '/seed/hero/**',
      },
    ],
  },
  // optimize build with vercel nft (node file tracing) https://nextjs.org/docs/advanced-features/output-file-tracing
  // outputFileTracingRoot needed for monorepo
  output: 'standalone',
  experimental: {
    outputFileTracingRoot: path.join(__dirname, '../../'),
    outputFileTracingExcludes: {
      '*': [
        'node_modules/.pnpm/@swc+core-linux-x64-musl',
        'node_modules/.pnpm/@swc+core-linux-x64-gnu',
        'node_modules/.pnpm/@esbuild+linux-x64',
        'node_modules/.pnpm/webpack',
        'node_modules/.pnpm/sass',
      ],
    },
    // https://vercel.com/docs/concepts/deployments/skew-protection#enabling-skew-protection
    useDeploymentId: true,
    // If use with serverActions is desired
    serverActions: true,
    useDeploymentIdServerActions: true,
    appDir: true,
    typedRoutes: false, // no solution found to get it working with nx monorepo (not accessible from external libs like feature)
  },
  sentry: {
    hideSourceMaps: true,
    // TODO set back when issue fixed, meanwhile issue in api route will not be reported if not wrapped with withSentry.
    autoInstrumentServerFunctions: false, // avoid error: error ./middleware.ts Module not found: Can't resolve 'sentry.edge.config.ts'
  },
};

const sentryWebpackPluginOptions = {
  // Additional config options for the Sentry Webpack plugin. Keep in mind that
  // the following options are set automatically, and overriding them is not
  // recommended:
  //   release, url, org, project, authToken, configFile, stripPrefix,
  //   urlPrefix, include, ignore
  org: 'offline-live',
  project: 'nextjs-marketplace',
  authToken: process.env.SENTRY_AUTH_TOKEN,
  dryRun: !SENTRY_DSN,
  silent: true, // Suppresses all logs
  // For all available options, see:
  // https://github.com/getsentry/sentry-webpack-plugin#options.
};

module.exports = async (phase, context) => {
  const addNx = withNx({
    ...nextConfig,
  });

  let config = await addNx(phase);
  config = await withSentryConfig(config, sentryWebpackPluginOptions);
  config = await withBundleAnalyzer(config);
  config = await withNextIntl(config);
  return config;
};

And my apps/web/project.json:

{
  "name": "web",
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "apps/web",
  "projectType": "application",
  "targets": {
    "build": {
      "executor": "@nx/next:build",
      "outputs": ["{options.outputPath}"],
      "defaultConfiguration": "production",
      "options": {
        "outputPath": "dist/apps/web",
        "postcssConfig": "apps/web/postcss.config.js",
        "debug": true
      },
      "assets": [
        {
          "input": "libs/ui/shared/src/assets",
          "glob": "**/*",
          "output": "assets"
        }
      ],
      "configurations": {
        "development": {
          "outputPath": "apps/web"
        },
        "production": {}
      }
    },
    "serve": {
      "executor": "@nx/next:server",
      "defaultConfiguration": "development",
      "options": {
        "buildTarget": "web:build",
        "hmr": true,
        "port": 8888,
        "dev": true,
        "assets": [
          {
            "input": "libs/ui/shared/src/assets",
            "glob": "**/*",
            "output": "assets"
          }
        ]
      },
      "configurations": {
        "development": {
          "buildTarget": "web:build:development",
          "dev": true
        },
        "production": {
          "buildTarget": "web:build:production",
          "dev": false
        }
      }
    },
    "is-services-launched": {
      "executor": "nx:run-commands",
      "options": {
        "commands": ["node tools/test/isServicesLaunched.js"],
        "readyWhen": "Services ready"
      }
    },
    "serve-e2e": {
      "executor": "nx:run-commands",
      "options": {
        "commands": ["nx is-services-launched web", "nx serve web"],
        "readyWhen": "Services ready"
      }
    },
    "export": {
      "executor": "@nx/next:export",
      "options": {
        "buildTarget": "web:build:production"
      }
    },
    "test": {
      "executor": "@nx/jest:jest",
      "outputs": ["{workspaceRoot}/coverage/apps/web"],
      "options": {
        "jestConfig": "apps/web/jest.config.ts",
        "passWithNoTests": true
      }
    },
    "lint": {
      "executor": "@nx/linter:eslint",
      "outputs": ["{options.outputFile}"],
      "options": {
        "lintFilePatterns": ["apps/web/**/*.{ts,tsx,js,jsx,gql,graphql}"]
      }
    },
    "gql": {
      "executor": "nx:run-commands",
      "options": {
        "commands": [
          {
            "command": "npx graphql-codegen --config codegen.yml -r dotenv/config -e .env.local "
          }
        ]
      }
    },
    "storybook": {
      "executor": "@nx/storybook:storybook",
      "options": {
        "port": 4401,
        "quiet": true,
        "configDir": "apps/web/.storybook"
      },
      "configurations": {
        "ci": {
          "quiet": true
        }
      }
    },
    "build-storybook": {
      "executor": "@nx/storybook:build",
      "outputs": ["{options.outputDir}"],
      "options": {
        "configDir": "apps/web/.storybook",
        "outputDir": "dist/storybook/web",
        "webpackStatsJson": true
      },
      "configurations": {
        "ci": {
          "quiet": true
        }
      }
    },
    "test-storybook": {
      "executor": "nx:run-commands",
      "options": {
        "command": "test-storybook -c apps/web/.storybook --url=http://localhost:4401"
      }
    }
  },
  "tags": []
}
github-actions[bot] commented 1 year ago

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.