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
Application should function normally.
After upgrading to v2.5.1 express always returns a "cannot GET /" message.
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
@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.
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"
}
}
I can confirm this was a breaking change for some programmatic users. This will be reverted back in 2.6.
@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
@xxRockOnxx
PS: No action is required from the side of users. Calling and awaiting on ready() after the constructor is still recommended.
Same issue with me as well. Trying get rid of this error from past 3 days but still could not find any solutions
@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
@pi0 i added that after reading all comments here and it is working fine now. Thank you so much for your reply.
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.
@zoellner
It's in there but not highlighted.
I've added an additional note 鈽猴笍
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',
],
});
@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.
@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
@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));
};
@chriswilcox-mof you, sir, are a life saver! Thanks a lot, this solution works perfectly!
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?
@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!
Thank a lot to @chriswilcox-mof and @phpoenix you save my life. Great !
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.
@thomas4Bitcraft thanks for this! I can confirm as of today, this is the only solution that worked for me!
Most helpful comment
@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
Then changed our lambda handler using this approach https://stackoverflow.com/a/47851485