Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to deploy it on Vercel #4

Closed
bitcoinvsalts opened this issue Aug 5, 2024 · 9 comments
Closed

How to deploy it on Vercel #4

bitcoinvsalts opened this issue Aug 5, 2024 · 9 comments

Comments

@bitcoinvsalts
Copy link

@nitedani any idea on how to deploy express-react example on vercel?

@nitedani
Copy link
Member

nitedani commented Aug 5, 2024

I never tried vercel before. I'll try to make it work and create a new example.

@bitcoinvsalts
Copy link
Author

@nitedani thank you for your reply. What do you use to deploy it? Netlify?

@nitedani
Copy link
Member

nitedani commented Aug 6, 2024

https:/vikejs/vike-node/tree/main/examples/express-react-vercel

  • vike-node now doesn't automatically serve static assets when running on vercel, and lets vercel handle it (vercel.json > outputDirectory setting)
  • this example is still deployable to any VPS by running npm run build and npm run prod, not only vercel

The steps to add vercel support were:

  1. export the express instance from server/index.js
  2. create api/index.js, import the express instance here, and re-export it as a web request handler(because web request handlers support response streaming on vercel)
    The express instance is imported from the already built server entry file, so vite features like import.meta.env can be used in server/index.js. But I think this is a workaround and it can be improved.
  3. create vercel.json

@bitcoinvsalts
Copy link
Author

@nitedani Thank you so much. I appreciate your quick reply and help.

Let me add my user auth logic to the server and see if it works fine with the Vike frontend.

@bitcoinvsalts
Copy link
Author

@nitedani I am trying to pass the user auth info to the PageContext. Here is my code:

import express from 'express'
import vike from 'vike-node/connect'
import cookieParser from 'cookie-parser'

const { auth } = require('express-openid-connect');

export default startServer()

function autho(app) {
  const config = {
    authRequired: false,
    auth0Logout: true,
    issuerBaseURL: 'https://dev-xxnyc.us.auth0.com',
    clientID: 'HHxxxxxO',
    secret: 'Kp6xxxxxxxS2',
    baseURL: 'https://viked.vercel.app/'
  };
  app.use(cookieParser())
  app.use(express.json()) // Parse & make HTTP request body available at `req.body`
  app.use(
    auth(config)
  );
  app.use(function (req, res, next) {
    req.user = req.oidc.user;
    next();
  });
}

function startServer() {
  const app = express()
  autho(app)
  app.use(vike())
  const port = process.env.PORT || 3000
  app.listen(port, () => console.log(`Server running at http://localhost:${port}`))
  return app
}

But the user info is not yet passed to the PageContext. Any idea how to do this?

Here is a code that works but I cannot find a way to deploy it to Vercel:

import express from 'express'
import { renderPage } from 'vike/server'
import { root } from './root.js'
import cookieParser from 'cookie-parser'
import { getUser, checkCredentials } from './users.js'
const { auth } = require('express-openid-connect');

const isProduction = process.env.NODE_ENV === 'production'
const port = process.env.PORT || 3000

startServer()

async function startServer() {
  const app = express()
  autho(app)
  await assets(app)
  vike(app)
  app.listen(port)
  console.log(`Server running at http://localhost:${port}`)
}

function autho(app) {
  const config = {
    authRequired: false,
    auth0Logout: true,
    issuerBaseURL: 'https://dev-0xxxnyc.us.auth0.com',
    clientID: 'HHxxxxO',
    secret: 'Kp6xxxxxS2',
    baseURL: 'https://directbooking.netlify.app/'
  };
  app.use(cookieParser())
  app.use(express.json()) // Parse & make HTTP request body available at `req.body`
  app.use(
    auth(config)
  );
  app.use(function (req, res, next) {
    req.user = req.oidc.user;
    next();
  });
}

async function assets(app) {
  if (isProduction) {
    app.use(express.static(`${root}/dist/client`))
  } else {
    const vite = await import('vite')
    const viteDevMiddleware = (
      await vite.createServer({
        root,
        server: { middlewareMode: true }
      })
    ).middlewares
    app.use(viteDevMiddleware)
  }
}

function vike(app) {
  app.get('*', async (req, res, next) => {
    console.log("--=====--")
    const pageContextInit = {
      urlOriginal: req.originalUrl,
      headersOriginal: req.headers,
      user: req.user,
      userFullName: req.user?.fullName
    }
    const pageContext = await renderPage(pageContextInit)
    const { httpResponse } = pageContext
    if (!httpResponse) {
      return next()
    } else {
      const { statusCode, headers, earlyHints } = httpResponse
      if (res.writeEarlyHints) res.writeEarlyHints({ link: earlyHints.map((e) => e.earlyHintLink) })
      headers.forEach(([name, value]) => res.setHeader(name, value))
      res.status(statusCode)
      httpResponse.pipe(res)
    }
  })
}

@phonzammi
Copy link
Member

@bitcoinvsalts Have you try this custom-pagecontext ?

@bitcoinvsalts
Copy link
Author

I found the solution to my deployment issue!

If I use prerender: true in the vite config file like this, it wont process the destination API correctly while using auth

plugins: [
vike({
prerender: true,
}),
//mdx(),
react()
],
It works fine if I set prerender to false.

Big thanks to @nitedani for your help.

@brillout
Copy link
Member

brillout commented Aug 8, 2024

I'm glad you managed to achieve what you want. Btw. would your company be up for sponsoring (vikejs/vike#1350)?

@bitcoinvsalts
Copy link
Author

@brillout sorry I don't have a company, I am looking for a job as a Full Stack dev if anyone is looking for one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants