serverless-next.js icon indicating copy to clipboard operation
serverless-next.js copied to clipboard

NX Monorepo support

Open Oldbury opened this issue 3 years ago • 9 comments

Nx Monorepo Support

Would be good to support using this component as part of a Monorepo.

I'm building an app with NextJS as part of an NX Monorepo and want to use the Serverless next component to deploy the app and functions as I have done in previous projects

Oldbury avatar Oct 15 '21 20:10 Oldbury

I'm not familiar with Nx Monorepo but could you clarify what specifically does not work?

I believe you should be able to use inputs like nextConfigDir and build.* to specify different project structures. You could even build the Next app outside of this and set build = false, so this would only package and deploy.

dphang avatar Oct 22 '21 05:10 dphang

We are using this in an Nx monorepo. What kind of issue are you experiencing?

rrooding avatar Oct 26 '21 18:10 rrooding

Hello, i'm using NX and have set build = false but serverless is expecting that file.

How does this file gets created .serverless_nextjs\default-lambda\manifest.json?

I'm getting an error because that file does not exists in the build output folder created by NX.

@Oldbury were you able to deploy?

wguerram avatar Nov 05 '21 02:11 wguerram

I have it working like this (the app is named "client"):

in worskpace.json, I have this configuration:

"client": {
      "root": "apps/client",
      "sourceRoot": "apps/client",
      "projectType": "application",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@nrwl/next:build",
          "options": {
            "root": "apps/client",
            "outputPath": "dist/apps/client",
            "assets": [
              {
                "input": "assets",
                "glob": "**/*",
                "output": "assets"
              }
            ]
          },
          "configurations": {
            "production": {
              "outputPath": "apps/client/deploy"
            }
          }
        },

The important part is the production output path - I'm sending it to a deploy folder inside the app root.

Next, in apps/client/deploy, I have a serverless.yml file

client:
  component: '@sls-next/[email protected]'
  inputs:
    build:
      cmd: './build.sh'
      args: ''

In the same deploy folder, I have a file build.sh

#!/bin/bash
rm -rf .next
cd ../../../
npx nx run client:build:production

In the client app root, my next.config.js file looks like this:

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

module.exports = withNx({
  nx: {
    // Set this to false if you do not want to use SVGR
    // See: https://github.com/gregberge/svgr
    svgr: true,
    webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
      config.optimization.splitChunks.cacheGroups = {};
      config.optimization.minimize = true;
      return config;
    },
  },
  target: 'serverless',
});

And finally, to deploy, I run the following:

cd apps/client/deploy
npx serverless --debug

(actually, my setup is a little bit more complex because I deploy to multiple environments, but this is how it would be done for single environment deployments)

estyh avatar Nov 05 '21 06:11 estyh

@estyh thanks for the detailed explanation, I really appreciate it, that gave me some directions. I end up

serverless.yml

client:
  component: '@sls-next/[email protected]'
  inputs:
    build:
      cmd: ':'
      cleanupDotNext: false

workspace.json

"options": {
            "root": "apps/client",
            "outputPath": "dist/apps/client",
            "assets": [
              {
                "input": "apps/client/src",
                "glob": "serverless.yml",
                "output": "."
              }
            ]
          },
nx build client --prod
cd dist/apps/client
mv ./public/serverless.yml ./
npx serverless --debug

wguerram avatar Nov 06 '21 02:11 wguerram

@wguerram Do you have a public repo with this configuration? When I build it using your method I'm unable to zip the correct artifact size. For me it should be 90mb or around that, instead it's 7mb and it throws:

2021-12-01T08:35:18 [INFO]: Cannot find any generated SSR resources to deploy. If you intend for your app to be SSR, please check your app Service Role permissions. Otherwise, please check out our docs on how to setup your app to be detected as SSG (https://docs.aws.amazon.com/amplify/latest/userguide/server-side-rendering-amplify.html#deploy-nextjs-app)
2021-12-01T08:35:18 [ERROR]: {"code":"7","message":"No ssrResources.json file"}

@estyh Did you run into a artifact size issue when deploying using your method?

Rafcin avatar Dec 01 '21 08:12 Rafcin

@Rafcin no

estyh avatar Dec 01 '21 18:12 estyh

Just me then. Your serverless method is also way better @estyh!! Odd it seems I'm the only one who can't deploy a proper build.

Rafcin avatar Dec 01 '21 18:12 Rafcin

I am also running into this issue. We are trying to convert our project into an nx monorepo, and it keeps failing on the next-i18next integration.

Specifically, this fails: https://github.com/serverless-nextjs/serverless-next.js/blob/4316b18794f053d7ed929b9342a649d6e0ab6f68/packages/libs/core/src/build/third-party/next-i18next.ts#L10

Further down: https://github.com/serverless-nextjs/serverless-next.js/blob/4316b18794f053d7ed929b9342a649d6e0ab6f68/packages/libs/core/src/build/third-party/integration-base.ts#L24

It assumes that the nextConfigDir is also the same place that has the package dependencies listed, but in our nx repo that's defined in the project root's package.json. So naturally, it fails when it tries to access the package.dependency property.

Maybe I am configuring things the wrong way around, but everything else seems to work fine (the build step goes through no problem). It's just when it hits the next-i18next integration, it fails in our pipeline.

Any advice/help is greatly appreciated.

yoont4 avatar Apr 25 '22 22:04 yoont4

Small update to @estyh script for this to work with Next 13 since target was deprecated from the Next config and no serverless dir is created

see: https://github.com/serverless-nextjs/serverless-next.js/blob/ca7f7f72e3b1e5fcb49ffc4a3f6d6f629e644b20/packages/libs/lambda-at-edge/src/build.ts#L94

Renaming the server dir to serverless right after building fixed the issue. Not sure if useServerlessTraceTarget had any effect but leaving it anyway for optmizations.

Use the useServerlessTraceTarget option in serverless.yml. This will cause Next.js to not bundle dependencies into each page (instead creating lightweight pages) and then serverless-next.js will reference a single set of dependencies in node_modules.

current config

some-app:
  component: "@sls-next/[email protected]"
  inputs:
    build:
      cmd: "./build.sh"
      args:
        - some-app
      useServerlessTraceTarget: true
#!/bin/bash

set -eoux pipefail

app=$1
rm -rf .next
project_root="$(git rev-parse --show-toplevel)"
deploy_dir=${project_root}/apps/${app}/deploy
dist_dir=${deploy_dir}/.next

cd "${project_root}"
nx run "${app}":build:production
mv "${dist_dir}"/server "${dist_dir}"/serverless

edit:

I also use the patched serverless version

npx @sls-next/serverless-patched

busla avatar Nov 23 '22 00:11 busla

can someone share a workable example for this?

yehonadav-feel avatar Dec 07 '22 17:12 yehonadav-feel