Edgio

Nuxt.js

This guide shows you how to deploy a Nuxt.js application to Edgio. If you run into any issues please consult the Troubleshooting section.

Prerequisites

Setup requires:

Install the Edgio CLI

If you have not already done so, install the Edgio CLI.
Bash
1npm i -g @edgio/cli@latest

Creating a new Nuxt app

If you don’t already have a nuxt.js application, you can create one using:
Bash
1npm create nuxt-app my-nuxt-app
Nuxt’s create module will ask you a series of questions to configure your app. Make sure you answer as follows:
  • For Choose rendering mode select Universal (SSR / SSG)
  • Your answers to the other questions should not matter for the purposes of this guide.

Adding Edgio to an existing Nuxt app

To prepare your Nuxt.js application for Edgio:
  1. In the existing nuxt.config.js configuration, add “@edgio/nuxt/module” to buildModules:
JavaScript
1// nuxt.config.js
2
3module.exports = {
4 /* ... */
5 buildModules: [['@edgio/nuxt/module', { edgioSourceMaps: true }]],
6}
Options:
  • edgioSourceMaps: true|false: when true, the Edgio cloud build includes sourcemap files which make debugging easier when tailing the server logs in the Edgio Console. It also increases the Edgio cloud bundle size, which may push your deployments over the 50MB (compressed) limit.
We noticed some performance issues related to sourcemaps being loaded in the Edgio cloud, which may result in 539 project timeout errors. In case you encounter such errors, please try again with sourcemaps disabled. This document will be updated once the problem is fully resolved.
  1. Run edgio init to configure your project for Edgio.
Bash
1edgio init --edgioVersion latest
The edgio init command will automatically add all the required dependencies and files to your project. These include:
  • The @edgio/core package
  • The @edgio/nuxt package
  • The @edgio/vue package
  • edgio.config.js - Contains various configuration options for Edgio.
  • routes.js - A default routes file that sends all requests to nuxt.js. You can update this file to add caching or proxy some URLs to a different origin as described later in this guide.
  • sw/service-worker.js - A service worker that provides static asset and API prefetching.
This command will also update your package.json with the following changes:
  • Moves all packages in dependencies to devDependencies except those listed in the modules property of nuxt.config.js.
  • Adds @nuxt/core to dependencies
  • Adds several scripts to run the available edgio commands
As an example, here’s the original package.json from Nuxt’s create step:
JSON
1{
2 "name": "my-nuxt-app",
3 "version": "1.0.0",
4 "description": "My remarkable Nuxt.js project",
5 "author": "Techy Ted",
6 "private": true,
7 "scripts": {
8 "dev": "nuxt",
9 "build": "nuxt build",
10 "start": "nuxt start",
11 "generate": "nuxt generate"
12 },
13 "dependencies": {
14 "@edgio/cli": "^7.0.0",
15 "@edgio/core": "^7.0.0",
16 "@edgio/nuxt": "^7.0.0",
17 "nuxt": "^2.0.0"
18 },
19 "devDependencies": {}
20}
And here is the package.json after modifications by edgio init:
JSON
1{
2 "name": "my-nuxt-app",
3 "version": "1.0.0",
4 "description": "My remarkable Nuxt.js project",
5 "author": "Techy Ted",
6 "private": true,
7 "scripts": {
8 "dev": "edgio run",
9 "build": "edgio build",
10 "start": "edgio run",
11 "prod": "edgio run --production",
12 "generate": "nuxt generate"
13 },
14 "dependencies": {
15 "@nuxt/core": "^2.14.2"
16 },
17 "devDependencies": {
18 "@edgio/cli": "^7.0.0",
19 "@edgio/core": "^7.0.0",
20 "@edgio/nuxt": "^7.0.0",
21 "@edgio/vue": "^7.0.0",
22 "dotenv": "^8.2.0",
23 "nuxt": "^2.0.0",
24 "serverless": "^1.64.0",
25 "serverless-dotenv-plugin": "^2.3.2",
26 "serverless-offline": "^5.14.1"
27 }
28}

Run the Nuxt.js app locally on Edgio

Run the Nuxt.js app with the command:
Bash
1npm run edgio:dev
Load the site: http://127.0.0.1:3000

modules vs buildModules

Nuxt does not bundle packages listed in the modules property of nuxt.config.js when building your app for production. This can lead to an increased bundle size and slow down server-side rendering. Most Nuxt modules can be moved to buildModules. We recommend the following to maximize performance of server-side rendering in the cloud:
  • Move all entries from modules to buildModules in nuxt.config.js
  • Move all corresponding packages from dependencies to devDependencies in package.json
  • Run yarn install or npm install to update your lock file.
Doing so will exclude these modules from your production deployment and keep the bundle size as small as possible.

Routing

The next few sections of this guide explain how Edgio interacts with Nuxt’s routing, which is important if you are migrating an existing application. If you just created a new nuxt app, you can jump to Running Locally and come back to these sections later. Edgio supports Nuxt.js’s built-in routing scheme. The default routes.[js|ts] file created by edgio init sends all requests to Nuxt.js via a fallback route:
JavaScript
1// This file was added by edgio init.
2// You should commit this file to source control.
3
4import { Router } from '@edgio/core/router';
5import { nuxtRoutes } from '@edgio/nuxt';
6
7export default new Router()
8 .match('/service-worker.js', ({serviceWorker}) => {
9 serviceWorker('.nuxt/dist/client/service-worker.js');
10 })
11 .use(nuxtRoutes);

nuxtRoutes Middleware

In the code above, nuxtRoutes adds all Nuxt.js routes based on the /pages directory. It’s also compatible with extending Nuxt’s router via the router config in nuxt.config.js, for example:
JavaScriptnuxt.config.js
1export default {
2 // ... more config ...
3 router: {
4 // For example, we can extend the nuxt router to accept /products in addition to /p.
5 // The nuxtRoutes middleware automatically picks this up and adds it to the Edgio router
6 extendRoutes(routes, resolve) {
7 routes.push({
8 path: '/products/:id?',
9 component: resolve(__dirname, 'pages/p/_id.vue'),
10 });
11 },
12 },
13 // ... more config ...
14};
You can add additional routes before and after nuxtRoutes, for example to send some URLs to an alternate backend. This is useful for gradually replacing an existing site with a new Nuxt.js app.
A popular use case is to fallback to a legacy site for any route that your Nuxt.js app isn’t configured to handle:
JavaScript
1import { Router } from '@edgio/core/router';
2import { nuxtRoutes } from '@edgio/nuxt';
3
4export default new Router()
5 .use(nuxtRoutes)
6
7 // Proxy non-Nuxt.js routes to your origin site
8 .match('/:path*', {
9 origin: {
10 set_origin: 'origin',
11 },
12 });
To configure the origin backend, use edgio.config.js:
JavaScriptedgio.config.js
1module.exports = {
2 // Other config options...
3
4 // If you need to proxy some URLs to an origin instead of your Nuxt.js app, you can configure the origins here:
5 origins: [
6 {
7 // The name of the backend origin
8 name: 'origin',
9
10 // When provided, the following value will be sent as the host header when connecting to the origin.
11 // If omitted, the host header from the browser will be forwarded to the origin.
12 override_host_header: 'example.com',
13
14 // The list of backend hosts
15 hosts: [
16 {
17 // The domain name or IP address of the origin server
18 location: 'example.com',
19 },
20 ],
21 },
22 ],
23};
You may define the origins configuration at the root or within an environment-specific object (e.g., environments.production.origins[0]). Defining it at the root may overwrite your origin configurations for the environment to which your build is being deployed. If your environments use different origin configurations, we recommend that you define it within an environment-specific object.
Learn more about environments and the edgio.config.js file.

Caching

The easiest way to add edge caching to your nuxt.js app is to add caching routes before the middleware. For example, imagine you have /pages/c/_categoryId.js:
JavaScript
1export default new Router().use(nuxtRoutes).get('/pages/c/:categoryId', {
2 caching: {
3 max_age: '1d',
4 stale_while_revalidate: '1h',
5 service_worker_max_age: '1d',
6 bypass_client_cache: true,
7 },
8 headers: {
9 set_response_headers: {
10 'x-sw-cache-control': 'max-age=86400',
11 },
12 },
13});

Prefetching

