From 98bdd143de707ba7a480147aee9bcad9b826aae3 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Fri, 12 Jan 2024 15:55:03 +0500 Subject: [PATCH 1/8] Remove staticFilePath check Removing staticFilePath check, as vite.middlewares are now mounted before the injectViteIndexMiddleware function. This adjustment is made because the staticFilePath check doesn't provide any additional benefits, aside from blocking requests like /index.html on the development server. --- src/main.ts | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main.ts b/src/main.ts index 92360d8..93b90e2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -47,10 +47,6 @@ function info(msg: string) { ); } -function isStaticFilePath(path: string) { - return path.match(/(\.\w+$)|@vite|@id|@react-refresh/); -} - async function getTransformedHTML(html: string, req: express.Request) { return Config.transformer ? Config.transformer(html, req) : html; } @@ -226,22 +222,19 @@ async function injectViteIndexMiddleware( if (isIgnoredPath(req.path, req)) return next(); - if (isStaticFilePath(req.path)) next(); - else { - const indexPath = findClosestIndexToRoot(req.path, config.root); - if (indexPath === undefined) return next(); - - const template = fs.readFileSync(indexPath, "utf8"); - let html = await server.transformIndexHtml(req.originalUrl, template); - - try { - html = await getTransformedHTML(html, req); - res.send(html); - } catch (e) { - console.error(e); - res.status(500); - return next(); - } + const indexPath = findClosestIndexToRoot(req.path, config.root); + if (indexPath === undefined) return next(); + + const template = fs.readFileSync(indexPath, "utf8"); + let html = await server.transformIndexHtml(req.originalUrl, template); + + try { + html = await getTransformedHTML(html, req); + res.send(html); + } catch (e) { + console.error(e); + res.status(500); + return next(); } }); } From 961f47bfc79e9fc54cba58b1c0311963df31aff8 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sat, 13 Jan 2024 00:20:13 +0500 Subject: [PATCH 2/8] Serve */index.html using IndexMiddlewares Allowing requests for html files to be transformable. This is achieved by skipping files with .htm or .html in the Static Middleware, allowing them to be handled by the IndexMiddlewares. --- src/main.ts | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/main.ts b/src/main.ts index 93b90e2..8432db0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -172,7 +172,10 @@ async function injectStaticMiddleware( middleware: RequestHandler, ) { const config = await getViteConfig(); - app.use(config.base, middleware); + + app.use(config.base, (req, res, next) => + req.path.match(/(\.html?|\/)$/) ? next() : middleware(req, res, next), + ); const stubMiddlewareLayer = app._router.stack.find( (layer: { handle?: RequestHandler }) => layer.handle === stubMiddleware, @@ -194,6 +197,15 @@ function isIgnoredPath(path: string, req: express.Request) { : Config.ignorePaths(path, req); } +function getFullPathIfFileExist( + reqPath: string, + root: string, +): string | undefined { + const pathToTest = path.join(root, reqPath); + if (fs.existsSync(pathToTest)) return pathToTest; + return undefined; +} + function findClosestIndexToRoot( reqPath: string, root: string, @@ -203,14 +215,16 @@ function findClosestIndexToRoot( while (dirs.length > 0) { const pathToTest = path.join(root, ...dirs, "index.html"); - if (fs.existsSync(pathToTest)) { - return pathToTest; - } + if (fs.existsSync(pathToTest)) return pathToTest; dirs.pop(); } return undefined; } +function isHTMLFilePath(path: string) { + return path.match(/\.html?$/); +} + async function injectViteIndexMiddleware( app: core.Express, server: ViteDevServer, @@ -222,7 +236,10 @@ async function injectViteIndexMiddleware( if (isIgnoredPath(req.path, req)) return next(); - const indexPath = findClosestIndexToRoot(req.path, config.root); + const indexPath = ( + isHTMLFilePath(req.path) ? getFullPathIfFileExist : findClosestIndexToRoot + )(req.path, config.root); + if (indexPath === undefined) return next(); const template = fs.readFileSync(indexPath, "utf8"); @@ -246,7 +263,10 @@ async function injectIndexMiddleware(app: core.Express) { app.use(config.base, async (req, res, next) => { if (isIgnoredPath(req.path, req)) return next(); - const indexPath = findClosestIndexToRoot(req.path, distPath); + const indexPath = ( + isHTMLFilePath(req.path) ? getFullPathIfFileExist : findClosestIndexToRoot + )(req.path, distPath); + if (indexPath === undefined) return next(); let html = fs.readFileSync(indexPath, "utf8"); From 5d7d157003f440e9a8deec91fa7ab054b663ea13 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sat, 13 Jan 2024 00:55:00 +0500 Subject: [PATCH 3/8] Correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73c401c..da7101c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Contributors: [@elturpin](https://github.com/elturpin), [@patreeceeo](https://gi ## 0.11.1 (2023-11-17) -- Mount middlewares that serve HTML at `config.root` instead of `/` ([#91](https://github.com/szymmis/vite-express/pull/91)) +- Mount middlewares that serve HTML at `config.base` instead of `/` ([#91](https://github.com/szymmis/vite-express/pull/91)) Contributors: [@rmhaiderali](https://github.com/rmhaiderali) From b927beb18ec885243148156a679e19bd0be2f152 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sat, 13 Jan 2024 22:48:04 +0500 Subject: [PATCH 4/8] Return closest index file if no html file found Previously, my implementation involved checking if a file ended with the html extension and then verifying its existence. If the file didn't exist, it would trigger next(), eventually resulting in a 404 error. However, I now realize that this approach does not align with the current methodology. The updated approach is to return the closest index file if the requested file does not exist. --- src/main.ts | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/main.ts b/src/main.ts index 8432db0..d678f58 100644 --- a/src/main.ts +++ b/src/main.ts @@ -197,15 +197,6 @@ function isIgnoredPath(path: string, req: express.Request) { : Config.ignorePaths(path, req); } -function getFullPathIfFileExist( - reqPath: string, - root: string, -): string | undefined { - const pathToTest = path.join(root, reqPath); - if (fs.existsSync(pathToTest)) return pathToTest; - return undefined; -} - function findClosestIndexToRoot( reqPath: string, root: string, @@ -218,11 +209,17 @@ function findClosestIndexToRoot( if (fs.existsSync(pathToTest)) return pathToTest; dirs.pop(); } + return undefined; } -function isHTMLFilePath(path: string) { - return path.match(/\.html?$/); +function findFilePath(reqPath: string, root: string): string | undefined { + if (reqPath.match(/\.html?$/)) { + const pathToTest = path.join(root, reqPath); + if (fs.existsSync(pathToTest)) return pathToTest; + } + + return findClosestIndexToRoot(reqPath, root); } async function injectViteIndexMiddleware( @@ -236,10 +233,7 @@ async function injectViteIndexMiddleware( if (isIgnoredPath(req.path, req)) return next(); - const indexPath = ( - isHTMLFilePath(req.path) ? getFullPathIfFileExist : findClosestIndexToRoot - )(req.path, config.root); - + const indexPath = findFilePath(req.path, config.root); if (indexPath === undefined) return next(); const template = fs.readFileSync(indexPath, "utf8"); @@ -263,10 +257,7 @@ async function injectIndexMiddleware(app: core.Express) { app.use(config.base, async (req, res, next) => { if (isIgnoredPath(req.path, req)) return next(); - const indexPath = ( - isHTMLFilePath(req.path) ? getFullPathIfFileExist : findClosestIndexToRoot - )(req.path, distPath); - + const indexPath = findFilePath(req.path, distPath); if (indexPath === undefined) return next(); let html = fs.readFileSync(indexPath, "utf8"); From 7574fda8bfa1de771611016056b2b0db0a4c6fd0 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sat, 13 Jan 2024 23:10:05 +0500 Subject: [PATCH 5/8] Adding Tests These tests will ensure serving and transformation of .html and .htm files when request explicitly includes filenames. --- tests/env/dist/main.htm | 12 ++++++++++++ tests/env/main.htm | 12 ++++++++++++ tests/server.test.ts | 8 ++++++++ 3 files changed, 32 insertions(+) create mode 100644 tests/env/dist/main.htm create mode 100644 tests/env/main.htm diff --git a/tests/env/dist/main.htm b/tests/env/dist/main.htm new file mode 100644 index 0000000..e6bce70 --- /dev/null +++ b/tests/env/dist/main.htm @@ -0,0 +1,12 @@ + + + + + + + Document + + +

main

+ + diff --git a/tests/env/main.htm b/tests/env/main.htm new file mode 100644 index 0000000..e6bce70 --- /dev/null +++ b/tests/env/main.htm @@ -0,0 +1,12 @@ + + + + + + + Document + + +

main

+ + diff --git a/tests/server.test.ts b/tests/server.test.ts index ea0522a..725ea01 100644 --- a/tests/server.test.ts +++ b/tests/server.test.ts @@ -32,6 +32,10 @@ test("Express app", async (done) => { expect(response.text).toMatch(/

index<\/h1>/); response = await request(app).get("/route"); expect(response.text).toMatch(/

index<\/h1>/); + response = await request(app).get("/index.html"); + expect(response.text).toMatch(/

index<\/h1>/); + response = await request(app).get("/main.htm"); + expect(response.text).toMatch(/

main<\/h1>/); it("html is served correctly"); @@ -247,6 +251,10 @@ test("Express app with transformer function", async (done) => { it("html is served correctly"); + expect(response.text).toMatch(//); + response = await request(app).get("/index.html"); + expect(response.text).toMatch(//); + response = await request(app).get("/main.htm"); expect(response.text).toMatch(//); it("html is transformed correctly"); From 4abfecb7551d1812b574d2c81455bd59476a7173 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sun, 14 Jan 2024 00:52:48 +0500 Subject: [PATCH 6/8] Use only .html files --- src/main.ts | 6 +++--- tests/env/dist/{main.htm => main.html} | 0 tests/env/{main.htm => main.html} | 0 tests/server.test.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename tests/env/dist/{main.htm => main.html} (100%) rename tests/env/{main.htm => main.html} (100%) diff --git a/src/main.ts b/src/main.ts index d678f58..aa23411 100644 --- a/src/main.ts +++ b/src/main.ts @@ -174,7 +174,7 @@ async function injectStaticMiddleware( const config = await getViteConfig(); app.use(config.base, (req, res, next) => - req.path.match(/(\.html?|\/)$/) ? next() : middleware(req, res, next), + req.path.match(/(\.html|\/)$/) ? next() : middleware(req, res, next), ); const stubMiddlewareLayer = app._router.stack.find( @@ -214,11 +214,11 @@ function findClosestIndexToRoot( } function findFilePath(reqPath: string, root: string): string | undefined { - if (reqPath.match(/\.html?$/)) { + if (reqPath.match(/\.html$/)) { const pathToTest = path.join(root, reqPath); if (fs.existsSync(pathToTest)) return pathToTest; } - + return findClosestIndexToRoot(reqPath, root); } diff --git a/tests/env/dist/main.htm b/tests/env/dist/main.html similarity index 100% rename from tests/env/dist/main.htm rename to tests/env/dist/main.html diff --git a/tests/env/main.htm b/tests/env/main.html similarity index 100% rename from tests/env/main.htm rename to tests/env/main.html diff --git a/tests/server.test.ts b/tests/server.test.ts index 725ea01..76a1477 100644 --- a/tests/server.test.ts +++ b/tests/server.test.ts @@ -34,7 +34,7 @@ test("Express app", async (done) => { expect(response.text).toMatch(/

index<\/h1>/); response = await request(app).get("/index.html"); expect(response.text).toMatch(/

index<\/h1>/); - response = await request(app).get("/main.htm"); + response = await request(app).get("/main.html"); expect(response.text).toMatch(/

main<\/h1>/); it("html is served correctly"); @@ -254,7 +254,7 @@ test("Express app with transformer function", async (done) => { expect(response.text).toMatch(//); response = await request(app).get("/index.html"); expect(response.text).toMatch(//); - response = await request(app).get("/main.htm"); + response = await request(app).get("/main.html"); expect(response.text).toMatch(//); it("html is transformed correctly"); From 2fff4e0bc4e0c33b4acc40f1b625d08a4d1dd20a Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Wed, 17 Jan 2024 21:54:14 +0500 Subject: [PATCH 7/8] Using endsWith instead of match --- src/main.ts | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main.ts b/src/main.ts index aa23411..d3ffacd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -104,9 +104,7 @@ async function resolveConfig(): Promise { ), ); } - } catch (e) { - 1; - } + } catch (e) {} try { const config = fs.readFileSync(getViteConfigPath(), "utf8"); @@ -174,7 +172,7 @@ async function injectStaticMiddleware( const config = await getViteConfig(); app.use(config.base, (req, res, next) => - req.path.match(/(\.html|\/)$/) ? next() : middleware(req, res, next), + req.path.endsWith(".html") ? next() : middleware(req, res, next), ); const stubMiddlewareLayer = app._router.stack.find( @@ -197,10 +195,13 @@ function isIgnoredPath(path: string, req: express.Request) { : Config.ignorePaths(path, req); } -function findClosestIndexToRoot( - reqPath: string, - root: string, -): string | undefined { +function findFilePath(reqPath: string, root: string): string | undefined { + if (reqPath.endsWith(".html")) { + const pathToTest = path.join(root, reqPath); + if (fs.existsSync(pathToTest)) return pathToTest; + } + + // find closest index to root const basePath = reqPath.slice(0, reqPath.lastIndexOf("/")); const dirs = basePath.split("/"); @@ -213,15 +214,6 @@ function findClosestIndexToRoot( return undefined; } -function findFilePath(reqPath: string, root: string): string | undefined { - if (reqPath.match(/\.html$/)) { - const pathToTest = path.join(root, reqPath); - if (fs.existsSync(pathToTest)) return pathToTest; - } - - return findClosestIndexToRoot(reqPath, root); -} - async function injectViteIndexMiddleware( app: core.Express, server: ViteDevServer, From d0765c9306d7159ce481c25b0465e87b670beaa8 Mon Sep 17 00:00:00 2001 From: Haider Ali Date: Sun, 21 Jan 2024 17:49:54 +0500 Subject: [PATCH 8/8] Using meaningful variable/function names --- src/main.ts | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/main.ts b/src/main.ts index d3ffacd..ec08ec3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -195,13 +195,16 @@ function isIgnoredPath(path: string, req: express.Request) { : Config.ignorePaths(path, req); } -function findFilePath(reqPath: string, root: string): string | undefined { +function findTemplateFilePath( + reqPath: string, + root: string, +): string | undefined { if (reqPath.endsWith(".html")) { const pathToTest = path.join(root, reqPath); if (fs.existsSync(pathToTest)) return pathToTest; } - // find closest index to root + // find closest index.html to provided path const basePath = reqPath.slice(0, reqPath.lastIndexOf("/")); const dirs = basePath.split("/"); @@ -214,7 +217,7 @@ function findFilePath(reqPath: string, root: string): string | undefined { return undefined; } -async function injectViteIndexMiddleware( +async function injectViteHTMLMiddleware( app: core.Express, server: ViteDevServer, ) { @@ -225,10 +228,10 @@ async function injectViteIndexMiddleware( if (isIgnoredPath(req.path, req)) return next(); - const indexPath = findFilePath(req.path, config.root); - if (indexPath === undefined) return next(); + const templateFilePath = findTemplateFilePath(req.path, config.root); + if (templateFilePath === undefined) return next(); - const template = fs.readFileSync(indexPath, "utf8"); + const template = fs.readFileSync(templateFilePath, "utf8"); let html = await server.transformIndexHtml(req.originalUrl, template); try { @@ -242,17 +245,17 @@ async function injectViteIndexMiddleware( }); } -async function injectIndexMiddleware(app: core.Express) { +async function injectHTMLMiddleware(app: core.Express) { const distPath = await getDistPath(); const config = await getViteConfig(); app.use(config.base, async (req, res, next) => { if (isIgnoredPath(req.path, req)) return next(); - const indexPath = findFilePath(req.path, distPath); - if (indexPath === undefined) return next(); + const templateFilePath = findTemplateFilePath(req.path, distPath); + if (templateFilePath === undefined) return next(); - let html = fs.readFileSync(indexPath, "utf8"); + let html = fs.readFileSync(templateFilePath, "utf8"); try { html = await getTransformedHTML(html, req); @@ -311,10 +314,10 @@ async function bind( if (Config.mode === "development") { const vite = await startServer(server); await injectStaticMiddleware(app, vite.middlewares); - await injectViteIndexMiddleware(app, vite); + await injectViteHTMLMiddleware(app, vite); } else { await injectStaticMiddleware(app, await serveStatic()); - await injectIndexMiddleware(app); + await injectHTMLMiddleware(app); } callback?.();