vite-express
Advanced tools
Comparing version 0.9.2 to 0.10.0
@@ -9,5 +9,5 @@ /// <reference types="qs" /> | ||
type ViteConfig = { | ||
root?: string; | ||
base?: string; | ||
build?: { | ||
root: string; | ||
base: string; | ||
build: { | ||
outDir: string; | ||
@@ -18,3 +18,4 @@ }; | ||
mode: "production" | "development"; | ||
inlineViteConfig: ViteConfig | undefined; | ||
inlineViteConfig: Partial<ViteConfig> | undefined; | ||
ignorePaths: RegExp | ((path: string, req: express.Request) => boolean) | undefined; | ||
transformer: ((html: string, req: express.Request) => string) | undefined; | ||
@@ -21,0 +22,0 @@ }; |
104
dist/main.js
@@ -33,6 +33,14 @@ 'use strict'; | ||
const { NODE_ENV } = process.env; | ||
const _State = { | ||
viteConfig: undefined, | ||
}; | ||
function clearState() { | ||
_State.viteConfig = undefined; | ||
} | ||
const Config = { | ||
mode: (NODE_ENV === "production" ? "production" : "development"), | ||
mode: (process.env.NODE_ENV === "production" | ||
? "production" | ||
: "development"), | ||
inlineViteConfig: undefined, | ||
ignorePaths: undefined, | ||
transformer: undefined, | ||
@@ -50,18 +58,66 @@ }; | ||
} | ||
function isRunningViteless() { | ||
return Config.inlineViteConfig !== undefined; | ||
function getDefaultViteConfig() { | ||
return { | ||
root: process.cwd(), | ||
base: "/", | ||
build: { outDir: "dist" }, | ||
}; | ||
} | ||
function getViteConfigPath() { | ||
if (fs.existsSync("vite.config.js")) | ||
return "vite.config.js"; | ||
else if (fs.existsSync("vite.config.ts")) | ||
return "vite.config.ts"; | ||
throw new Error("Unable to locate Vite config"); | ||
} | ||
function resolveConfig() { | ||
var _a, _b, _c; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!Config.inlineViteConfig) { | ||
if (Config.inlineViteConfig) { | ||
info(`${pc.yellow("Inline config")} detected, ignoring ${pc.yellow("Vite config file")}`); | ||
return Object.assign(Object.assign({}, getDefaultViteConfig()), Config.inlineViteConfig); | ||
} | ||
try { | ||
const { resolveConfig } = yield import('vite'); | ||
return resolveConfig({}, "build"); | ||
try { | ||
const config = yield resolveConfig({}, "build"); | ||
info(`Using ${pc.yellow("Vite")} to resolve the ${pc.yellow("config file")}`); | ||
return config; | ||
} | ||
catch (e) { | ||
console.error(e); | ||
info(pc.red(`Unable to use ${pc.yellow("Vite")}, running in ${pc.yellow("viteless")} mode`)); | ||
} | ||
} | ||
const { root = process.cwd(), base = "/", build = { outDir: "dist" }, } = Config.inlineViteConfig; | ||
return { root, base, build }; | ||
catch (e) { | ||
} | ||
try { | ||
const config = fs.readFileSync(getViteConfigPath(), "utf8"); | ||
const root = (_a = config.match(/"?root"?\s*:\s*"([^"]+)"/)) === null || _a === void 0 ? void 0 : _a[1]; | ||
const base = (_b = config.match(/"?base"?\s*:\s*"([^"]+)"/)) === null || _b === void 0 ? void 0 : _b[1]; | ||
const outDir = (_c = config.match(/"?outDir"?\s*:\s*"([^"]+)"/)) === null || _c === void 0 ? void 0 : _c[1]; | ||
const defaultConfig = getDefaultViteConfig(); | ||
return { | ||
root: root !== null && root !== void 0 ? root : defaultConfig.root, | ||
base: base !== null && base !== void 0 ? base : defaultConfig.base, | ||
build: { outDir: outDir !== null && outDir !== void 0 ? outDir : defaultConfig.build.outDir }, | ||
}; | ||
} | ||
catch (e) { | ||
info(pc.red(`Unable to locate ${pc.yellow("vite.config.*s file")}, using default options`)); | ||
return getDefaultViteConfig(); | ||
} | ||
}); | ||
} | ||
function getViteConfig() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!_State.viteConfig) { | ||
_State.viteConfig = yield resolveConfig(); | ||
} | ||
return _State.viteConfig; | ||
}); | ||
} | ||
function getDistPath() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const config = yield resolveConfig(); | ||
const config = yield getViteConfig(); | ||
return path.resolve(config.root, config.build.outDir); | ||
@@ -86,5 +142,4 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const config = yield resolveConfig(); | ||
const base = config.base || "/"; | ||
app.use(base, middleware); | ||
const config = yield getViteConfig(); | ||
app.use(config.base, middleware); | ||
const stubMiddlewareLayer = app._router.stack.find((layer) => layer.handle === stubMiddleware); | ||
@@ -99,6 +154,15 @@ if (stubMiddlewareLayer !== undefined) { | ||
} | ||
function isIgnoredPath(path, req) { | ||
if (Config.ignorePaths === undefined) | ||
return false; | ||
return Config.ignorePaths instanceof RegExp | ||
? path.match(Config.ignorePaths) | ||
: Config.ignorePaths(path, req); | ||
} | ||
function injectViteIndexMiddleware(app, server) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const config = yield resolveConfig(); | ||
const config = yield getViteConfig(); | ||
app.get("/*", (req, res, next) => __awaiter(this, void 0, void 0, function* () { | ||
if (isIgnoredPath(req.path, req)) | ||
return next(); | ||
const template = fs.readFileSync(path.resolve(config.root, "index.html"), "utf8"); | ||
@@ -117,3 +181,5 @@ if (isStaticFilePath(req.path)) | ||
const distPath = yield getDistPath(); | ||
app.use("*", (req, res) => { | ||
app.use("*", (req, res, next) => { | ||
if (isIgnoredPath(req.baseUrl, req)) | ||
return next(); | ||
const html = fs.readFileSync(path.resolve(distPath, "index.html"), "utf-8"); | ||
@@ -127,4 +193,5 @@ res.send(getTransformedHTML(html, req)); | ||
const { createServer, mergeConfig } = yield import('vite'); | ||
const config = Config.inlineViteConfig ? yield resolveConfig() : {}; | ||
const vite = yield createServer(mergeConfig(config, { | ||
const config = yield getViteConfig(); | ||
const isUsingViteResolvedConfig = Object.entries(config).length > 3; | ||
const vite = yield createServer(mergeConfig(isUsingViteResolvedConfig ? {} : config, { | ||
clearScreen: false, | ||
@@ -141,2 +208,3 @@ appType: "custom", | ||
Config.mode = config.mode; | ||
Config.ignorePaths = config.ignorePaths; | ||
Config.inlineViteConfig = config.inlineViteConfig; | ||
@@ -148,2 +216,3 @@ Config.transformer = config.transformer; | ||
info(`Running in ${pc.yellow(Config.mode)} mode`); | ||
clearState(); | ||
if (Config.mode === "development") { | ||
@@ -155,5 +224,2 @@ const vite = yield startServer(server); | ||
else { | ||
if (isRunningViteless()) { | ||
info(`Custom inline config defined, running in ${pc.yellow("viteless")} mode`); | ||
} | ||
yield injectStaticMiddleware(app, yield serveStatic()); | ||
@@ -160,0 +226,0 @@ yield injectIndexMiddleware(app); |
{ | ||
"name": "vite-express", | ||
"version": "0.9.2", | ||
"version": "0.10.0", | ||
"main": "dist/main.js", | ||
@@ -26,6 +26,2 @@ "types": "dist/main.d.ts", | ||
}, | ||
"peerDependencies": { | ||
"express": "^4.18.2", | ||
"vite": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
@@ -32,0 +28,0 @@ "@rollup/plugin-terser": "^0.2.0", |
@@ -155,8 +155,7 @@ # ⚡ Vite + Express | ||
`vite-express` uses Vite even in production to resolve [`vite.config.js`][vite-config] correctly. If you want to be able to run your production app without Vite and all development dependencies, you need to specify custom inline config using `ViteExpress.config({ inlineViteConfig: ... })`. | ||
`vite-express` will always try to use `Vite` to resolve [`vite.config.*s`][vite-config] file. But in production environment it is very possible that it will not be installed. When `Vite` package cannot be used, `vite-express` falls back to reading the config file as a plain text file, trying to extract [`root`][root], [`base`][base] and [`outDir`][outDir] values. If you don't want to ship `vite.config` to production you can specify custom inline config using [`ViteExpress.config({ inlineViteConfig: ... })`](https://github.com/szymmis/vite-express/tree/feature/running-viteless#configoptions--void). Remember that when using inline config there are two sources of truth, so you need to make sure `vite.config` used by Vite, and inline config used by `vite-express` are synchronized. | ||
Valid configuration values used by `vite-express` are [`root`][root], [`base`][base] and [`outDir`][outDir]. | ||
Order of config file resolve process: | ||
- When `inlineViteConfig` is set to `undefined` (by default) Vite is used in production to resolve config file | ||
- To use viteless mode with the defaults you can set `inlineViteConfig` as `{}` | ||
1. When `inlineViteConfig` is set to some value it will be used as a configuration object, completely ignoring `vite.config` file. | ||
@@ -167,12 +166,2 @@ ```javascript | ||
ViteExpress.config({ inlineViteConfig: {} }) | ||
ViteExpress.listen(express(), 3000); | ||
``` | ||
- You can also specify any combination of valid parameters | ||
```javascript | ||
import express from "express"; | ||
import ViteExpress from "vite-express"; | ||
ViteExpress.config({ | ||
@@ -188,6 +177,14 @@ inlineViteConfig: { | ||
Be aware that in viteless mode you have two separate sources of truth - `vite.config.js` and your inline configuration, so you need to manually keep them in sync. | ||
You can specify any combination of those values, it will be merged with the default values to get resulting configuration object. | ||
Most of the time you are okay with using Vite in production as it's easier, this approach is only recommended if you want to reduce production dependencies. | ||
Default config values are: | ||
- `root = process.cwd()` | ||
- `base = /` | ||
- `outDir = dist` | ||
2. When `inlineViteConfig` is not defined, `vite-express` will try to use `Vite` to resolve the config. | ||
3. If the package is not present, `vite.config.*s` file will be loaded as a plain file and config values will be extracted using plain text manipulation methods. That's why `root`, `base` and `outDir` need to be defined as json valid values: strings. | ||
4. If config file cannot be used to extract the values, defaults defined above will be used. | ||
## 🤖 Transforming HTML | ||
@@ -279,7 +276,8 @@ | ||
| 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"` | | ||
| transformer | A function used to transform HTML served to the client, useful when you want to inject some metadata on the server. First argument is the HTML that is about to be sent to the client, second is the [`Request`][express-request] object. Needs to return transformed HTML as a string. | `undefined` | `undefined` \| `(html: string, req: Request) => string` | | ||
| inlineViteConfig | When set to non-undefined value, `vite-express` will be run in [`viteless mode`](#-viteless-mode) | `undefined` | `undefined` \| `ViteConfig` | | ||
| 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"` | | ||
| transformer | A function used to transform HTML served to the client, useful when you want to inject some metadata on the server. First argument is the HTML that is about to be sent to the client, second is the [`Request`][express-request] object. Needs to return transformed HTML as a string. | `undefined` | `undefined` \| `(html: string, req: Request) => string` | | ||
| ignorePaths | A regex or function used to determine if matched path/request should be ignored by Vite index.html serving logic. When defined as a function, the request will be ignored when function returns true. Example of usage: Can be used to disable Vite on `/api` paths. | `undefined` | `undefined` \| `RegExp` \| `(path: string, req: Request) => bool` | | ||
| inlineViteConfig | When set to non-undefined value, `vite-express` will be run in [`viteless mode`](#-viteless-mode) | `undefined` | `undefined` \| `ViteConfig` | | ||
@@ -286,0 +284,0 @@ ```typescript |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
31327
1
262
358