fix: use fixed react version

This commit is contained in:
mingholy.lmh 2026-01-29 20:02:21 +08:00
parent 86a43618a7
commit 54bb39f6ab
7 changed files with 128 additions and 20 deletions

View file

@ -26,10 +26,24 @@ const templateModulePath = join(
'formatters',
'htmlTemplate.ts',
);
const packageJsonPath = join(assetsDir, 'package.json');
await mkdir(assetsDistDir, { recursive: true });
await mkdir(packageDistDir, { recursive: true });
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
const dependencyVersions = packageJson?.dependencies ?? {};
const getDependencyVersion = (name) => {
const version = dependencyVersions[name];
if (!version) {
throw new Error(`Missing ${name} dependency version in package.json.`);
}
return version.replace(/^[^0-9]*/, '');
};
const webuiVersion = getDependencyVersion('@qwen-code/webui');
const reactUmdVersion = '18.2.0';
const reactDomUmdVersion = '18.2.0';
const buildResult = await build(buildConfig);
const jsBundle = buildResult.outputFiles.find((file) =>
@ -52,6 +66,9 @@ const faviconData = encodeURIComponent(faviconSvg.trim());
const htmlOutput = htmlTemplate
.replace('__INLINE_CSS__', css.trim())
.replace('__INLINE_SCRIPT__', jsBundle.text.trim())
.replaceAll('__REACT_UMD_VERSION__', reactUmdVersion)
.replaceAll('__REACT_DOM_UMD_VERSION__', reactDomUmdVersion)
.replaceAll('__WEBUI_VERSION__', webuiVersion)
.replace('__FAVICON_SVG__', faviconSvg.trim())
.replace('__FAVICON_DATA__', faviconData);

View file

@ -14,7 +14,15 @@ export const buildConfig = {
platform: 'browser',
format: 'iife',
target: ['es2018'],
jsx: 'automatic',
jsx: 'transform',
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
tsconfigRaw: {
compilerOptions: {
jsx: 'react',
},
},
external: ['react', 'react-dom', 'react-dom/client'],
legalComments: 'none',
loader: {
'.ts': 'ts',

View file

@ -6,9 +6,7 @@
"build": "node build.mjs"
},
"dependencies": {
"@qwen-code/webui": "^0.1.0-beta.4",
"react": "^19.1.0",
"react-dom": "^19.1.0"
"@qwen-code/webui": "^0.1.0-beta.4"
},
"devDependencies": {
"esbuild": "^0.25.0"

View file

@ -8,6 +8,33 @@
type="image/svg+xml"
href="data:image/svg+xml,__FAVICON_DATA__"
/>
<script
crossorigin
src="https://unpkg.com/react@__REACT_UMD_VERSION__/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@__REACT_DOM_UMD_VERSION__/umd/react-dom.production.min.js"
></script>
<script>
const withKey = (props, key) =>
key == null ? props : Object.assign({}, props, { key });
const jsx = (type, props, key) => React.createElement(type, withKey(props, key));
const jsxRuntime = {
Fragment: React.Fragment,
jsx,
jsxs: jsx,
jsxDEV: jsx,
};
window.ReactJSXRuntime = jsxRuntime;
window['react/jsx-runtime'] = jsxRuntime;
window['react/jsx-dev-runtime'] = jsxRuntime;
</script>
<script src="https://unpkg.com/@qwen-code/webui@__WEBUI_VERSION__/dist/index.umd.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/@qwen-code/webui@__WEBUI_VERSION__/dist/styles.css"
/>
<title>Qwen Code Chat Export</title>
<style>
@font-face {
@ -23,9 +50,7 @@
<body>
<div id="app"></div>
<script id="chat-data" type="application/json">
// DATA_PLACEHOLDER: Chat export data will be injected here
</script>
<script id="chat-data" type="application/json"></script>
<script>
__INLINE_SCRIPT__;
</script>

View file

@ -1,17 +1,47 @@
import { createRoot } from 'react-dom/client';
import { ChatViewer, PlatformProvider } from '@qwen-code/webui';
import '@qwen-code/webui/styles.css';
import './styles.css';
import logoSvg from './favicon.svg';
declare global {
interface Window {
React: typeof import('react');
ReactDOM: typeof import('react-dom/client');
}
}
const ReactDOM = window.ReactDOM;
declare const QwenCodeWebUI: {
ChatViewer: (props: {
messages: unknown[];
autoScroll: boolean;
theme: string;
}) => React.ReactNode;
PlatformProvider: (props: {
value: unknown;
children: React.ReactNode;
}) => React.ReactNode;
};
const { ChatViewer, PlatformProvider } = QwenCodeWebUI;
type ChatData = {
messages?: unknown[];
sessionId?: string;
startTime?: string;
};
type PlatformContextValue = Parameters<typeof PlatformProvider>[0]['value'];
type ChatViewerMessage = Parameters<typeof ChatViewer>[0]['messages'][number];
type PlatformContextValue = {
platform: 'web';
postMessage: (message: unknown) => void;
onMessage: (handler: (event: MessageEvent) => void) => () => void;
openFile: (path: string) => void;
getResourceUrl: () => string | undefined;
features: {
canOpenFile: boolean;
canCopy: boolean;
};
};
type ChatViewerMessage = { type?: string } & Record<string, unknown>;
const logoSvgWithGradient = (() => {
if (!logoSvg) {
@ -133,5 +163,5 @@ const rootElement = document.getElementById('app');
if (!rootElement) {
console.error('App container not found.');
} else {
createRoot(rootElement).render(<App />);
ReactDOM.createRoot(rootElement).render(<App />);
}