The @edgio/nuxt/module builds a service worker that enables prefetching using Edgio and injects it into your app’s browser code. The service worker is based on Google’s Workbox library. The entry point for the service worker source code is sw/service-worker.js. If your app has an existing service worker that uses workbox, you can copy its contents into sw/service-worker.js and simply add the following to your service worker:
JavaScript
1import { Prefetcher } from '@edgio/prefetch/sw';
2new Prefetcher().route();
The above allows you to prefetch pages from Performance’s cache to greatly improve browsing speed. To prefetch a page, add the Prefetch component from @edgio/vue to any router-link or nuxt-link element:
JavaScript
1<template>
2 <ul v-for="product in products">
3 <li>
4 <Prefetch v-bind:url="'/api/' + product.url">
5 <nuxt-link v-bind:to="product.url">
6 <img v-bind:src="product.thumbnail" />
7 </nuxt-link>
8 </Prefetch>
9 </li>
10 </ul>
11</template>
12<script>
13 import { Prefetch } from '@edgio/vue'
14 export default {
15 components: {
16 Prefetch,
17 },
18 }
19</script>
The Prefetch component fetches data for the linked page from Performance’s cache based on the url property and adds it to the service worker’s cache when the link becomes visible in the viewport. When the user taps on the link, the page transition will be instantaneous because the browser won’t need to fetch data from the network.

Serving Sitemap with SSR

You can configure Nuxt to generate a sitemap in SSR mode with the following configuration:
JavaScriptnuxt.config.*
1export default {
2 /* ... */
3
4 // Modules: https://go.nuxtjs.dev/config-modules
5 modules: ['@nuxtjs/sitemap'],
6
7 sitemap: {
8 hostname: 'yourhost.com',
9 path: '/sitemap.xml',
10 defaults: {
11 lastmod: new Date(),
12 changefreq: 'weekly',
13 priority: 0.8,
14 },
15 },
16};
Within the Edgio router, add the following:
JavaScriptroutes.js
1import {Router} from '@edgio/core/router';
2import {nuxtRoutes} from '@edgio/nuxt';
3
4export default new Router()
5 .use(nuxtRoutes)
6
7 // Instruct Edgio to send traffic for /sitemap.xml to Nuxt middleware
8 .match('/sitemap.xml', ({ renderWithApp}) => {
9 renderWithApp();
10 })
This will send all traffic for /sitemap.xml to Nuxt middleware for server-side rendering.

Static Sites

Edgio supports fully and partially static sites using Nuxt generate. To deploy a static Nuxt site on Edgio, simply set target: 'static' in nuxt.config.js and run edgio deploy. This will run nuxt build and nuxt generate to generate a static version of your site.

Incremental Static Rendering (ISG)

By default, requests for any pages that are not statically rendered at build time will fall back to server side rendering. If you use the Edgio router to cache pages that are not statically rendered, the first user who attempts to access the page will see the fallback HTML page generated by Nuxt (200.html by default). Edgio will render and cache the HTML in the background so that subsequent visits result in a full HTML response. This behavior is similar to Next.js incremental static rendering (ISG). Here is an example route that adds caching for a partially static page:
JavaScriptroutes.js
1import { Router } from '@edgio/core/router';
2import { nuxtRoutes } from '@edgio/nuxt';
3
4export default new Router().use(nuxtRoutes).get('/products/:id', {
5 caching: {
6 // Requests for product pages that are not statically generated will fall back to SSR.
7 // The first user will see the 200.html loading page generated by Nuxt.
8 // Edgio will render full HTML response in the background and cache it for one day at the edge.
9 // All future requests to the page will result in the full HTML response.
10 max_age: '1d',
11 // continue to serve stale responses from the edge cache while refreshing via SSR in the background
12 stale_while_revalidate: '1h',
13 },
14});

Rendering a 404 Page

If you set the fallback property in the generate config to true, Nuxt.js will generate a 404.html page that will be served whenever the URL does not match a static page. Edgio will send a 404 http status for these URLs. Note that if you set the fallback property to a string, Nuxt will generate a fallback page with that name, and Edgio will serve it with a 200 http status when the URL does not match a statically generated page.

includeFiles

