Ariana Grande once said, “One taught me patience. And one taught me pain”. She was talking about her ex’s. I’m here today to talk to you about Nuxt’s.
Nuxt’s? Nuxt’is? Nuxt’ises?
What is Nuxt anyway?
Nuxt is “the VueJS framework”. That’s what it says on their website and why would they lie.
It’s kinda hard to nail down exactly what Nuxt does, because it does so much. It will automatically setup routing based on your folder structure. It will automatically do code splitting for static sites. It will automatically cause someone write a blog post with a few too many uses of the word “automatically:”.
But it’s probably best known as the way that you do server-side rendering with Vue.
My sample app is a single page with one XMLHTTPRequest (XHR) which pulls some fake images in from the JSON placeholder API. I was expecting better fake images than this, but I suppose you can’t complain about free. Like when my sister-in-law rented a margharita machine and then made them too weak. “Listen, thanks for the free alcohol, but I am dissapointed.”
Here’s the entirety of the code used to make this page.
Not super exciting, but enough to test out Nuxt’s value proposition of rendering apps on the server. On line 29 there is an HTTP call to the endpoint made with
axios. Even though this code is in the component, Nuxt is going to make that call and compile this template on the server. So the page we get will already have all of the markup in it.
But how do we know for sure that Nuxt is actually doing this? What if it’s just lying to us? How can I ever trust anyone again after left-pad?
Yep - all of the markup is definitely there. And it ‘aint pretty either. But that’s OK because it’s minified or something. And smaller is always better on the web. OR IS IT.
You can also open the dev tools and just look for an XHR. It will be conspicuously absent.
I didn’t have too much trouble getting this far. Nuxt is….different than a standard Vue application, but it’s not a brick to teeth. It’s relatively easy to just scaffold out a new app and then read the first paragraph of the “Getting Started” page and assume that you know everything already.
Then I went to deploy it.
Since Nuxt is rendering things on the server, Nuxt apps require a server. A node server to put too fine a point on it. I’m using Azure, so that means AppService. Vue apps that are single-page applications can be hosted on Azure Storage.
Before the app can be run, it has to be built. Ideally, we want this to happen on the server. The preferred workflow is…
- Make a change
- Check into Github
- Azure pulls in code automatically
- Azure performs build
- Azure starts the site
This workflow lets you focus on writing code, not deploying things. You just check them into source control and your site is magically updated. This is kind of like the simplest possible form of DevOps.
To set up a workflow like this in Azure, I need to first decide if I’m more of a Windows guy or more of a Linux guy. Azure supports both operating systems, and the one that you choose matters a whole lot. Just wait.
Let’s start with Linux. It’s important that we start with Linux because Linux is the preferred way to run Node applications in Azure. I bolded that statement because it’s important. It means that the effort to improve the Node experience in Azure is focused around Linux.
Running a Nuxt application on AppService for Linux “just works” thanks to a new build tool in Azure called “Oryx”. In fact, Oryx just rolled out this month. Welcome to the world, Oryx! Sorry about 2019.
All it takes to deploy and build this thing on Azure, is to configure the site for Git or GitHub deployment and check the project into the repo.
Oryx will pull in the code, run an
npm install and then do
npm run build. The Git logs will show that a
nuxt build did occur.
Browse to the site and…
It takes a LONG time for Azure to return this error and I’ve been working with Azure long enough to know that when this happens, it’s probably because Azure cannot bind to a port or address. That happens if the app is trying to bind to some hard-coded address (like localhost) or some hard-coded port (like 3000).
A lot of hosting providers have this issue. This included sites on Heroku and anywhere else that uses containers to host apps like Azure does. To fix it, the Nuxt docs say to include a section in the
nuxt.config.js that binds to 0.0.0.0.
Excellent! Not too bad. The host setting is really the only thing that might trip you up here.
That’s Linux. Now let’s talk about Windows.
Deploying To Windows
Deploying to Windows is quite a bit more….interesting. There is no Oryx build tool for Windows. Instead, you get something called “Kudu”.
By default, Kudu doesn’t build anything. You have to include a
.deployment file with the right setting to get it to perform a build. That just happens to be the
The problem is that your definition of a build and Kudu’s definition of a build are probably not the same. When I say build, I mean
npm install and then
npm run build. Kudu’s definition stops at
npm install. But since Kudu is already running an
npm install, we can trick it into also running the build command by just making it a
"postinstall": "npm run build"
It works! Wait. Kind of.
Well it worked in so much as Kudu did run the
postinstall hook, but the build fails. And it fails because
function is an unexpected token. Anytime you see “unexpected token” as an error, the problem is likely because your Node version is wrong. I scrolled back up through the logs and saw this…
My guess is Node 6.9.1 doesn’t support
Nope. Looks like version 7.10.1 is the minimum for that. To stay safe, let’s choose the highest supported version of Node in Azure, which at the time of this writing, is
10.15.2. The most reliable way to set the
WEBSITE_DEFAULT_NODE_VERSION in Azure is to do it via an App Setting. In my experience, using the
engines property in the
package.json does not have any effect.
Now we’ll just browse to the site….
What’s the word when something should work, but it doesn’t work and you don’t know why? Oh yeah, “programming”.
Scrolling back up through the output reveals this…
Well it’s not an invalid startup command, but Kudu is expecting something in the format of
node entry-point. There is an interesting line below that one that says…
Missing server.js/app.js files, web.config is not generated
What’s happening here is Windows uses IISNode to run the application. IISNode requires a
web.config to set the entry point and root directory. If you have an
serverjs file in the root of your app, Kudu will use that file to automatically generate a
So I added a
server.js file to the root of my project that just required in my actual startup file.
Not terrible, but not terribly intuitive either. You don’t know what you don’t know. And if you didn't know, now you know.
Look what you taught me
I’ll be honest, figuring out the Windows part of this thing was no fun. Patience and pain. That said, I do feel like I understand Azure AppService for Windows way more than I ever thought that I would. At least enough to write a blog post.
Oryx is new, and it’s a much-welcomed improvement. It works the way that I would expect it to, which is kinda all we’re really asking for as developers. It’s like the Dyson guy used to say…
I just think that things should work
-The Dyson Vacuum Cleaner Guy