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

thejmill
0
thejmill
commented a year ago

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.

bug
0
Gedminas
0
Gedminas
commented a year ago

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

0
manniL
7.0k
manniL
commented a year ago

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

0
alanmarcos
0
alanmarcos
commented a year ago

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"
      }
    }
0
pi0
37.3k
pi0
commented a year ago

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

0
xxRockOnxx
0
xxRockOnxx
commented a year ago

@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

0
manniL
7.0k
manniL
commented a year ago

@xxRockOnxx

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

From https://github.com/nuxt/nuxt.js/pull/5413

0
prakashbharti786
0
prakashbharti786
commented a year ago

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

0
pi0
37.3k
pi0
commented a year ago

@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

1
prakashbharti786
0
prakashbharti786
commented a year ago

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

0
zoellner
0
zoellner
commented a year ago

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.

0
manniL
7.0k
manniL
commented a year ago

@zoellner

It's in there but not highlighted.
grafik

I've added an additional note ☺️

0
lukaVarga
3
lukaVarga
commented a year ago

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',
  ],
});
0
pi0
37.3k
pi0
commented a year ago

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

0
lukaVarga
3
lukaVarga
commented a year ago

@pi0 thanks for a quick response. You mean ts-node, right?
I created a reproduction and opened a new issue - https://github.com/nuxt/nuxt.js/issues/5502

0
chriswilcox-mof
0
chriswilcox-mof
commented a year ago

@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));
};
0
lukaVarga
3
lukaVarga
commented a year ago

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

0
dseeker
0
dseeker
commented a year ago

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?

0
phpoenix
0
phpoenix
commented 8 months ago

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

0
MaximeScibetta
0
MaximeScibetta
commented 8 months ago

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

0
thomas4Bitcraft
0
thomas4Bitcraft
commented 5 months ago

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.

0
matthew-inamdar
0
matthew-inamdar
commented 2 months ago

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

0
Informations
Bug ReportOpen
#c8955 - Created a year ago