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

Deploying with Serverless-next.js not working RFC Custom rewrites #767

Closed
anialamo opened this issue Nov 5, 2020 · 14 comments
Closed

Deploying with Serverless-next.js not working RFC Custom rewrites #767

anialamo opened this issue Nov 5, 2020 · 14 comments
Assignees
Labels
bug Something isn't working release-1.19

Comments

@anialamo
Copy link

anialamo commented Nov 5, 2020

Describe the bug

Hi! I am deploying my nextjs app with module serverless-next.js: "^1.15.0-alpha.2" because I have a custom serverless.js to copy in public/locale directory my translation files. Using this code: https://github.com/serverless-nextjs/serverless-next.js/issues/383#issuecomment-667716885

And then I deployed to my AWS @LambdaEdge and also works fine!

// Add the Next SASS plugin
nextConfig = withSass(nextConfig);

module.exports = nextConfig;`

Describe the bug

Now I added recently this code in my next.confg.js for RFC - Custom Routes https://github.com/vercel/next.js/discussions/9081 but when I try to test in my server this "rewrite" fails e.g. if I write myserver.com/en/business this returns 404 error Page not found.

let nextConfig = {
     publicRuntimeConfig: {
          localeLanguages, 
          localeSubpaths
     },
     async rewrites() {
       return [
          { source: "/en/business", destination: "/en/empresas" },
          { source: "/en/contact", destination: "/en/contacto" }, 
          { source: "/en/legal-notice", destination: "/en/aviso-legal" }, 
          { source: "/en/privacy-policy", destination: "/en/politica-privacidad" }, 
          { source: "/en/cookies-policy", destination: "/en/politica-cookies" }, 
          { source: "/en/configure-cookies", destination: "/en/configurar-cookies" }, 
       ];
     }
};

Actual behavior

Expected behavior

In my localhost this works fine! BUT in AWS lambda edge & CloudFront this does not work.

Screenshots/Code/Logs

My serverless.js has the following code:

// serverless.js
const NextJsComponent = require('serverless-next.js/serverless');
const fs = require('fs-extra')

class MyNextJsComponent extends NextJsComponent {
  async default(inputs = {}) {
    if (inputs.build !== false) {
      console.log('-> Building...')
      await this.build(inputs);
      console.log('Building was successful')
    }
    console.log('-> Copying locales directory...');
    this.copyLocales();
    console.log('Locale directory was copied successfully')
    console.log('-> Updating manifest...');
    this.updateNonDynamicManifest();
    console.log('Manifest update successful');
    console.log('-> Deploying...');
    return this.deploy(inputs);
  }

  copyLocales() {
    const localeSrc = './public/locales';
    const localeDest = './.serverless_nextjs/default-lambda/public/locales';
    fs.copySync(localeSrc, localeDest, { recursive: true });
  }

  updateNonDynamicManifest() {
    const manifestFileName = './.serverless_nextjs/default-lambda/manifest.json';
    const manifestJson = require(manifestFileName);
    manifestJson.pages.ssr.nonDynamic['/index'] = "pages/index.js";
    fs.writeFileSync(manifestFileName, JSON.stringify(manifestJson));
  }
}

module.exports = MyNextJsComponent;`

I tried this link Serverless components - Build your own https://github.com/serverless/components#build-your-own
creating my own serverless.js file at root with this sample, but it always returns me this error:

"service" property is missing in serverless.yml

// serverless.js

const { Component } = require('@serverless/core');

class MyBlog extends Component {
  async deploy(inputs) {
    console.log('Deploying a serverless blog'); // Leave a status update for users deploying your Component with --debug
    this.state.url = outputs.url; // Save state
    return outputs;
  }
}

module.exports = MyBlog;

