1

I've successfully deployed a node js ap with a Vue frontend on azure but whenever you visit a URL which is not the root, it shows a white screen with the message 'CANNOT GET /products' for example.

In the root of the web server, I have a index.js which will among other things load the content of the dist folder where the compiled vue frontend code is placed: app.use(express.static(__dirname + "/dist"));

I have tried changing my web.config file but if I change <action type="Rewrite" url="index.js"/> to /dist/index.html, my api endpoints stop working and it's basically only a frontend. This is my web config file:

<configuration>
 <system.webServer>
 <webSocket enabled="false" />
 <handlers>
  <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
  <add name="iisnode" path="index.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
  <rules>
    <!-- Do not interfere with requests for node-inspector debugging -->
    <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
      <match url="^index.js\/debug[\/]?" />
    </rule>

    <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
    <rule name="StaticContent">
      <action type="Rewrite" url="public{REQUEST_URI}"/>
    </rule>

    <!-- All other URLs are mapped to the node.js site entry point -->
    <rule name="DynamicContent">
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
      </conditions>
      <action type="Rewrite" url="index.js"/>
    </rule>
  </rules>
</rewrite>
<security>
  <requestFiltering>
    <hiddenSegments>
      <remove segment="bin"/>
    </hiddenSegments>
  </requestFiltering>
 </security>
</system.webServer>
</configuration>

`

Edit - more details on project setup

Folder structure:

Root:

enter image description here

/dist:

enter image description here

Index.js:

const contentRoutes = require("./api/content"); 
const userRoutes = require("./api/users");
const gymRoutes = require("./api/gyms");
...
app.use("/api/content", contentRoutes);
app.use("/api/users", userRoutes);
app.use("/api/gyms", gymRoutes);
...
app.use(express.static(__dirname + "/dist"));

app.listen(port, () => {
  console.log("Server is live");
});

Router.js in Vue project:

Vue.use(Router);

export default new Router({
 routes: [
  {
   path: "/",
   name: "index",
   component: index
   },
  {
   path: "/gyms/new",
   component: gymNew
   },
  {
    path: "/gyms/:id",
    component: gym
   },
   ...
  ],
  mode: "history"

Any idea what I'm doing wrong?

6
  • i believe you need this <action type="Rewrite" url="public{REQUEST_URI}"/> to be this <action type="Rewrite" url="dist{REQUEST_URI}"/> Commented Mar 27, 2018 at 22:11
  • I have tried changing the StaticContent rule url from public to dist but it didn't have any effect. Commented Mar 27, 2018 at 22:16
  • Oh ok, nevermind you're serving your statics through express. Should work as is, what's your F12 console saying when you get those CANNOT GET /x errors? There should be more context, check the Network tab as well. Commented Mar 27, 2018 at 22:22
  • Can you post an example of what the api and frontend routes look like? Commented Mar 27, 2018 at 22:22
  • I just get a Request Method: GET, Status Code: 404 Not Found. I'll post my frontend routes and api end points in a min. Commented Mar 27, 2018 at 22:26

2 Answers 2

3
+50
const express = require('express')
const serveStatic = require('serve-static')
const app = express()

// First serve static pages from dist folder
var staticPage = serveStatic('dist', {})
app.use(staticPage)

Since it was an SPA, you need to re-route to index.html every time the page refresh or do a new request

// the regex will check if the request url is not /api then redirect to index.html
app.get(/^((?!\/api\/).)*$/, function (req, res) {
    res.sendFile(__dirname + '/dist/index.html')
});
Sign up to request clarification or add additional context in comments.

Comments

0

This is an old post (and requires a lot of config that I no longer find necessary), but is the first thing I came across when researching this problem myself. So I will post my findings here, since this easily solved my problem: https://router.vuejs.org/guide/essentials/history-mode.html#internet-information-services-iis

This gist is to add a web.config as specified to the public folder, which will then be added to the dist folder for production.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.