mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 05:42:15 +08:00
refactor: prefer instrumentation-client (#34009)
This commit is contained in:
@@ -1,66 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
// Polyfill for Array.prototype.toSpliced (ES2023, Chrome 110+)
|
|
||||||
if (!Array.prototype.toSpliced) {
|
|
||||||
// eslint-disable-next-line no-extend-native
|
|
||||||
Array.prototype.toSpliced = function <T>(this: T[], start: number, deleteCount?: number, ...items: T[]): T[] {
|
|
||||||
const copy = this.slice()
|
|
||||||
// When deleteCount is undefined (omitted), delete to end; otherwise let splice handle coercion
|
|
||||||
if (deleteCount === undefined)
|
|
||||||
copy.splice(start, copy.length - start, ...items)
|
|
||||||
else
|
|
||||||
copy.splice(start, deleteCount, ...items)
|
|
||||||
return copy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StorageMock {
|
|
||||||
data: Record<string, string>
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.data = {} as Record<string, string>
|
|
||||||
}
|
|
||||||
|
|
||||||
setItem(name: string, value: string) {
|
|
||||||
this.data[name] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
getItem(name: string) {
|
|
||||||
return this.data[name] || null
|
|
||||||
}
|
|
||||||
|
|
||||||
removeItem(name: string) {
|
|
||||||
delete this.data[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this.data = {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let localStorage, sessionStorage
|
|
||||||
|
|
||||||
try {
|
|
||||||
localStorage = globalThis.localStorage
|
|
||||||
sessionStorage = globalThis.sessionStorage
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
localStorage = new StorageMock()
|
|
||||||
sessionStorage = new StorageMock()
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(globalThis, 'localStorage', {
|
|
||||||
value: localStorage,
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.defineProperty(globalThis, 'sessionStorage', {
|
|
||||||
value: sessionStorage,
|
|
||||||
})
|
|
||||||
|
|
||||||
const BrowserInitializer = ({
|
|
||||||
children,
|
|
||||||
}: { children: React.ReactElement }) => {
|
|
||||||
return children
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BrowserInitializer
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { IS_DEV } from '@/config'
|
|
||||||
import { env } from '@/env'
|
|
||||||
import dynamic from '@/next/dynamic'
|
|
||||||
|
|
||||||
const SentryInitializer = dynamic(() => import('./sentry-initializer'), { ssr: false })
|
|
||||||
|
|
||||||
const LazySentryInitializer = () => {
|
|
||||||
if (IS_DEV || !env.NEXT_PUBLIC_SENTRY_DSN)
|
|
||||||
return null
|
|
||||||
|
|
||||||
return <SentryInitializer />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LazySentryInitializer
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import * as Sentry from '@sentry/react'
|
|
||||||
import { useEffect } from 'react'
|
|
||||||
import { IS_DEV } from '@/config'
|
|
||||||
import { env } from '@/env'
|
|
||||||
|
|
||||||
const SentryInitializer = () => {
|
|
||||||
useEffect(() => {
|
|
||||||
const SENTRY_DSN = env.NEXT_PUBLIC_SENTRY_DSN
|
|
||||||
if (!IS_DEV && SENTRY_DSN) {
|
|
||||||
Sentry.init({
|
|
||||||
dsn: SENTRY_DSN,
|
|
||||||
integrations: [
|
|
||||||
Sentry.browserTracingIntegration(),
|
|
||||||
Sentry.replayIntegration(),
|
|
||||||
],
|
|
||||||
tracesSampleRate: 0.1,
|
|
||||||
replaysSessionSampleRate: 0.1,
|
|
||||||
replaysOnErrorSampleRate: 1.0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SentryInitializer
|
|
||||||
@@ -9,14 +9,12 @@ import { getLocaleOnServer } from '@/i18n-config/server'
|
|||||||
import { ToastProvider } from './components/base/toast'
|
import { ToastProvider } from './components/base/toast'
|
||||||
import { ToastHost } from './components/base/ui/toast'
|
import { ToastHost } from './components/base/ui/toast'
|
||||||
import { TooltipProvider } from './components/base/ui/tooltip'
|
import { TooltipProvider } from './components/base/ui/tooltip'
|
||||||
import BrowserInitializer from './components/browser-initializer'
|
|
||||||
import { AgentationLoader } from './components/devtools/agentation-loader'
|
import { AgentationLoader } from './components/devtools/agentation-loader'
|
||||||
import { ReactScanLoader } from './components/devtools/react-scan/loader'
|
import { ReactScanLoader } from './components/devtools/react-scan/loader'
|
||||||
import LazySentryInitializer from './components/lazy-sentry-initializer'
|
|
||||||
import { I18nServerProvider } from './components/provider/i18n-server'
|
import { I18nServerProvider } from './components/provider/i18n-server'
|
||||||
import RoutePrefixHandle from './routePrefixHandle'
|
import RoutePrefixHandle from './routePrefixHandle'
|
||||||
import './styles/globals.css'
|
import './styles/globals.css'
|
||||||
import './styles/markdown.scss'
|
import './styles/markdown.css'
|
||||||
|
|
||||||
export const viewport: Viewport = {
|
export const viewport: Viewport = {
|
||||||
width: 'device-width',
|
width: 'device-width',
|
||||||
@@ -56,7 +54,6 @@ const LocaleLayout = async ({
|
|||||||
className="h-full select-auto"
|
className="h-full select-auto"
|
||||||
{...datasetMap}
|
{...datasetMap}
|
||||||
>
|
>
|
||||||
<LazySentryInitializer />
|
|
||||||
<div className="isolate h-full">
|
<div className="isolate h-full">
|
||||||
<JotaiProvider>
|
<JotaiProvider>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
@@ -67,20 +64,18 @@ const LocaleLayout = async ({
|
|||||||
enableColorScheme={false}
|
enableColorScheme={false}
|
||||||
>
|
>
|
||||||
<NuqsAdapter>
|
<NuqsAdapter>
|
||||||
<BrowserInitializer>
|
<TanstackQueryInitializer>
|
||||||
<TanstackQueryInitializer>
|
<I18nServerProvider>
|
||||||
<I18nServerProvider>
|
<ToastHost timeout={5000} limit={3} />
|
||||||
<ToastHost timeout={5000} limit={3} />
|
<ToastProvider>
|
||||||
<ToastProvider>
|
<GlobalPublicStoreProvider>
|
||||||
<GlobalPublicStoreProvider>
|
<TooltipProvider delay={300} closeDelay={200}>
|
||||||
<TooltipProvider delay={300} closeDelay={200}>
|
{children}
|
||||||
{children}
|
</TooltipProvider>
|
||||||
</TooltipProvider>
|
</GlobalPublicStoreProvider>
|
||||||
</GlobalPublicStoreProvider>
|
</ToastProvider>
|
||||||
</ToastProvider>
|
</I18nServerProvider>
|
||||||
</I18nServerProvider>
|
</TanstackQueryInitializer>
|
||||||
</TanstackQueryInitializer>
|
|
||||||
</BrowserInitializer>
|
|
||||||
</NuqsAdapter>
|
</NuqsAdapter>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</JotaiProvider>
|
</JotaiProvider>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@use '../../themes/markdown-light';
|
@import '../../themes/markdown-light.css';
|
||||||
@use '../../themes/markdown-dark';
|
@import '../../themes/markdown-dark.css';
|
||||||
|
|
||||||
.markdown-body {
|
.markdown-body {
|
||||||
-ms-text-size-adjust: 100%;
|
-ms-text-size-adjust: 100%;
|
||||||
81
web/instrumentation-client.ts
Normal file
81
web/instrumentation-client.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { IS_DEV } from '@/config'
|
||||||
|
import { env } from '@/env'
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// Polyfill for Array.prototype.toSpliced (ES2023, Chrome 110+)
|
||||||
|
if (!Array.prototype.toSpliced) {
|
||||||
|
// eslint-disable-next-line no-extend-native
|
||||||
|
Array.prototype.toSpliced = function <T>(this: T[], start: number, deleteCount?: number, ...items: T[]): T[] {
|
||||||
|
const copy = this.slice()
|
||||||
|
// When deleteCount is undefined (omitted), delete to end; otherwise let splice handle coercion
|
||||||
|
if (deleteCount === undefined)
|
||||||
|
copy.splice(start, copy.length - start, ...items)
|
||||||
|
else
|
||||||
|
copy.splice(start, deleteCount, ...items)
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!('localStorage' in globalThis) || !('sessionStorage' in globalThis)) {
|
||||||
|
class StorageMock {
|
||||||
|
data: Record<string, string>
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.data = {} as Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
setItem(name: string, value: string) {
|
||||||
|
this.data[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
getItem(name: string) {
|
||||||
|
return this.data[name] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
removeItem(name: string) {
|
||||||
|
delete this.data[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.data = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let localStorage, sessionStorage
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage = globalThis.localStorage
|
||||||
|
sessionStorage = globalThis.sessionStorage
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
localStorage = new StorageMock()
|
||||||
|
sessionStorage = new StorageMock()
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(globalThis, 'localStorage', {
|
||||||
|
value: localStorage,
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.defineProperty(globalThis, 'sessionStorage', {
|
||||||
|
value: sessionStorage,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const SENTRY_DSN = env.NEXT_PUBLIC_SENTRY_DSN
|
||||||
|
|
||||||
|
if (!IS_DEV && SENTRY_DSN) {
|
||||||
|
const Sentry = await import('@sentry/react')
|
||||||
|
Sentry.init({
|
||||||
|
dsn: SENTRY_DSN,
|
||||||
|
integrations: [
|
||||||
|
Sentry.browserTracingIntegration(),
|
||||||
|
Sentry.replayIntegration(),
|
||||||
|
],
|
||||||
|
tracesSampleRate: 0.1,
|
||||||
|
replaysSessionSampleRate: 0.1,
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
"tsx": "4.21.0",
|
"tsx": "4.21.0",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"uglify-js": "3.19.3",
|
"uglify-js": "3.19.3",
|
||||||
"vinext": "0.0.34",
|
"vinext": "https://pkg.pr.new/vinext@b6a2cac",
|
||||||
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.13",
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.1.13",
|
||||||
"vite-plugin-inspect": "11.3.3",
|
"vite-plugin-inspect": "11.3.3",
|
||||||
"vite-plus": "0.1.13",
|
"vite-plus": "0.1.13",
|
||||||
|
|||||||
7
web/plugins/vite/inject-target.ts
Normal file
7
web/plugins/vite/inject-target.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
|
export const rootClientInjectTargetRelativePath = 'instrumentation-client.ts'
|
||||||
|
|
||||||
|
export const getRootClientInjectTarget = (projectRoot: string): string => {
|
||||||
|
return path.resolve(projectRoot, rootClientInjectTargetRelativePath)
|
||||||
|
}
|
||||||
11
web/pnpm-lock.yaml
generated
11
web/pnpm-lock.yaml
generated
@@ -606,8 +606,8 @@ importers:
|
|||||||
specifier: 3.19.3
|
specifier: 3.19.3
|
||||||
version: 3.19.3
|
version: 3.19.3
|
||||||
vinext:
|
vinext:
|
||||||
specifier: 0.0.34
|
specifier: https://pkg.pr.new/vinext@b6a2cac
|
||||||
version: 0.0.34(1a91bf00ec5f7fb5f0ffb625316f9d01)
|
version: https://pkg.pr.new/vinext@b6a2cac(1a91bf00ec5f7fb5f0ffb625316f9d01)
|
||||||
vite:
|
vite:
|
||||||
specifier: npm:@voidzero-dev/vite-plus-core@0.1.13
|
specifier: npm:@voidzero-dev/vite-plus-core@0.1.13
|
||||||
version: '@voidzero-dev/vite-plus-core@0.1.13(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)'
|
version: '@voidzero-dev/vite-plus-core@0.1.13(@types/node@25.5.0)(esbuild@0.27.2)(jiti@1.21.7)(sass@1.98.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)'
|
||||||
@@ -7770,8 +7770,9 @@ packages:
|
|||||||
vfile@6.0.3:
|
vfile@6.0.3:
|
||||||
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
||||||
|
|
||||||
vinext@0.0.34:
|
vinext@https://pkg.pr.new/vinext@b6a2cac:
|
||||||
resolution: {integrity: sha512-igBP6UrL/tEtT73hPFt6EKmHTKd4lsSZ8luV5oQjmDWPcgGew3FaSt/7vo6qK42mj7yfg5MjvmQ2VmQrm2z8Cw==}
|
resolution: {integrity: sha512-/Jm507qqC1dCOhCaorb9H8/I5JEqkcsiUJw0Wgprg7Znym4eyLUvcWcRLVyM9z22Tm0+O1PugcSDA8oNvbqPuQ==, tarball: https://pkg.pr.new/vinext@b6a2cac}
|
||||||
|
version: 0.0.5
|
||||||
engines: {node: '>=22'}
|
engines: {node: '>=22'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -15977,7 +15978,7 @@ snapshots:
|
|||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
vfile-message: 4.0.3
|
vfile-message: 4.0.3
|
||||||
|
|
||||||
vinext@0.0.34(1a91bf00ec5f7fb5f0ffb625316f9d01):
|
vinext@https://pkg.pr.new/vinext@b6a2cac(1a91bf00ec5f7fb5f0ffb625316f9d01):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@unpic/react': 1.0.2(next@16.2.1(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.98.0))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
'@unpic/react': 1.0.2(next@16.2.1(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.98.0))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
'@vercel/og': 0.8.6
|
'@vercel/og': 0.8.6
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ const config = {
|
|||||||
path.resolve(_dirname, './app/components/base/button/index.css'),
|
path.resolve(_dirname, './app/components/base/button/index.css'),
|
||||||
path.resolve(_dirname, './app/components/base/modal/index.css'),
|
path.resolve(_dirname, './app/components/base/modal/index.css'),
|
||||||
path.resolve(_dirname, './app/components/base/premium-badge/index.css'),
|
path.resolve(_dirname, './app/components/base/premium-badge/index.css'),
|
||||||
|
path.resolve(_dirname, './app/components/base/segmented-control/index.css'),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
// https://github.com/tailwindlabs/tailwindcss/discussions/5969
|
// https://github.com/tailwindlabs/tailwindcss/discussions/5969
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import path from 'node:path'
|
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
import vinext from 'vinext'
|
import vinext from 'vinext'
|
||||||
@@ -6,11 +5,12 @@ import Inspect from 'vite-plugin-inspect'
|
|||||||
import { defineConfig } from 'vite-plus'
|
import { defineConfig } from 'vite-plus'
|
||||||
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
import { createCodeInspectorPlugin, createForceInspectorClientInjectionPlugin } from './plugins/vite/code-inspector'
|
||||||
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
import { customI18nHmrPlugin } from './plugins/vite/custom-i18n-hmr'
|
||||||
|
import { getRootClientInjectTarget } from './plugins/vite/inject-target'
|
||||||
import { nextStaticImageTestPlugin } from './plugins/vite/next-static-image-test'
|
import { nextStaticImageTestPlugin } from './plugins/vite/next-static-image-test'
|
||||||
|
|
||||||
const projectRoot = path.dirname(fileURLToPath(import.meta.url))
|
const projectRoot = fileURLToPath(new URL('.', import.meta.url))
|
||||||
const isCI = !!process.env.CI
|
const isCI = !!process.env.CI
|
||||||
const browserInitializerInjectTarget = path.resolve(projectRoot, 'app/components/browser-initializer.tsx')
|
const rootClientInjectTarget = getRootClientInjectTarget(projectRoot)
|
||||||
|
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const isTest = mode === 'test'
|
const isTest = mode === 'test'
|
||||||
@@ -39,17 +39,17 @@ export default defineConfig(({ mode }) => {
|
|||||||
: [
|
: [
|
||||||
Inspect(),
|
Inspect(),
|
||||||
createCodeInspectorPlugin({
|
createCodeInspectorPlugin({
|
||||||
injectTarget: browserInitializerInjectTarget,
|
injectTarget: rootClientInjectTarget,
|
||||||
}),
|
}),
|
||||||
createForceInspectorClientInjectionPlugin({
|
createForceInspectorClientInjectionPlugin({
|
||||||
injectTarget: browserInitializerInjectTarget,
|
injectTarget: rootClientInjectTarget,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
}),
|
}),
|
||||||
react(),
|
react(),
|
||||||
vinext({ react: false }),
|
vinext({ react: false }),
|
||||||
customI18nHmrPlugin({ injectTarget: browserInitializerInjectTarget }),
|
customI18nHmrPlugin({ injectTarget: rootClientInjectTarget }),
|
||||||
// reactGrabOpenFilePlugin({
|
// reactGrabOpenFilePlugin({
|
||||||
// injectTarget: browserInitializerInjectTarget,
|
// injectTarget: rootClientInjectTarget,
|
||||||
// projectRoot,
|
// projectRoot,
|
||||||
// }),
|
// }),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user