It was a long and arduous road to finally get a working deployment of my app built in Vue/Nuxt.

While there are some bits of documentation about how to deploy Nuxt to various places like Heroku or GitHub Pages, there were no pointers towards how to get Nuxt running on Microsoft Azure — specifically a universal app that runs both server-side and client-side, and not just a static generated app or SPA-style client-side only app.

On top of that, I wasn’t particularly sure which files were even supposed to be on the server and which were not.

As of August 2018, here’s really all you need to know.

What Goes On My Server?

These are the only files that need to live in your wwwroot on your production server instance on Azure:

.nuxt

static

nuxt.config.js

package.json

server.js

So let’s go over those one at a time.

The .nuxt Directory

The .nuxt directory has everything Nuxt needs to run as a server-side application, and it also includes inside a directory called dist . This directory is populated with all the files that make up your app by running the command npm run build from the root directory of your app.

Inside dist you’re going to see something like the following:

0fdda7689bf96582760e.js

7a8ee1584491e3b3499a.js

5843c32d223ef79c6cac.js

7698b9b9d7a056e0332e.js

5359442cf7d324107315.js

c2dbf45c410d904f8449.js

These are all the compiled Javascript files that make up your individual .vue pages and components. Pretty straightforward.

You’ll also have by default:

index.spa.html

index.ssr.html

server-bundle.json

vue-ssr-client-manifest.json

These files are required elements of your app. For universal apps, you don’t really need index.spa.html , so you can safely delete that if you like. It’s 1KB, so, no big deal either way.

Making Sure The .CSS Is Actually Served As .CSS Files

153d433a761cf8ccc028.css

5376176449ad137de0b4.css

Then there are of course your stylesheets. Now, by default, you won’t see styles as their own separate files when building your app without first modifying your config file. So these might not be appearing after running npm run build for you. Here’s why:

The default mode is to include all the styles inside those .js files instead, and then it inlines all the css when you load the app in your browser instead of pointing to external .css files. So you end up with a ton of <style type="text/css">...</style> declarations in your <head> .

In order to ensure these .css files are actually present when you build your app, you’ll need to use a few lines in your nuxt.config.js configuration file. At the top, you’ll want to install and import UglifyJS and the optimize-css-assets-webpack-plugin:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

Then down below, you’ll want to include the following in your build section:

module.exports = {

...

build: {

extractCSS: true,

optimization: {

minimizer: [

new UglifyJsPlugin({

cache: true,

parallel: true,

sourceMap: true // set to true if you want JS source maps

}),

new OptimizeCssAssetsPlugin({})

],

splitChunks: {

cacheGroups: {

styles: {

name: 'styles',

test: /\.(vue)$/,

chunks: 'all',

enforce: true

}

}

}

}

}

...

}

The extractCSS is self-explanatory — it lets Nuxt know you want to pull the CSS out of the .js files and make .css files to point to instead.

The UglifyJsPlugin is in there to ensure all the .js gets compressed and minified since we are modifying the minimizer settings of webpack.

The OptimizeCssAssetsPlugin is doing exactly what you’d think: optimizing the css assets by minifying them, removing whitespace, and getting them to be as lean as possible.

The splitChunks section is making sure that instead of creating a ton of stylesheets for every single .vue single file component and page in your app, it consolidates all of your styles into just a few files instead.

OK. So now we have all our .js files, our .css files, and the rest of the dist folder.

The Other Files and Directories in Your Deployment Folder

So we still have a few other directories and files left:

static

nuxt.config.js

package.json

server.js

So the static directory is just copy/pasted from your app root. It’s all the static files your app uses. Things like fonts, images, ads.txt, favicon.ico, robots.txt — anything that should be served from "/" on your site, essentially.

nuxt.config.js can also just be copy/pasted from your app root. It still tells Nuxt how you want your app configured and is a required file. You don’t need to change anything in it unless you have very specific production-only requirements.

Your package.json can be copy/pasted, but you’ll likely want to trim the fat on it to include only the following:

{

"name": "yourappname",

"engines": {

"node": ">=6.11",

"npm": ">=5.6.0"

},

"dependencies": {

"nuxt-edge": "latest"

}

}

(Side note: I’m referencing nuxt-edge here because Nuxt 2.0 is not out yet, but by the time you read this, you may want to just reference "nuxt": "^2.0.0" instead.)

Essentially, all you need is name , the engines block to indicate to Azure which versions of Node and NPM should be running, and then any of your app dependencies.

(Note: You don’t need to include your devDependencies , because your app has already been built and lives in the .nuxt/dist folder, and you won’t need to rebuild your app on the server — thus, no need for the devDependencies on your production server on Azure.)

Last, but not least, we have server.js . This was the one file that was the most confusing to me leading up to figuring all of this out, because there’s no real mention of it in any documentation in how it relates specifically to deploying to Azure. Here’s my server.js in its entirety:

const express = require('express')

const {Nuxt} = require('nuxt-edge') const app = express() const host = process.env.HOST || '127.0.0.1'

const port = process.env.PORT || 3000 // Import and set Nuxt.js options

let config = require('./nuxt.config.js') const nuxt = new Nuxt(config) // Give Nuxt middleware to express

app.use(nuxt.render) // Listen the server

app.listen(port, host);

console.log('Server listening on ' + host + ':' + port);

Essentially this is just setting the host and port, instantiating Nuxt, and letting Express serve the app.

OK. So make sure you run npm run build once more now that our configurations are all set, copy our directories and files (.nuxt, static, nuxt.config.js, package.json, server.js) to a new folder — maybe named “deployment”, or something similar — and we’re ready to go.

We’ve Got Our Files. How Do We Get Them Up On Azure?

This was another tricky part for me due to lack of clear documentation, but I referenced this guide on Azure Node.JS deployments and it worked for me: https://code.visualstudio.com/tutorials/nodejs-deployment/getting-started

This will get your app up on a Node.JS web app on Azure on the free tier. It costs nothing, but you can always scale up the app to make it perform better once you have it deployed. This is also deploying from a Windows machine.

Tl;dr — The quick and dirty of the above link on deploying to Azure is:

Go to your “deployment” directory that contains (.nuxt, static, nuxt.config.js, package.json, server.js) in PowerShell

Make sure you have Azure CLI and Git installed on your machine

and installed on your machine Create a resource group : az group create --name myResourceGroup --location "Your Location" (reference the Azure locations for the location name nearest you — myResourceGroup can be whatever name you like)

: (reference the Azure locations for the location name nearest you — can be whatever name you like) Create an Azure App Service plan : az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku F1 (again, myAppServicePlan can be named however you like)

: (again, can be named however you like) Create a web app: az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app_name>

Initialize your Git repo:

git init

git add -A

git commit -m "initial commit"

Set the remote: az webapp deployment user set --user-name <UserName> --password <Password>

git remote add azure <your git endpoint>

Deploy it! git push azure master

If the deployment was successful and you didn’t hit any errors, then you should be able to browse to the deployed address <yourappname>.azurewebsites.net

If it fails to load the first time, try refreshing your browser a few times. On the free tiers, Azure sometimes takes a bit to get going, but eventually it should load without fail.

Whew! We Did It!

I hope this helps someone else out there who is struggling to get their Nuxt app onto Azure. Of course, there are a million different things to consider for deployment to ensure great Lighthouse scores, or different middleware options, or if you have specific preprocessing you like to use, or any number of things. I encourage you to come join the Discord server where there are always other developers hanging out and helping each other get through the tough problems. Become a part of the community, and we can solve it together!