Skip to main content

Vue.js Apps on Apache and Nginx

in category Projects -> Web Development -> Vue.js Apps on Apache and Nginx. Updated at Wed, 07 Feb 2024 11:42:54 EST

Fixing Vue app routing issues after npm run build. Easy fix for running your Vue app on a typical web server.


After doing $ npm run build for your Vue application, Vue creates a js 'module' and places it in a dist folder within your build directory. If you look in the dist folder you'll (typically) see an index.html file and an assets folder. In order to run that app on Apache or Nginx, with index.html being the doc root index, you need to add a vhost to your server config and point the document root to the dist folder. You can place the dist folder anywhere as long as your server config knows where to find this document root. You can likewise rename the dist folder.

After doing $ npm run build, the output dist/index.html will typically look like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App>/title>
    <script type="module" crossorigin src="/dist/assets/index-avtuWnnn.js"></script>
    <link rel="stylesheet" crossorigin href="/dist/assets/index-WjEyzLJD.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

After your web server is pointed to the dist folder as doc root, you head to that location whether it's just your localhost server or somewhere else and you pull up a blank page with type errors that look like this:

Loading module from “https://vue.localhost/dist/assets/index-avtuWnnn.js” was blocked because of a disallowed MIME type (“text/html”).

Initially, the first time this happened to me, I went scoping around the net looking for a solution and came across all sorts of complicated answers. I read answers at Stackoverflow, I checked the Vue docs.. I even went as far as doing a manual http-equiv="content-type" line in the index.html header. Nothing worked. Vuejs.org does have docs regarding this path and how to configure the build path differently for different environments. Those are good docs and useful for other things, like a big project. But mine is a simple SPA and if you are anything like me, you need this folder to be re-useable so that you aren't loading more and more node modules and modifying the build config would chain me to that action which might be problematic downline. Not irreversible but I prefer to stay at default. Those node modules take up a lot of disk space if you make a new folder whenever you want to build a simple widget. So, re-useable is important.

I realized that the path as written by Vue's run build command is simply wrong for a simple SPA but better left as is because mostly, I wasn't paying attention. Dist is the docroot here, recall? So, as usual, the actual answer is not complicated at all. Simply remove '/dist' from the html src links so that your index.html now looks like this and everything should run as expected.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App>/title>
    <script type="module" crossorigin src="/assets/index-avtuWnnn.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-WjEyzLJD.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
If your app is not an SPA and the index.html is located elsewhere or becomes part of another page, you still simply need to remove '/dist' from the src references or replace it with the actual folder name path/location of the Vue assets.

Keywords
Vue app routing, npm run build,