`

What can I do to update my MyNextJsComponent serverless.js file to allow RFC -Custom redirects/rewrites?
Thanks!!!!

Versions

serverless-next.js: "^1.15.0-alpha.2"

@danielcondemarin
Copy link
Contributor

@anialamo Have you tried using the latest stable @sls-next/serverless-component@1.18.0 ?

@anialamo
Copy link
Author

anialamo commented Nov 5, 2020

@danielcondemarin thanks! but how I can use @sls-next/serverless-component@1.18.0 and together create my own serverless.js file to "copy manually" my files located in the path "public/locales/"
Do you have an example how to be the complete serverless.js to copy files to my deployed serverless component & deploy all the app in cloudfront?

I have this example, but this works only with serverless-next.js/serverless.

// serverless.js
const NextJsComponent = require('serverless-next.js/serverless');
const fs = require('fs-extra')

class MyNextJsComponent extends NextJsComponent {
  async default(inputs = {}) {
    if (inputs.build !== false) {
      console.log('-> Building...')
      await this.build(inputs);
      console.log('Building was successful')
    }
    console.log('-> Copying locales directory...');
    this.copyLocales();
    console.log('Locale directory was copied successfully')
    console.log('-> Updating manifest...');
    this.updateNonDynamicManifest();
    console.log('Manifest update successful');
    console.log('-> Deploying...');
    return this.deploy(inputs);
  }

  copyLocales() {
    const localeSrc = './public/locales';
    const localeDest = './.serverless_nextjs/default-lambda/public/locales';
    fs.copySync(localeSrc, localeDest, { recursive: true });
  }

  updateNonDynamicManifest() {
    const manifestFileName = './.serverless_nextjs/default-lambda/manifest.json';
    const manifestJson = require(manifestFileName);
    manifestJson.pages.ssr.nonDynamic['/index'] = "pages/index.js";
    fs.writeFileSync(manifestFileName, JSON.stringify(manifestJson));
  }
}

module.exports = MyNextJsComponent;

How could be this custom serverless.js requiring @serverless/core.... but avoiding the error... "service" property is missing in serverless.yml?
Some help please? How can I create my own serverless.js file using @sls-next/serverless-component@1.18.0?

@anialamo
Copy link
Author

anialamo commented Nov 5, 2020

@danielcondemarin please now I have in my serverless.yml like this:

myNextApp:
  component: "@sls-next/serverless-component@1.18.0"

And also I have in my public/locales 2 subpaths for my languages (multilang app that uses nextjs-i18next module). When I run in the browser my app deployed in AWS CloudFront with @LambdaEdge I discover my app fails. I can see in logs the following error:

"errorType": "Error",
    "errorMessage": "ENOENT: no such file or directory, scandir '/var/task/public/locales/en'",
    "code": "ENOENT",
    "errno": -2,
    "syscall": "scandir",
    "path": "/var/task/public/locales/en", 

I use in my i18n.js file the following path to locate my translation files:
path.resolve('./public/locales')
(This module nextjs-i18next needs the translation files are inside public/static/locales or public/locales directories)

And this is the location for the translation files inside .serverless_nextjs -> assets -> public -> locales

image

Where can I put my locales files? public/static/locales? (this gives me an error when I execute npx serverless. I do not know what to do.

Some help please?
A lot of thanks!!

@dphang
Copy link
Collaborator

dphang commented Nov 5, 2020

You can try to put inside static instead of public/static for now, as static/* is a CloudFront cache behavior only for S3 files (it doesn't have Lambda handler attached to it). I had intentionally failed build if it detects stuff in public/static as it would conflict.

@anialamo
Copy link
Author

anialamo commented Nov 5, 2020

Ok thanks @dphang ! I will try to put my locales inside /static.

@anialamo
Copy link
Author

anialamo commented Nov 5, 2020

Oh no! @dphang this also gives me this error:

image

Is my path.resolve wrong? My translation files are located on .serverless_nextjs-> api-lambda -> assets -> static directory, but my path is "./static"... but the log file says me
ENOENT: no such file or directory, scandir '/var/task/static/en

What is wrong?

@dphang
Copy link
Collaborator

dphang commented Nov 5, 2020

I think it is trying to access from local directory which would be the Lambda container. However, we do not copy any of those static files to the Lambda itself, it is only going to S3. I am not familiar with using next-i18next, but it is probably similar to this related issue: i18next/next-i18next#844.

To support it, I think we need to add ability to copy those files to Lambda handler so it can access it. I will add it the list of items for 1.19.

@dphang dphang added bug Something isn't working release-1.19 labels Nov 5, 2020
@dphang dphang self-assigned this Nov 5, 2020
@anialamo
Copy link
Author

anialamo commented Nov 5, 2020

@dphang ok thanks! Do you know if its available to add some javascript code in serverless.js file or something like this code for the moment?

copyLocales() {
    const localeSrc = './public/locales';
    const localeDest = './.serverless_nextjs/default-lambda/public/locales';
    fs.copySync(localeSrc, localeDest, { recursive: true });
  }

Sorry! I dont know how to make a custom serverless.js. Or better I wait for the release 1.19 will be generated?
A lot of thanks! For your help.

@dphang
Copy link
Collaborator

dphang commented Nov 5, 2020

Yeah, I think if you look in this: serverless/components#522 you should be able to build and deploy steps separately, e.g by passing serverless --component=X build flag. I don't use this so not sure how well this works, but ideally you can use this way to run some custom logic to copy stuff (or do anything else) to serverless_nextjs in between the build and deploy steps. I believe the deploy will just copy everything from those default-lambda and api-lambda as is and upload to Lambda.

If it doesn't work, I think you can also try using deploy and build input along with environment variables in serverless.yml file, setting deploy: false for building and then build: false and deploy: true for deploying.

In meanwhile I think it will be useful to add an ability for user to execute custom scripts in two parts:

  1. After next build but before this component's build. Edit: actually looks like build.cmd input can do this?
  2. After this component's build

@dphang
Copy link
Collaborator

dphang commented Nov 6, 2020

I published the PR: #772 which is in the latest @sls-next/serverless-component 1.19.0 alpha, it should give more flexibility by letting you run custom commands in between build and deploy for serverless command. So you should be able to create a script and call it e.g node script.js to copy additional files you need into the Lambda package.

Let me know if it works for you. This should be more generic - we should not try to build something specifically for next-i18next package

@dphang dphang closed this as completed Nov 6, 2020
@anialamo
Copy link
Author

anialamo commented Nov 6, 2020

Hi @dphang! thanks!

I added in my serverless.yml this code:


myNextApp:
  component: "@sls-next/serverless-component@1.19.0-alpha.0"
  
  inputs:
    build:
      postBuildCommands: ["post-build.js"]

And my file post-build.js is in the root of my app and has this code:

// post-build.js
const fs = require('fs-extra')

console.log('-> Copying locales directory...');
const localeSrc = './public/locales';
const localeDest = './.serverless_nextjs/default-lambda/public/locales';
fs.copySync(localeSrc, localeDest, { recursive: true });
console.log('Locale directory was copied successfully');

When I execute npx serverless or sls command in my termnal at 11seconds I see an editor (in my case SublimeText3 is open with my file post-build.js and displays me its code while the timer of my npx serverless command is stopped at:
11s » myNextApp »

image

Until I close the SublimeText3 editor then the timer of command npx serverless continues deploying. And finally it finish. But nothing is added on .serverless_nextjs-> default_lambda as I expected (public -> locales -> .... files)

image

What is wrong in my case so my script is not executed and only displays its code in an editor?
Thanks!

@dphang
Copy link
Collaborator

dphang commented Nov 6, 2020

Not sure, I think ["post-build.js"] might be opening it up in editor, you probably meant to execute it by doing ["node post-build.js"]?

@anialamo
Copy link
Author

anialamo commented Nov 8, 2020

A lot of thanks @dphang !!!! You are excellent! This new postBuildCommands help me a lot!!!
God bless you!!!

@kylekirkby
Copy link

kylekirkby commented Nov 14, 2020

Thanks @dphang for adding this! I have added the same and it's working perfectly now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working release-1.19
Projects
None yet
Development

No branches or pull requests

4 participants