autobrr/web/vite.config.ts
KaiserBh 4432dfb099
feat(http): implement proper BaseUrl support to coexist with legacy mode (#1298)
* refactor: remove baseUrl from api calls and sseBaseUrl

* refactor: set cookie session to '/'.

Since that's where the api endpoint is that way we set it to the root domain, we can't set it to the subfolder since the api is called directly now and not using the baseUrl.

* feat: add the baseUrl route.

When user for example is in `/autobrr` and hit reload it should just return the index.html.

* refactor: now it have to be `/autobrr`

Remove the trailing `/`, now base url is set to /autobrr aligned with other arrs.

* refactor: remove baseUrl stuff.

* refactor: use separate router for the api endpoint and the baseUrl.

I don't think we need separate router, but I didn't test it, so feel free to test it and see if it works without the separate router, the whole point was to make sure that it's not prefixed with baseUrl and I noticed that it was being called in the frontend `APIClients.ts`. So yea just check if it works without it then keep the old one.

Also removed the index since it was zombie code not being used anywhere.

* feat: Dynamic base url.

* fix: auth handler deps

* feat(http): mount web and api on baseurl

* feat(http): web api client routes

* feat(http): baseurl legacy mode

* feat(http): baseurl legacy mode test

* feat(http): add assetBaseUrl

* feat(http): try separate web handlers

* feat(http): improve file serving

* feat(http): ignore .gitkeep

* fix(assets): windows paths

* fix(assets): windows paths trimprefix

* fix(assets): windows paths join

* fix(assets): cleanup

* fix(assets): additional web route check

* feat(http): add comments

---------

Co-authored-by: ze0s <ze0s@riseup.net>
2024-12-19 12:56:04 +01:00

168 lines
5.5 KiB
TypeScript

import { fileURLToPath, URL } from "node:url";
import { defineConfig, loadEnv, ConfigEnv } from "vite";
import { VitePWA } from "vite-plugin-pwa";
import react from "@vitejs/plugin-react-swc";
import svgr from "vite-plugin-svgr";
import path from "node:path";
import fs from "node:fs";
interface PreRenderedAsset {
name: string | undefined;
source: string | Uint8Array;
type: 'asset';
}
// https://vitejs.dev/config/
export default ({ mode }: ConfigEnv) => {
// early load .env file
// import.meta.env.VITE_NAME available here with: process.env.VITE_NAME
process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
return defineConfig({
// __BASE_URL__: "{{.BaseUrl}}",
base: "",
plugins: [react(), svgr(), VitePWA({
injectRegister: null,
selfDestroying: true,
scope: "{{.BaseUrl}}",
// strategies: "injectManifest",
useCredentials: true,
includeAssets: [
// looks inside "public" folder
// manifest's icons are automatic added
"favicon.ico"
],
manifest: {
name: "autobrr",
short_name: "autobrr",
description: "Automation for downloads.",
theme_color: "#141415",
background_color: "#141415",
icons: [
{
src: "logo192.png",
sizes: "192x192",
type: "image/png"
},
{
src: "apple-touch-icon-iphone-60x60.png",
sizes: "60x60",
type: "image/png"
},
{
src: "apple-touch-icon-ipad-76x76.png",
sizes: "76x76",
type: "image/png"
},
{
src: "apple-touch-icon-iphone-retina-120x120.png",
sizes: "120x120",
type: "image/png"
},
{
src: "apple-touch-icon-ipad-retina-152x152.png",
sizes: "152x152",
type: "image/png"
}
],
start_url: "{{.BaseUrl}}",
scope: "{{.BaseUrl}}",
display: "standalone"
},
workbox: {
// looks inside "dist" folder
globPatterns: ["**/*.{js,css,html,svg,woff2}"],
sourcemap: true,
navigateFallbackDenylist: [/^\/api/]
}
}),
{
name: "html-transformer-plugin",
enforce: "post",
apply: "build",
async closeBundle() {
const outputDir = 'dist'; // Adjust this if your `build.outDir` is different
const htmlPath = path.resolve(outputDir, 'index.html');
// Check if the file exists
if (!fs.existsSync(htmlPath)) {
console.error(`Could not find ${htmlPath}. Make sure the output directory matches.`);
return;
}
// Read the `index.html` content
let html = fs.readFileSync(htmlPath, 'utf-8');
// Perform your transformations here
// the experimental renderBuiltUrl works except for the style font url where it escapes the curly braces
// we look for those and replace with the non escaped curly braces to be able to correctly replace baseurl.
html = html.replace('%7B%7B.AssetBaseUrl%7D%7D/', '{{.AssetBaseUrl}}'); // Example: Replace `{{.BaseUrl}}`
// Write the updated `index.html` back
fs.writeFileSync(htmlPath, html);
console.log('Transformed index.html successfully.');
},
},
],
resolve: {
alias: [
{ find: "@", replacement: fileURLToPath(new URL("./src/", import.meta.url)) },
{ find: "@app", replacement: fileURLToPath(new URL("./src/", import.meta.url)) },
{ find: "@components", replacement: fileURLToPath(new URL("./src/components", import.meta.url)) },
{ find: "@forms", replacement: fileURLToPath(new URL("./src/forms", import.meta.url)) },
{ find: "@hooks", replacement: fileURLToPath(new URL("./src/hooks", import.meta.url)) },
{ find: "@api", replacement: fileURLToPath(new URL("./src/api", import.meta.url)) },
{ find: "@screens", replacement: fileURLToPath(new URL("./src/screens", import.meta.url)) },
{ find: "@utils", replacement: fileURLToPath(new URL("./src/utils", import.meta.url)) },
{ find: "@types", replacement: fileURLToPath(new URL("./src/types", import.meta.url)) },
{ find: "@domain", replacement: fileURLToPath(new URL("./src/domain", import.meta.url)) }
]
},
server: {
port: 3000,
hmr: {
overlay: true
},
proxy: {
"/api": {
target: "http://127.0.0.1:7474/",
changeOrigin: true,
secure: false
},
}
},
build: {
sourcemap: true,
rollupOptions: {
output: {
assetFileNames: (chunkInfo: PreRenderedAsset) => {
if (chunkInfo.name === "Inter-Variable.woff2") {
return "assets/[name][extname]";
}
return "assets/[name]-[hash][extname]";
}
},
}
},
experimental: {
renderBuiltUrl(filename: string, { hostId, hostType, type }: {
hostId: string,
hostType: 'js' | 'css' | 'html',
type: 'public' | 'asset'
}) {
// console.debug(filename, hostId, hostType, type)
return '{{.AssetBaseUrl}}' + filename
// if (type === 'public') {
// return 'https://www.domain.com/' + filename
// }
// else if (path.extname(hostId) === '.js') {
// return { runtime: `window.__assetsPath(${JSON.stringify(filename)})` }
// }
// else {
// return 'https://cdn.domain.com/assets/' + filename
// }
}
}
});
};