Nuxt requires that certain resources are included in a build and deploy to have access to them. As such, at times this will require additional configuration. To include additional resources for server side rendering, API calls, etc., use the includeFiles option in your edgio.config.js file. Read more
In this example, we would have an api folder that we want to include all items from.
JavaScript
1module.exports = {
2 connector: '@edgio/nuxt',
3
4 serverless: {
5 // Set to true to include all packages listed in the dependencies property of package.json when deploying to Edgio.
6 // This option generally isn't needed as Edgio automatically includes all modules imported by your code in the bundle that
7 // is uploaded during deployment
8 // includeNodeModules: true,
9
10 // Include additional paths that are dynamically loaded by your app at runtime here when building the serverless bundle.
11 include: ['api/**/*'],
12 },
13};
In addition, if includeNodeModules does not copy over the necessary package that may be needed in production, it can be included via this key as well. For instance,
JavaScript
1module.exports = {
2 /* ... */
3 serverless: {
4 includeFiles: ['api/**/*', 'node_modules/some_package/**/*'],
5 },
6};

Nitro

The Nuxt team provides a renderer called Nitro which optimizes your application for serverless deployment and greatly minimizes the size of your server application bundle. If you’re running into the size limitation for serverless bundles (50MB), you might try adding Nitro to your app. As of June 2021 Nitro is still not production ready, so use at your own risk.
Edgio provides a connector specifically for Nuxt apps that use nitro called @edgio/nuxt-nitro.
To add Nitro to your app, make the following changes:
  1. Install nitro and the connector as dev dependencies:
Bash
1npm install -D @nuxt/nitro @edgio/nuxt-nitro`
  1. Ensure buildModules in nuxt.config.js contains the following:
JavaScript
1buildModules: [
2 '@nuxt/nitro/compat',
3 '@edgio/nuxt-nitro/module', // If you have previously added @edgio/nuxt/module you can remove it.
4 // ...others...
5],
  1. Add the following to nuxt.config.js:
JavaScript
1publicRuntimeConfig: {
2 nitroVersion: require('@nuxt/nitro/package.json').version,
3},
  1. If your nuxt.config.js has a target property, remove it.
  2. If you’ve previously added @edgio/nuxt as a dependency, you can remove it.

Additional Nitro Resources

Running Locally

Test your app with Sites on your local machine by running the following command in your project’s root directory:
Bash
1edgio build && edgio run
You can do a production build of your app and test it locally using:
Bash
1edgio build && edgio run --production
Setting --production runs your app exactly as it will be uploaded to the Edgio cloud using serverless-offline.

Deploying

Deploy your app to the Sites by running the following command in your project’s root directory:
Bash
1edgio deploy
Your initial CDN-as-code deployment will generate system-defined origin configurations along with those defined within your edgio.config.js. Learn more about system-defined origins.
See Deployments for more information.

Related Resources

Below are a few helpful resources that may be referenced in this guide for configuring, managing, and serving your property on Edgio:

Troubleshooting

The following section describes common issues and their workarounds.

I get an error message Nuxt.js Internal Server Error

This may be because you have a custom server framework (such as Express). Please make sure you selected None when asked to choose Choose custom server framework during the creation of your nuxt app.

edgio init doesn’t work

If you get a command not found error such as:
Bash
1edgio init
2- bash: edgio: command not found
Make sure you installed the Edgio CLI
Bash
1npm i -g @edgio/cli@latest

Make sure your version of the Edgio CLI is current

If you previously installed the Edgio CLI, make sure your version is current.
Check npm for the latest released version of the CLI:
Bash
1npm show @edgio/cli version
24.0.0
Compare the latest release against the version currently installed on your system:
Bash
1edgio --version
27.0.0
If your version is out of date you can update it by running
Bash
1npm update -g @edgio/cli

Error on deploy: edgio-deploy-lambda: Unzipped size must be smaller than...

As the error states, there is an upper limit on how big a package can be when deployed to the Edgio cloud. Some common strategies for solving:
  • You may need to move some dependencies as described here. Only dependencies are copied up to the lambda.
  • Make sure you are using imports in a smart way. A common example is changing: import { get } from lodash to import get from lodash/get to avoid unnecessary bloat in your modules
You can view what is included in your package under .edgio/lambda/ after a build, and running du -h -d 1 on the directories in a shell will output the size of each directory and help you identify where space savings can be found, ie du -h -d 1 .edgio/lambda/.nuxt