@vitejs integration module for @expressjs
With Vite you can easily bootstrap your project and just start working without figuring everything out. That's great for front-end apps, but when you want to include server-side into the mix, things get quite complicated. Thanks to vite-express you can just as easily start writing full-stack app in seconds.
import express from "express";
import ViteExpress from "vite-express";
const app = express();
app.get("/message", (_, res) => res.send("Hello from express!"));
ViteExpress.listen(app, 3000, () => console.log("Server is listening..."));
You can also bind into the express app, to be able to do things such as specifying custom host address or creating your own server instance (e.g., when you want to use the https:
protocol).
import express from "express";
import ViteExpress from "vite-express";
const app = express();
const server = app.listen(3000, "0.0.0.0", () =>
console.log("Server is listening...")
);
ViteExpress.bind(app, server);
⚡ vite-express
takes care of
- spinning up Vite's Dev Server
- injecting necessary middlewares to static files from your API
- managing unhandled routes to make client-side routing possible
The only thing that is left to you is to code! 🎉
The easiest way to setup a Vite Express app is to use 🏗️ create-vite-express
package
-
Run the CLI from your terminal
yarn create vite-express
-
Follow the prompts to configure your project using your favourite framework.
-
Open app folder, install dependencies and run the app in development mode
cd YOUR_APP_NAME yarn yarn dev
-
Open your browser at
http://localhost:3000
-
Change the client code and see the beauty of HMR in action!
Congrats, you've just created your first vite-express
app! 🎉 Happy hacking!
Alternatively you can use create-vite
package to setup the client and then add an express server to it if your favourite framework isn't supported by create-vite-express
.
-
Start by creating Vite project
yarn create vite
-
Follow the prompts to configure your project using your favourite framework.
-
Install
express
andvite-express
packagesyarn add express vite-express
-
Create a server script inside project root directory
//e.g server.js import express from "express"; import ViteExpress from "vite-express"; const app = express(); app.get("/message", (_, res) => res.send("Hello from express!")); ViteExpress.listen(app, 3000, () => console.log("Server is listening..."));
⚠️ For some frameworks like React, Vite sets thepackage.json
type
field tomodule
so you need to use ESModulesimport
syntax despite writing a node script. If that's a problem you can freely change thetype
back tocommonjs
as Vite usesESModules
for front-end either way! -
Run the express script
node server.js
-
Open your browser at
http://localhost:3000
-
Change the client code and see the beauty of HMR in action!
Congrats, you've just created your first vite-express
app! 🎉 Happy hacking!
By default vite-express runs in development mode, when server acts as a simple proxy between client and Vite's Dev Server utilizing the power of HMR and native browser modules. This is not suitable for production as described here, so in production we want to serve static files that Vite spits out during it's build process. That's why you need to invoke vite build
command first. Then you need to run your app in production mode.
You have these options to achieve that
-
Run the code with
NODE_ENV=production
variable, either by inlining it with the commandNODE_ENV=production node server.ts
Or by using
dotenv
or other envs tool. -
Use
ViteExpress.config()
and setmode
toproduction
import express from "express"; import ViteExpress from "vite-express"; const app = express(); ViteExpress.config({ mode: "production" }) app.get("/message", (_, res) => res.send("Hello from express!")); ViteExpress.listen(app, 3000, () => console.log("Server is listening..."));
The way vite-express
works is quite simple. As soon as you invoke ViteExpress.listen
:
-
Static files serving middleware is injected at the end of express middlewares stack, but you can change that by using
ViteExpress.static
middleware to precisely describe at what point do you want to serve static files. This middleware takes care of serving static files from the Vite Dev Server indevelopment
mode and inproduction
modeexpress.static
is used instead. -
A GET routes handler
get("*")
is registered at the end of middleware stack to handle all the routes that were unhandled by you. We do this to ensure that client-side routing is possible. -
Lastly Vite Dev Server is started up, listening on port 5173 or the one that you pass into configuration.
Because ViteExpress.listen
is an async function, in most cases it doesn't matter when you invoke it, but it is generally the best to do it at the end of file to avoid get("*")
handler overriting your routes.
Used to pass in configuration object with each key optional.
ViteExpress.config({ /*...*/ });
name | description | default | valid values |
---|---|---|---|
mode | When set to development Vite Dev Server will be utilized, in production app will serve static files built with vite build command |
development |
development , production |
vitePort | Port that Vite Dev Server will be listening on | 5173 |
any number |
printViteDevServerHost | When set to true, Vite's dev server host (e.g. http://localhost:5173 ) will be printed to console. Should be used only for debug info |
false |
boolean |
Used to inject necessary middlewares into the app and start listening on defined port. Should replace app.listen()
in your base express application. Due to its async nature can be invoked at any time but should generally be invoked at the end to avoid interfering with other middlewares and route handlers.
app
- express application returned from invokingexpress()
port: number
- port that server will be listening oncallback?: () => void
- function that will be invoked after server starts listening
Returns the same http.Server
that is returned by express when running app.listen()
const app = express();
const httpServer = ViteExpress.listen(app, 3000, () => console.log("Server is listening!"));
Used to inject necessary middleware into the app, but does not start the listening process. Should be used when you want to create your own http
/https
server instance manually e.g. when you use socket.io
library. Same as listen
, can be invoked at any time because it is async, but it is advised to invoke it when you already registered all routes and middlewares, so that it can correctly hook into the express app.
app
- express application returned from invokingexpress()
server: http.Server | https.Server
- server instance that is returned when invokinghttp.createServer
callback?: () => void
- function that will be invoked after Vite dev server is started and vite-express injects all middleware
const app = express();
const server = http.createServer(app).listen(3000, () => {
console.log("Server is listening!")
});
ViteExpress.bind(app, server);
Used as a typical express middleware to indicate to vite-express
the exact moment when you want to register static serving logic. You can use this method to prevent some of your request blocking middleware, such as authentication/authorization, from blocking files coming from your server, which would make displaying for example login page impossible because of blocked html, styles and scripts files.
Example:
import express from "express"
import yourAuthMiddleware from "some/path"
const app = express()
app.use(ViteExpress.static())
app.use(yourAuthMiddleware())
app.get("/", ()=> /*...*/ )
ViteExpress.listen(app, 3000, () => console.log("Server is listening!"))
You should use it when the default behaviour of serving static files at the end of middleware chain doesn't work for you because you block requests in some way.
Used when you want to build the app to production programically. It is adviced to use vite build
command, but can be freely used in some edge scenarios (e.g. in some automation scripts) as it does the same thing.
ViteExpress.build();