Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NX Monorepo support #1845

Open
Oldbury opened this issue Oct 15, 2021 · 11 comments
Open

NX Monorepo support #1845

Oldbury opened this issue Oct 15, 2021 · 11 comments

Comments

@Oldbury
Copy link

Oldbury commented Oct 15, 2021

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

@dphang
Copy link
Collaborator

dphang commented Oct 22, 2021

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.

@rrooding
Copy link
Contributor

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

@wguerram
Copy link

wguerram commented Nov 5, 2021

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?

@estyh
Copy link

estyh commented Nov 5, 2021

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/serverless-component@1.20.0-alpha.23'
  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)

@wguerram
Copy link

wguerram commented Nov 6, 2021

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

serverless.yml

client:
  component: '@sls-next/serverless-component@3.5.2'
  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

@Rafcin
Copy link

Rafcin commented Dec 1, 2021

@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?

@estyh
Copy link

estyh commented Dec 1, 2021

@Rafcin no

@Rafcin
Copy link

Rafcin commented Dec 1, 2021

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.

@yoont4
Copy link

yoont4 commented Apr 25, 2022

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:

if (await this.isPackagePresent("next-i18next")) {

Further down:

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.

@busla
Copy link

busla commented Nov 23, 2022

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:

this.serverlessDir = path.join(this.dotNextDir, "serverless");

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/serverless-component@3.7.0"
  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

@yehonadav-feel
Copy link

can someone share a workable example for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants