From 25ff8939f68aa35e6e7a52d06858221b5b04a1ef Mon Sep 17 00:00:00 2001 From: Marc Date: Sun, 9 Mar 2025 13:40:57 +0000 Subject: [PATCH] feat(dev): use proxy server in dev mode (#3069) In dev environment, this PR allows to proxy to whatever backend without CORS issue by specifying the backend URL in `.env.local` variable. I believe this would ease contribution by frontend developpers that would only have to run the unstable docker to work on the frontend without need for all the go toolchain to build the whole backend to have a cors enabled backend. Co-authored-by: kolaente Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/3069 Co-authored-by: Marc Co-committed-by: Marc --- .drone.yml | 8 ++---- frontend/.env.local.example | 4 ++- frontend/README.md | 17 ++++++++++- frontend/index.html | 2 +- frontend/netlify.toml | 12 ++++++-- frontend/src/helpers/checkAndSetApiUrl.ts | 4 ++- frontend/vite.config.ts | 35 +++++++++++++++++++++-- 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/.drone.yml b/.drone.yml index ec03f3fc5..c375ed277 100644 --- a/.drone.yml +++ b/.drone.yml @@ -448,7 +448,7 @@ steps: from_secret: cypress_project_key commands: - cd frontend - - sed -i 's/localhost/test-api-run/g' dist-test/index.html + - sed -i 's@/api/v1@http://test-api-run:3456/api/v1@g' dist-test/index.html - npm install -g corepack && corepack enable && pnpm config set store-dir .cache/pnpm - pnpm cypress install - pnpm run test:e2e-record-test @@ -470,8 +470,6 @@ steps: commands: - cd frontend - cp -r dist-test dist-preview - # Override the default api url used for preview - - sed -i 's|http://localhost:3456|https://try.vikunja.io|g' dist-preview/index.html # create via: # `shasum -a 384 ./scripts/deploy-preview-netlify.mjs > ./scripts/deploy-preview-netlify.mjs.sha384` - shasum -a 384 -c ./scripts/deploy-preview-netlify.mjs.sha384 @@ -973,7 +971,6 @@ steps: - pnpm install --fetch-timeout 100000 --frozen-lockfile - pnpm run lint - pnpm run build - - sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing - name: static image: kolaente/zip @@ -1032,7 +1029,6 @@ steps: - npm install -g corepack && corepack enable && pnpm config set store-dir .cache/pnpm - pnpm install --fetch-timeout 100000 --frozen-lockfile - pnpm run build - - sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing - name: static image: kolaente/zip @@ -1208,6 +1204,6 @@ steps: --- kind: signature -hmac: 03f04eb6ba48191e7a854126243382c9ff0213f728b9f8525e74331535dd4968 +hmac: 321cc0f212caa1566aa5139c8f983f0e55653ddc241e3093b24697802be733be ... diff --git a/frontend/.env.local.example b/frontend/.env.local.example index 6fd3aaff2..15dc19401 100644 --- a/frontend/.env.local.example +++ b/frontend/.env.local.example @@ -9,4 +9,6 @@ # SENTRY_AUTH_TOKEN=YOUR_TOKEN # SENTRY_ORG=vikunja # SENTRY_PROJECT=frontend-oss -# VIKUNJA_FRONTEND_BASE=/custom-subpath \ No newline at end of file +# VIKUNJA_FRONTEND_BASE=/custom-subpath + +# DEV_PROXY=http://vikunja-backend.domain.tld \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index 7cd67481c..4141bbf32 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -17,7 +17,22 @@ For general information about the project, refer to the top-level readme of this pnpm install ``` -### Compiles and hot-reloads for development +### Development + +#### Define backend server + +You can develop the web front end against any accessible backend, including the demo at https://try.vikunja.io + +In order to do so, you need to set the `DEV_PROXY` env variable. The recommended way to do so is to: + +- Copy `.env.local.exemple` as `.env.local` +- Uncomment the `DEV_PROXY` line +- Set the backend url you want to use + +In the end, it should look like `DEV_PROXY=https://try.vikunja.io` if you work against the online demo backend. + + +#### Start dev server (compiles and hot-reloads) ```shell pnpm run dev diff --git a/frontend/index.html b/frontend/index.html index 5619b2f99..9ad084d61 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -22,7 +22,7 @@ // This variable points the frontend to the api. // It has to be the full url, including the last /api/v1 part and port. // You can change this if your api is not reachable on the same port as the frontend. - window.API_URL = 'http://localhost:3456/api/v1' + window.API_URL = '/api/v1' diff --git a/frontend/netlify.toml b/frontend/netlify.toml index afa6154f0..d48bb5f26 100644 --- a/frontend/netlify.toml +++ b/frontend/netlify.toml @@ -2,6 +2,12 @@ command = "pnpm run build" publish = "dist-preview" +[[redirects]] + from = "/api/*" + to = "https://try.vikunja.io/api/:splat" + status = 200 + force = true + [[redirects]] from = "/*" to = "/index.html" @@ -10,6 +16,6 @@ [[headers]] for = "/*" [headers.values] - X-Frame-Options = "DENY" - X-XSS-Protection = "1; mode=block" - X-Robots-Tag = "noindex" + X-Frame-Options = "DENY" + X-XSS-Protection = "1; mode=block" + X-Robots-Tag = "noindex" diff --git a/frontend/src/helpers/checkAndSetApiUrl.ts b/frontend/src/helpers/checkAndSetApiUrl.ts index 3ac1770c8..b60886b50 100644 --- a/frontend/src/helpers/checkAndSetApiUrl.ts +++ b/frontend/src/helpers/checkAndSetApiUrl.ts @@ -20,7 +20,8 @@ export class InvalidApiUrlProvidedError extends Error { } } -export const checkAndSetApiUrl = (url: string | undefined | null): Promise => { +export const checkAndSetApiUrl = (pUrl: string | undefined | null): Promise => { + let url = pUrl if (url === '' || url === null || typeof url === 'undefined') { throw new NoApiUrlProvidedError() } @@ -55,6 +56,7 @@ export const checkAndSetApiUrl = (url: string | undefined | null): Promise { + console.warn(`Could not fetch 'info' from the provided endpoint ${pUrl} on ${window.API_URL}/info. Some automatic fallback will be tried.`) // Check if it is reachable at /api/v1 and http if ( !urlToCheck.pathname.endsWith('/api/v1') && diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 66e97c7ed..df08e5f1b 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -66,12 +66,24 @@ function createFontMatcher(fontNames: string[]) { } // https://vitejs.dev/config/ -export default defineConfig(({mode}) => { +export default defineConfig(({command, mode}) => { // Load env file based on `mode` in the current working directory. // Set the third parameter to '' to load all env regardless of the `VITE_` prefix. // https://vitejs.dev/config/#environment-variables const env = loadEnv(mode, process.cwd(), '') + switch (command) { + case 'serve': + // this is DEV mode + return getServeConfig(env) + // return getBuildConfig(env) + case 'build': + // build for prodution + return getBuildConfig(env) + } +}) + +function getBuildConfig(env: Record) { return { base: env.VIKUNJA_FRONTEND_BASE, // https://vitest.dev/config/ @@ -220,4 +232,23 @@ export default defineConfig(({mode}) => { }, }, } -}) +} + +function getServeConfig(env: Record) { + // get some default settings from prod mod + const buildConfig = getBuildConfig(env) + // override prod settings with dev settings + return { + ...buildConfig, + server: { + ...buildConfig.server, + ...(env.DEV_PROXY && { proxy: { + '/api': { + target: env.DEV_PROXY, + changeOrigin: true, + secure: false, + }, + }}), + }, + } +}