Skip to content

Commit

Permalink
feat(cli): create plugin for serving index.html from external public …
Browse files Browse the repository at this point in the history
…directory (#2449)

Create a plugin `externalPublicPlugin` to fix the issue with serving the `index.html` file from the specified external public directory. Vite mode `spa` will not serve the `index.html` file from the specified external public directory.

- Enhanced the middleware to intercept requests and serve the `index.html` file from the specified external public directory.
- Transformed the HTML using Vite's `transformIndexHtml` method.
- Applied appropriate content headers and additional configured headers before sending the response.
  • Loading branch information
odinr committed Sep 16, 2024
1 parent 8fbdf00 commit 8cb1d2a
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .changeset/hot-ears-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
'@equinor/fusion-framework-cli': minor
---

**@equinor/fusion-framework-cli:**

Create a plugin `externalPublicPlugin` to fix the issue with serving the `index.html` file from the specified external public directory. Vite mode `spa` will not serve the `index.html` file from the specified external public directory.

- Enhanced the middleware to intercept requests and serve the `index.html` file from the specified external public directory.
- Transformed the HTML using Vite's `transformIndexHtml` method.
- Applied appropriate content headers and additional configured headers before sending the response.

```typescript
const viteConfig = {
roo
plugins: [
// path wich contains the index.html file
externalPublicPlugin('./my-portal'),
],
};

const viteConfig = defineConfig({
// vite configuration
root: './src', // this where vite will look for the index.html file
plugins: [
// path which contains the index.html file
externalPublicPlugin('./my-portal'),
],
});
```
71 changes: 71 additions & 0 deletions packages/cli/src/bin/plugins/external-public.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { join } from 'node:path';
import { readFileSync } from 'node:fs';

import { type Plugin } from 'vite';

/**
* Creates a plugin that serves an external public directory.
*
* This plugin is useful when you want to serve a static site from a different directory than the one where the Vite server is running.
* Vite`s built in `mode: 'spa'` will only look for the `index.html` file in the configured `root` directory,
* so this plugin is necessary to serve the `index.html` file from a different directory.
*
* @param path - The path to the external public directory.
* @returns A Plugin object configured to serve the specified public directory.
*
* The plugin:
* - Sets the `publicDir` configuration to the provided path.
* - Adds a middleware to the server that serves the `index.html` file from the specified path.
*
* The middleware:
* - Reads the `index.html` file from the specified path.
* - Transforms the HTML using the server's `transformIndexHtml` method.
* - Responds with the transformed HTML, setting appropriate headers.
*/
export const externalPublicPlugin = (path: string): Plugin => {
return {
name: 'fusion:external-public',
apply: 'serve',
config(config) {
config.publicDir = path;
},
configureServer(server) {
// intercept requests to serve the index.html file
server.middlewares.use(async (req, res, next) => {
if (
// Only accept GET or HEAD
(req.method !== 'GET' && req.method !== 'HEAD') ||
// Only accept text/html
!req.headers.accept?.includes('text/html')
) {
return next();
}
try {
// load the raw html from provided path
const htmlRaw = readFileSync(join(path, 'index.html'), 'utf-8');
// transform the html, this is where vite plugin hooks are applied
const html = await server.transformIndexHtml(
req.url!,
htmlRaw,
req.originalUrl,
);

// apply content headers and configured additional headers
res.writeHead(200, {
'content-type': 'text/html',
'content-length': Buffer.byteLength(html),
'cache-control': 'no-cache',
...server.config.server.headers,
});

// send the transformed html and end the response
res.end(html);
} catch (e) {
next(e);
}
});
},
};
};

export default externalPublicPlugin;

0 comments on commit 8cb1d2a

Please sign in to comment.