2

I've implemented an express server that uses express.static to serve the build folder created from a static docusaurus site in order to apply basic authentication to access the site. This is working great locally, but I'm running into troubles when deploying to Vercel.

Currently my configuration is allowing the deployed version on vercel to render the basic auth login page, but upon successful login I am directed to a page the states: "Cannot GET /"

I belive this is likely an issue with either my vercel.json configuration, or with my vercel's template settings.

My code is as follows:

index.mjs

import express from 'express';
import dotenv from 'dotenv';

dotenv.config();

const app = express();

app.use(express.json());

const authorize = ((req, res, next) => {

    const auth = {login: process.env.USERNAME, password: process.env.PASSWORD}

  
    const b64auth = (req.headers.authorization || '').split(' ')[1] || ''
    const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':')
  
    
    if (login && password && login === auth.login && password === auth.password) {
     
      return next()
    }
  
    res.set('WWW-Authenticate', 'Basic realm="401"') 
    res.status(401).send('Authentication required.') 
});

app.use('/', authorize);
app.use('/', express.static('build'));

app.listen(3000);
console.log(` Server ready at http://localhost:3000`);

vercel.json

{
  "version": 2,
  "builds": [{
    "src": "./index.mjs",
    "use": "@vercel/node"
  }],
  "routes": [{"handle": "filesystem"},
    {
      "src": "/.*",
      "dest": "/"
    }
  ]
  

}

package.json - start script

"start": "node --experimental-modules index.mjs",

And my vercel template is set to other, with the start script set to npm start.

Any ideas would be greatly appreciated!

4 Answers4

1

I had similar issue: serve some static content and use /api routes. All worked fine in local dev but throwed "Cannot GET/" in vercel.

My solution.

  • Build separately serverless and static content.
  • Route adjustements for /api calls and static content.

My final vercel.json:

{
    "version": 2,
    "builds": [
        {
            "src": "server.js",
            "use": "@vercel/node"
        },
        {
            "src": "public/**",
            "use": "@vercel/static"
        }
    ],
    "routes":[
        {
            "src": "/api/(.*)",
            "dest": "server.js"
        },
        {
            "src": "/",
            "dest": "public/index.html"
        },
        {
            "src": "/(.+)",
            "dest": "public/$1"
        }
    ]
}

Notes

  1. All static content is under /public (html,css,img,js,etc)
  2. server.js is the main app: express and route definitions. Similar to yours.
  3. vercel build log shows:
Generated build outputs:    
12:28:55.974     - Static files: 12
12:28:55.974     - Serverless Functions: 1
12:28:55.975     - Edge Functions: 0
...
12:28:58.142    Done with "server.js"

Maybe from this point you can find a solution for your case.

Rodrigo M
  • 11
  • 2
0

Ok, I've been looking for a solution for this one a little, and turns out we have to serve index.html explicitly in express:

app.get('/', (req: Request, res: Response) => {
  res.sendFile('index.html', {root: path.join(__dirname, 'public')});
});

given that you probably have index.html in public folder. That's what solved the issue for me.

sudo-sein
  • 11
  • 1
0

For anyone who struggles with seeing docusaurus load despite following the answer above, make sure to add the docs/build folder to your Git repository so that it gets deployed to Vercel. You can do this by adding the following line to your .gitignore file:

!docs/build/

This will ignore all files and folders in the docs folder except for the docs/build folder.

Ashtrix
  • 147
  • 1
  • 1
  • 11
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 17 '23 at 20:49
0

In my case, I needed to use the same base URL to load both the page request and the assets that are included in each page.

Requests:

GET: mywebsite.com/customer/favorites
  \- GET: mywebsite.com/assets/images/logo.svg
  \- GET: mywebsite.com/assets/css/bootstrap.min.css
  \- GET: mywebsite.com/modules/shared/web-components/item-list.js

Files structure:

public
 \- assets
    \- images
    \- css
 \- modules
    \- admin
    \- customer
    \- shared
server.js
package.json

So, I wrote a vercel.json file that takes all the request URLs without file extensions and pass them to the server.js file, while the request URLs that have a file extension (like .css, .js, .img) are taken as static calls to the public directory

{
  "name": "express-static-website",
  "version": 2,
  "public": true,
  "builds": [
    {
      "src": "server.js",
      "use": "@vercel/node"
    },
    {
      "src": "public/**",
      "use": "@vercel/static"
    }
  ],
  "routes": [
    {
      "src": "/((?!.*\\.\\w+$).*)",
      "dest": "/server.js"
    },
    {
      "src": "/(.+\\.[a-z]+)$",
      "dest": "/public/$1"
    }
  ]
}
Chemah
  • 538
  • 6
  • 18