npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@andrew-razumovsky/serverless-nextjs-plugin-individual-packaging

v2.5.1

Published

A serverless plugin for nextjs 8 serverless target

Downloads

66

Readme

UPDATE!

A new iteration of this project has been released powered by the amazing Serverless Components. Check it out here. As you can see, it lives in the same monorepo. The new version has feature parity with nextjs 9.0 and does not use CloudFormation, allowing faster deployments and no resource limit issues.

It is recommended for both existing and new users to try the new version. Obviously existing users of the next plugin don't have to migrate over straight away, the plan is to continue maintaining the plugin until the new component is more mature.

Serverless Nextjs Plugin

serverless Build Status Financial Contributors on Open Collective npm version Coverage Status Codacy Badge

A serverless framework plugin to deploy nextjs apps.

The plugin targets Next 8 serverless mode

demo

Contents

Motivation

Next 8 released official support for serverless! It doesn't work out of the box with AWS Lambdas, instead, next provides a low level API which this plugin uses to deploy the serverless pages.

Nextjs serverless page handler signature:

exports.render = function(req, res) => {...}

AWS Lambda handler:

exports.handler = function(event, context, callback) {...}

A compat layer between the nextjs page bundles and AWS Lambda is added at build time:

const compat = require("next-aws-lambda");
const page = require(".next/serverless/pages/somePage.js");

module.exports.render = (event, context, callback) => {
  compat(page)(event, context, callback);
};

Getting started

Installing

npm install --save-dev serverless-nextjs-plugin

Out of the box, the plugin won't require any configuration. If you need to override any defaults check this.

For example:

nextApp
│   next.config.js
│   serverless.yml
└───pages
│   │   home.js
│   │   about.js
│   │   admin.js

Edit the serverless.yml and add:

plugins:
  - serverless-nextjs-plugin

package:
  exclude:
    - ./**

You can exclude everything. The plugin makes sure the page handlers are included in the artifacts.

Hosting static assets

If you don't want to manage uploading the next static assets yourself, like uploading them to a CDN, the plugin can do this for you by hosting the asset files on S3.

The easiest way is to use a valid bucket URL in the assetPrefix field of your next configuration:

// next.config.js
module.exports = {
  assetPrefix: "https://s3.amazonaws.com/your-bucket-name"
};

The plugin will create a new S3 Bucket using the parsed name. On deployment, static assets will be uploaded to the bucket provisioned.

Alternatively, if you just want the assets to get uploaded to S3, you can provide the bucket name via the plugin config:

# serverless.yml
plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    assetsBucketName: "your-bucket-name"

Serving static assets

Static files can be served by following the NextJs convention of using a static and public folder.

From your code you can then reference those files with a /static URL:

function MyImage() {
  return <img src="/static/my-image.png" alt="my image" />
}

export default MyImage

To serve static files from the root directory you can add a folder called public and reference those files from the root, e.g: /robots.txt.

Note that for this to work, an S3 bucket needs to be provisioned as per hosting-static-assets.

For production deployments, enabling CloudFront is recommended:

# serverless.yml
plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    assetsBucketName: "your-bucket-name"
    cloudFront: true

By doing this, a CloudFront distribution will be created in front of your next application to serve any static assets from S3 and the pages from Api Gateway.

Note that deploying the stack for the first time will take considerably longer, as CloudFront takes time propagating the changes, typically 10 - 20mins.

You can provide your own configuration for the CloudFront distribution:

# serverless.yml
plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    assetsBucketName: "your-bucket-name"
    cloudFront: ${file(cloudfront-override.yml)}
# cloudfront-override.yml
# e.g. add custom domain name
Properties:
  DistributionConfig:
    Aliases:
      - my.alias.com
    ViewerCertificate:
      AcmCertificateArn: arn:aws:acm:xxxx
      ...

The configuration provided will be merged onto the defaults in packages/serverless-plugin/resources/cloudfront.yml.

Deploying

serverless deploy

When running serverless deploy all your next pages will be automatically compiled, packaged and deployed.

The Lambda functions created for each page have by default the following configuration:

handler: /path/to/page/handler.render
events:
  - http:
      path: pageName # home, about, etc. Unless is the index page which is served at /
      method: get
  - http:
      path: pageName # home, about, etc. Unless is the index page which is served at /
      method: head

Overriding page configuration

You may want to have a different configuration for one or more of your page functions. This is possible by setting the pageConfig key in the plugin config:

plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    pageConfig:
      about:
        memorySize: 512 # default is 1024
      home:
        timeout: 10 # default is 6

If you need to change the default configuration, such as memorySize, timeout etc. use the top level provider which will override all the functions configuration. For example, to change the memorySize to 512MB:

provider:
  name: aws
  runtime: nodejs8.10
  memorySize: 512
  ...

You can also add configuration for all page functions by adding an asterisk entry (*) to pageConfig. This is particularly useful when you have other functions in your service (i.e. an api) aside from the page functions and you only want to apply configuration changes to the latter:

plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    pageConfig:
      "*":
        layers:
          - arn:aws:lambda:${self:provider.region}:553035198032:layer:nodejs12:1

You can set any function property described here.

Custom page routing

The default page routes follow the same convention as next useFileSystemPublicRoutes documented here.

E.g.

| page | path | | --------------------------- | ------------------- | | pages/index.js | / | | pages/post.js | /post | | pages/blog/index.js | /blog | | pages/categories/uno/dos.js | /categories/uno/dos |

You may want to serve your page from a different path. This is possible by setting your own http path in the routes config. For example for pages/post.js:

class Post extends React.Component {
  static async getInitialProps({ query }) {
    return {
      slug: query.slug
    };
  }
  render() {
    return <h1>Post page: {this.props.slug}</h1>;
  }
}

export default Post;
plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    routes:
      - src: post
        path: posts/{slug}
        request:
          parameters:
            paths:
              slug: true

Custom error page

404 or 500 errors are handled both client and server side by a default component error.js, same as documented here.

Simply add pages/_error.js:

class Error extends React.Component {
  static getInitialProps({ res, err }) {
    const statusCode = res ? res.statusCode : err ? err.statusCode : null;
    return { statusCode };
  }

  render() {
    return (
      <p>
        {this.props.statusCode
          ? `An error ${this.props.statusCode} occurred on server (╯°□°)╯︵ ┻━┻`
          : "An error occurred on client"}
      </p>
    );
  }
}

export default Error;

Custom lambda handler

If you need to customize the lambda handler you can do so by providing a path to your own handler in the customHandler field. Note that it resolves the path to the custom handler relative to your next.config.js.

plugins:
  - serverless-nextjs-plugin

custom:
  serverless-nextjs:
    customHandler: ./handler.js

The custom handler needs to look something like this:

const compat = require("next-aws-lambda");

module.exports = page => {
  const handler = (event, context) => {
    // do any stuff you like

    // this makes sure the next page renders
    const responsePromise = compat(page)(event, context);

    // do any other stuff you like

    return responsePromise;
  };
  return handler;
};

All plugin configuration options

| Plugin config key | Type | Default Value | Description | | ----------------- | ------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | nextConfigDir | string | ./ | Path to parent directory of next.config.js. | | assetsBucketName | string | <empty> | Creates an S3 bucket with the name provided. The bucket will be used for uploading next static assets. | | cloudFront | bool | object | false | Set to true to create a cloud front distribution in front of your nextjs application. Also can be set to an object if you need to override CloudFront configuration, see serving static assets. | | routes | []object | [] | Array of custom routes for the next pages. | | customHandler | string | <empty> | Path to your own lambda handler. | | uploadBuildAssets | bool | true | In the unlikely event that you only want to upload static or public dirs, set this to false. | | createAssetBucket | bool | true | Set to false if you want to manage next assets yourself. |

Caveats

Beware this plugin relies on CloudFormation which has a hard limit of 200 resources. If you have a large number of pages in your application it is very likely that you will hit this limit. Use https://github.com/danielcondemarin/serverless-next.js/tree/master/packages/serverless-nextjs-component which solves this problem by not using CloudFormation.

Examples

See the examples/ directory.

Contributing

Please see the contributing guide.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]