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

Programmatic usage breaks when upgrading from v2.4 to v2.5 #5408

Closed
thejmill opened this issue Mar 28, 2019 · 21 comments · Fixed by #5413
Closed

Programmatic usage breaks when upgrading from v2.4 to v2.5 #5408

thejmill opened this issue Mar 28, 2019 · 21 comments · Fixed by #5413
Assignees

Comments

@thejmill
Copy link

Version

v2.5.1

Reproduction link

http://donthaveone.com

Steps to reproduce

Deploy Nuxt application using v2.4 to lambda function with express.

Based on https://github.com/serverless/examples/tree/master/aws-node-vue-nuxt-ssr

What is expected ?

Application should function normally.

What is actually happening?

After upgrading to v2.5.1 express always returns a "cannot GET /" message.

This bug report is available on Nuxt community (#c8955)
@ghost ghost added the cmty:bug-report label Mar 28, 2019
@Gedminas
Copy link

Had the same issue. It is running express. This minor version upgrade broke our prod.

fun thing it is working on dev and it is working if it is built using the builder in node, but not npm run build.

We switched from express to nuxt server for the time being, but I am assuming I know the issue.

https://github.com/nuxt/nuxt.js/releases/tag/v2.5.0

Programmatic API / Middleware
If not already done, please explicitly call nuxt.ready() after new Nuxt(). nuxt.ready() was always async, but not awaiting the function call has now a severe impact.

   const nuxt = new Nuxt(config)
++ await nuxt.ready()

This breaks all existing express servers.
I'd say it's careless to release a minor version with breaking changes

@manniL
Copy link
Member

manniL commented Mar 29, 2019

@Gedminas It is no breaking change as stated in the release notes. Awaiting until nuxt is actually ready should always have happened when using Nuxt programmatically.

@manniL manniL closed this as completed Mar 29, 2019
@alanmarcos
Copy link

alanmarcos commented Mar 29, 2019

We had the same issue, including running in dev mode but not in prod. Solved by downgrading nuxt-cli to 2.4.5

our package-lock.json:

"nuxt": {
      "version": "2.4.5",
      "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-2.4.5.tgz",
      "integrity": "sha512-y2p0q58C8yyNr8zg9wEx5ZNhAYe0sbMXHeproGiCKXc2GW7TR6KtZ9/9IBeVlz7HwvoZW+VXIt2m/oecI9IbqQ==",
      "requires": {
        "@nuxt/builder": "2.4.5",
        "@nuxt/cli": "2.4.5",
        "@nuxt/core": "2.4.5",
        "@nuxt/generator": "2.4.5",
        "@nuxt/opencollective": "0.2.1",
        "@nuxt/webpack": "2.4.5"
      }
    }

@pi0 pi0 self-assigned this Mar 29, 2019
@pi0
Copy link
Member

pi0 commented Mar 29, 2019

I can confirm this was a breaking change for some programmatic users. This will be reverted back in 2.6.

@xxRockOnxx
Copy link

@pi0 just curious about the revert. I already upgraded and just followed the additional await thing for nuxt.ready(), would that mean just removing the await? Also, how does it work before v2.5 without await? It says in the migration guide that it has always been an async function but it works without it

@manniL
Copy link
Member

manniL commented Apr 1, 2019

@xxRockOnxx

PS: No action is required from the side of users. Calling and awaiting on ready() after the constructor is still recommended.

From #5413

@manniL manniL changed the title Serverless error when upgrading from v2.4 to v2.5 Programmatic usage breaks when upgrading from v2.4 to v2.5 Apr 4, 2019
@prakashpie
Copy link

Same issue with me as well. Trying get rid of this error from past 3 days but still could not find any solutions

@pi0
Copy link
Member

pi0 commented Apr 4, 2019

@prakashbharti786 Did you also added ready() call after new Nuxt() and what exact error are you getting?

/PS 2.6 will be released today or tomorrow

@prakashpie
Copy link

@pi0 i added that after reading all comments here and it is working fine now. Thank you so much for your reply.

@zoellner
Copy link

zoellner commented Apr 5, 2019

Any reason a change like that doesn't make it into the CHANGELOG file? The release notes seem pretty clear - but I missed them since the changelog doesn't indicate that there's anything more to the release than what's mentioned there.

@manniL
Copy link
Member

manniL commented Apr 6, 2019

@zoellner

It's in there but not highlighted.
grafik

I've added an additional note ☺️

@lukaVarga
Copy link

After I upgraded from 2.4.6 (nuxt-ts) to 2.6.1 nuxt package, I have the same problem (ie. I keep getting a 'Cannot GET /' response when looking at the page generated by serverless).

As far as I understand, calling ready() isn't needed anymore, correct? Is the problem in the fact that I am using typescript?

My nuxt.js is fairly standard:

const express = require("express");
const { Nuxt } = require("nuxt");
const path = require("path");
const config = require("./nuxt.config.ts");

const app = express();
const nuxt = new Nuxt(config);
app.use("/_nuxt", express.static(path.join(__dirname, ".nuxt", "dist")));
app.use(nuxt.render);

module.exports = app;

As is my lambda handler:

const sls = require("serverless-http");
const nuxt = require("./nuxt");

module.exports.nuxt = sls(nuxt, {
  binary: [
    'application/javascript',
    'application/json',
    'application/octet-stream',
    'application/xml',
    'font/eot',
    'font/opentype',
    'font/otf',
    'image/jpeg',
    'image/png',
    'image/svg+xml',
    'text/comma-separated-values',
    'text/css',
    'text/html',
    'text/javascript',
    'text/plain',
    'text/text',
    'text/xml',
  ],
});

@pi0
Copy link
Member

pi0 commented Apr 9, 2019

@lukaVarga The problem should not be related to ready. Do you manually use node-ts to require nuxt.config.ts? If you can create a new issue with reproduction we can help better.

@lukaVarga
Copy link

@pi0 thanks for a quick response. You mean ts-node, right?
I created a reproduction and opened a new issue - #5502

@chriswilcox-mof
Copy link

@pi0 @lukaVarga we had the exact same issue when upgrading from 2.4.x. We didn't find that 2.6.1 helped with the issue. We had almost the same nuxt.js and lambda handler. We aren't using typescript.

What worked for us was to change nuxt.js to an async function so that we could call await nuxt.render()

So nuxt.js became

const express = require('express');
const { Nuxt } = require('nuxt');
const path = require('path');
const config = require('./nuxt.config.js');

async function start() {
  const app = express();
  const nuxt = new Nuxt(config);
  await nuxt.ready();
  app.use('/_nuxt', express.static(path.join(__dirname, '.nuxt', 'dist')));
  app.use(nuxt.render);
  return app;
}

module.exports = start;

Then changed our lambda handler using this approach https://stackoverflow.com/a/47851485

const sls = require('serverless-http');
const binaryMimeTypes = require('./binaryMimeTypes');
const nuxt = require('./nuxt');

module.exports.nuxt = (evt, ctx, callback) => {
  nuxt()
    .then(app =>
      sls(app, {
        binary: binaryMimeTypes,
      })
    )
    .then(proxy => proxy(evt, ctx, callback))
    .catch(err => console.error(err));
};

@lukaVarga
Copy link

@chriswilcox-mof you, sir, are a life saver! Thanks a lot, this solution works perfectly!

@dseeker
Copy link

dseeker commented Apr 16, 2019

Was also getting this issue after a clean install and upgrade, async handler fixed it. But before I was able to store variable in lambda and it would stay in memory for the next call. now this behavior seems to have changed. wondering what was happening before that gave this lambda advantage.

I have this middleware db.js that's using an S3 client lib

let s3
if (process.server) s3 = require('../lib/s3client')
export default (ctx) => {
  return new Promise(async (resolve, reject) => {
  	let resp = await s3.getObject('filename.json')
      	Vue.prototype.catalog = ctx.app.film_catalog = resp.catalog
  	resolve(resp.catalog)
  })
}

in the S3 client library I store the result into a global variable, and check if it's available in the next call, then avoid download the S3 file again

const AWS = require('aws-sdk')
const aws_config = require('/aws-token')
const s3 = new AWS.S3()
let cache = {}, cacheInvalidate = 2 * 60 * 1000 // 2 minutes

AWS.config.update({ accessKeyId: aws_config.accessKeyId, secretAccessKey: aws_config.secretAccessKey });
let s3Bucket = new AWS.S3({ params: {Bucket: aws_config.bucket, timeout: aws_config.timeout}});

const getObject = async (module) => {
 if (cache.hasOwnProperty(module)) {
    var update = {LastModified: cache[module].lastmod}
     if (cache[module].lastcheck + cacheInvalidate < new Date().getTime()) {
      update = await checkMeta(module)
      cache[module].lastcheck = new Date().getTime()
    }
    if (update.LastModified.toString() == cache[module].lastmod.toString()) return cache[module]
  }
    let srcS3 = await read(module)

    let data = Object.values(JSON.parse(srcS3.Body))
    cache[module] = { lastcheck: new Date().getTime(), lastmod: srcS3.LastModified, versionId: srcS3.VersionId, catalog: data }
    return cache[module]
}

if (process.server) module.exports = { getAllFilms, checkMeta}

with this the S3 file would first take 2000ms to download, then in the next call it took 1ms, taking the items from memory.

now with this new method for initializing nuxt and the latest version of libraries such as esm, this effect does not happen anymore, the cache variable is always starting null. apparently before it was only running the module.exports method in each call, but globals only once. now it seems to run globals and module.exports methods entirely every call.

this is probably not related to the change in nuxt, but something from esm, in any case I thought it was interesting how we can have long lived memory in Lambda. does anyone know if we can store data in say process.env or other cross-call object?

@bgdnp
Copy link

bgdnp commented Aug 3, 2019

@chriswilcox-mof Great solution, I received timeouts so I guessed it is now mandatory for lambda to return something so I just added return before calling nuxt() and it works like a charm. Thanks!

@MSkred
Copy link

MSkred commented Aug 21, 2019

Thank a lot to @chriswilcox-mof and @phpoenix you save my life. Great !

@thomas4Bitcraft
Copy link

thomas4Bitcraft commented Oct 30, 2019

Just for info:

// nuxt.js

const express = require('express')
const app = express()
const { Nuxt } = require('nuxt')
const path = require('path')

app.use('/_nuxt', express.static(path.join(__dirname, '.nuxt', 'dist')))
const config = require('./nuxt.config.js')
const nuxt = new Nuxt(config)
app.use(async (req, res) => {
   await nuxt.ready()
   nuxt.render(req, res)
})

module.exports = app
// index.js

const sls = require('serverless-http')
const binaryMimeTypes = require('./binaryMimeTypes')

const nuxt = require('./nuxt')
module.exports.nuxt = sls(nuxt, {
   binary: binaryMimeTypes
})

is also possible.

@matthew-inamdar
Copy link

@thomas4Bitcraft thanks for this! I can confirm as of today, this is the only solution that worked for me!

@danielroe danielroe added the 2.x label Jan 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.