Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize basename handling and ensure dynamic runtime definition (custom basepath) #3317

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ Flowise support different environment variables to configure your instance. You
| S3_STORAGE_REGION | Region for S3 bucket | String | |
| S3_ENDPOINT_URL | Custom Endpoint for S3 | String | |
| SHOW_COMMUNITY_NODES | Show nodes created by community | Boolean | |
| BASE_HREF | Sets the base URL for React Router’s basename and should only be defined dynamically at runtime | String | |

You can also specify the env variables when using `npx`. For example:

Expand Down
1 change: 1 addition & 0 deletions i18n/CONTRIBUTING-ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ Flowise 支持不同的环境变量来配置您的实例。您可以在 `package
| S3_STORAGE_REGION | S3 存储地区 | 字符串 | |
| S3_ENDPOINT_URL | S3 端点 URL | 字符串 | |
| SHOW_COMMUNITY_NODES | 显示由社区创建的节点 | 布尔值 | |
| BASE_HREF | 设置React路由器的basename的基本URL,并且只能在运行时动态定义 | 字符串 | |

您也可以在使用 `npx` 时指定环境变量。例如:

Expand Down
27 changes: 27 additions & 0 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from 'express'
import { Request, Response } from 'express'
import fs from 'fs'
import path from 'path'
import cors from 'cors'
import http from 'http'
Expand Down Expand Up @@ -31,6 +32,29 @@ declare global {
}
}

function replaceBaseHref(filePath: string) {
const backupPath = `${filePath}.tpl`
let sourceFile = filePath

// If index.html.tpl exists, use it as the source file and skip creating the backup
if (fs.existsSync(backupPath)) {
sourceFile = backupPath
} else {
// Create a backup if it doesn't exist
fs.copyFileSync(filePath, backupPath)
}

// Read the source file
const content = fs.readFileSync(sourceFile, 'utf8')

// Replace %BASE_HREF% with the value of BASE_HREF or '/' if not set
const baseHref = process.env.BASE_HREF || '/'
const updatedContent = content.replace(/%BASE_HREF%/g, baseHref)

// Write the updated content back to index.html
fs.writeFileSync(filePath, updatedContent, 'utf8')
}

export class App {
app: express.Application
nodesPool: NodesPool
Expand Down Expand Up @@ -223,6 +247,9 @@ export class App {
const uiBuildPath = path.join(packagePath, 'build')
const uiHtmlPath = path.join(packagePath, 'build', 'index.html')

// replace index.html BASE_HREF env variable to support custom basename
replaceBaseHref(uiHtmlPath)

this.app.use('/', express.static(uiBuildPath))

// All other requests not handled will return React app
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="%BASE_HREF%" />
<title>Flowise - Low-code LLM apps builder</title>
<link rel="icon" href="favicon.ico" />
<!-- Meta Tags-->
<!-- Meta Tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2296f3" />
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/public/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base href="%BASE_HREF%" />
<title>Flowise - Low-code LLM apps builder</title>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- Meta Tags-->
<!-- Meta Tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2296f3" />
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import { Provider } from 'react-redux'
import { SnackbarProvider } from 'notistack'
import ConfirmContextProvider from '@/store/context/ConfirmContextProvider'
import { ReactFlowContext } from '@/store/context/ReactFlowContext'
import { baseName } from '@/store/constant'

const container = document.getElementById('root')
const root = createRoot(container)

root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<BrowserRouter basename={baseName}>
<SnackbarProvider>
<ConfirmContextProvider>
<ReactFlowContext>
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/src/store/constant.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { getBasename } from '@/utils/genericHelper'

// constant
export const gridSpacing = 3
export const drawerWidth = 260
export const appDrawerWidth = 320
export const headerHeight = 80
export const maxScroll = 100000
export const baseURL = import.meta.env.VITE_API_BASE_URL || window.location.origin
export const uiBaseURL = import.meta.env.VITE_UI_BASE_URL || window.location.origin
export const baseName = getBasename()
export const baseURL = (import.meta.env.VITE_API_BASE_URL || window.location.origin) + baseName
export const uiBaseURL = (import.meta.env.VITE_API_BASE_URL || window.location.origin) + baseName
export const FLOWISE_CREDENTIAL_ID = 'FLOWISE_CREDENTIAL_ID'
export const REDACTED_CREDENTIAL_VALUE = '_FLOWISE_BLANK_07167752-1a71-43b1-bf8f-4f32252165db'
16 changes: 16 additions & 0 deletions packages/ui/src/utils/genericHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -945,3 +945,19 @@ export const getCustomConditionOutputs = (value, nodeId, existingEdges, isDataGr

return { outputAnchors, toBeRemovedEdgeIds }
}

export const getBasename = () => {
try {
const baseTag = document.querySelector('base')
let baseHref = baseTag ? baseTag.getAttribute('href') || '/' : '/'
if (baseHref === '%BASE_HREF%') {
baseHref = '/'
}
if (baseHref.endsWith('/')) {
baseHref = baseHref.slice(0, -1)
}
return baseHref
} catch (error) {
throw new Error(`basenameHelper.getBasename ${getErrorMessage(error)}`)
}
}
3 changes: 2 additions & 1 deletion packages/ui/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default defineConfig(async ({ mode }) => {
proxy,
port: process.env.VITE_PORT ?? 8080,
host: process.env.VITE_HOST
}
},
base: './'
}
})
Loading