Next.js: Cant handle static assets with serverless framework

Created on 15 Feb 2019  路  14Comments  路  Source: vercel/next.js

Bug report

Describe the bug

I cannot load the assets with a lambda with serverless framework.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Go to https://github.com/romainquellec/boilerplate, clone
  2. yarn
  3. yarn (global) add serverless
  4. yarn build
  5. yarn lambda
  6. See error on console or chrome console (assets don't load)

System information

  • OS: Windows
  • Version of Next.js: 8.0.1

Additional context

In lambda function, i'm doing :

app.use("/_next/static", express.static("../static"));
app.use("/static", express.static("../static"));

Most helpful comment

Changing app.use("/_next/static", express.static(path.join(__dirname, "/static"))); to app.use("/_next", express.static(path.join(__dirname, ".next"))); fixed it.

All 14 comments

This doesn't sound like a bug in Next.js 馃

I honestly have no idea. This example is pretty simple.
@vadorequest @Enalmada, do you know what's happenig ?

Idea :
Should we use aws-serverless-express or serverless-express instead of serverless-http ?

I am not doing any lambda right now because my bundle is just so dang huge but just to rule things out and help brainstorm ways of narrow it down...

Can you confirm if this happens on Next 7 or when doing a build from linux (Windows Subsystem for Linux to rule out paths issue)? Can you post the actual error on the chrome console...I am curious if there is any chance it provides any hints.

I'm not using Next 7 for lambda (and you should switch on Next 8, its so much easier for lambda).
I will try on WSL. Will give any hints later, weekend is coming ;)

@timneutkens I don't think that's a Next.js bug either. Assets (especially binary files) need to be treated particularly to work on AWS Lambda. It's more a usage issue IMHO.

I haven't had time to look into how Next 8 deals with assets and what's the recommended way to load them (assuming S3). I'll try to dive in later. Meanwhile, if anybody has any hint regarding the issue, it'd help! :)

Static assets should not be part of the lambdas basically. So indeed use s3 or another static file host.

I'm talking about the static folder generated by next.
All my images, gif, ... is on S3 but I dont want a different process for static js files generated by next.
I'm currently using serverless framework with razzle and basic assets handle is fine : https://github.com/CuistotduCoin/cuistot/tree/master/frontend

I dont see the difference with serverless and/or next on this one (except aws-serverless-express)

JFYI, I tried this :

const compression = require("compression");
const express = require("express");
const { parse } = require("url");
const pathMatch = require("path-match");
const awsServerlessExpress = require('aws-serverless-express');
const isProduction = process.env.NODE_ENV === "production";

// setup Express and hook up Next.js handler
const app = express();
app.use(compression());

const route = pathMatch();
const matches = [];

const binaryMimeTypes = ['*/*'];

// host the static files
app.use("/_next/static", express.static("./static"));
app.use("/static", express.static("./static"));

app.get('/', require('./serverless/pages/index').render)
app.get('*', (req, res) => {

  const parsedUrl = parse(req.url, true);
  const { pathname, query } = parsedUrl;
  let hasMatch = false;

  for (const match of matches) {
    const params = match.route(pathname);
    if (params) {
      try {
        require(`./serverless/pages${pathname}`).render(req, res, match.page, Object.assign(params, query))
      } catch (err) {
        require('./serverless/pages/_error').render(req, res, match.page, Object.assign(params, query))
      }
      hasMatch = true;
      break;
    }
  }
  if (!hasMatch) {
    try {
      require(`./serverless/pages${pathname}`).render(req, res, parsedUrl)
    } catch (err) {
      require('./serverless/pages/_error').render(req, res, parsedUrl)
    }
  }
})

// 404 handler
app.get("*", require('./serverless/pages/_error').render);

const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes);
const lambda = (event, context) => awsServerlessExpress.proxy(server, event, context);

// export the wrapped handler for the Lambda runtime
exports.handler = lambda;

not working either

Ok, I resolved this by :

// host the static files
app.use("/_next/static", express.static(path.join(__dirname, "/static")));

I suspect Windows for this. This should do the trick for win and linux.

Can someone with linux try this ?
https://github.com/romainquellec/boilerplate
I can make an example out of this for this repo.

Adding this as great examples : https://github.com/justinwhall/nextjs-serverless-aws

I am experiencing the same issue.

Changing app.use("/_next/static", express.static(path.join(__dirname, "/static"))); to app.use("/_next", express.static(path.join(__dirname, ".next"))); fixed it.

I'm closing this. Will try to make an example out of it later.

in next.config.js, add:

assetPrefix: './' 

then in you next app's root html:

src="/_next/...

will become to :

src="./_next/...

then in your nginx conf:

location ^~/yourpath {
  proxy_pass http://localhost:yournextappport/;
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

havefive picture havefive  路  3Comments

renatorib picture renatorib  路  3Comments

ghost picture ghost  路  3Comments

irrigator picture irrigator  路  3Comments

knipferrc picture knipferrc  路  3Comments