Error: 404 Not Found The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I have deployed a simple webapp to Azure app service. base url works fine but when I try to hit baseurl/hello endpoint I get the error.
Setup works locally, but I have been pondering my brains out to figure how I can get express to redirect requests in Azure.
web.config
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- SPA fallback rule to handle client-side routing -->
<rule name="SPA Routing" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- Exclude /hello and any other endpoints -->
<add input="{REQUEST_URI}" pattern="^/hello" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
package.json
"scripts": {
"dev": "nodemon -w src/server -x tsx src/server/main.ts",
"start": "cross-env NODE_ENV=production tsx src/server/main.ts",
"build": "vite build && cpx web.config dist/"
server/main.ts
import express from "express";
import ViteExpress from "vite-express";
const app = express();
app.get("/hello", (_, res) => {
res.send("Hello Vite + React + TypeScript!");
});
const port = process.env.PORT || 3000;
ViteExpress.listen(app, +port, () =>
console.log(`Server is listening on port ${port}...`)
);
When I tried your code, even I was unable to redirect to /hello
endpoint in Azure App Service.
I added the below lines of code to the main.ts
file. this setup serves all static files from the dist
folder and allowing the front-end framework to handle the route.
import path from 'path';
app.use(express.static(path.join(__dirname, '../../dist')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../dist', 'index.html'));
});
Below is the complete code of main.ts.
src/server/main.ts:
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import ViteExpress from 'vite-express';
const app = express();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
app.use(express.static(path.join(__dirname, '../../dist')));
app.get('/hello', (_, res) => {
res.send('Hello Vite + React + TypeScript!');
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../dist', 'index.html'));
});
const port = process.env.PORT || 3000;
ViteExpress.listen(app, +port, () =>
console.log(`Server is listening on port ${port}...`)
);
In local environment vite-express
handles both server and client, but in azure we need to define /hello
route in vite.config.ts
.
vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/hello': {
target: `http://localhost:${process.env.PORT || 3000}`,
changeOrigin: true,
},
},
},
});
package.json:
{
"name": "my-vite-express-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "nodemon -w src/server -x tsx src/server/main.ts",
"start": "cross-env NODE_ENV=production tsx src/server/main.ts",
"build": "vite build && cpx web.config dist/"
},
"dependencies": {
"cross-env": "^7.0.3",
"express": "^4.21.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vite-express": "^0.19.0"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"cpx": "^1.5.0",
"eslint": "^9.13.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.11.0",
"tsx": "^4.19.2",
"typescript": "~5.6.2",
"typescript-eslint": "^8.11.0",
"vite": "^5.4.10"
}
}
tsconfig.json:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"lib": ["DOM", "ESNext"],
"jsx": "react-jsx",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "dist",
"types": ["node"]
}
}
After changing main.ts
, I am successfully redirected to the /hello
endpoint.
Azure Web App Output: