-
Notifications
You must be signed in to change notification settings - Fork 183
fix: enhance performance for codeblock #347
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
Conversation
|
WalkthroughThe pull request introduces modifications to the Changes
Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
@thucpn this looks good to merge. Why it's a draft? |
It should fix the performance issue from react syntax highlight. But I still get a bit lagging when rendering long code. So I put it in draft for investigate more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (3 hunks)
- templates/types/streaming/nextjs/package.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (1)
Pattern
templates/**
: For files under thetemplates
folder, do not report 'Missing Dependencies Detected' errors.templates/types/streaming/nextjs/package.json (1)
Pattern
templates/**
: For files under thetemplates
folder, do not report 'Missing Dependencies Detected' errors.
🔇 Additional comments (1)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (1)
57-63
: Use ofuseRef
anduseEffect
for syntax highlighting is appropriateThe implementation correctly uses
useRef
anduseEffect
to apply syntax highlighting withhljs.highlightElement
whenlanguage
orvalue
change.
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx
Outdated
Show resolved
Hide resolved
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (4)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (4)
57-63
: LGTM: Effective implementation of highlight.jsThe use of
useRef
anduseEffect
for highlighting the code withhighlight.js
is well-implemented. The condition to prevent unnecessary re-highlighting is a good optimization.Consider memoizing the
value
prop if it's a large string to potentially reduce unnecessary re-renders:const memoizedValue = useMemo(() => value, [value]);Then use
memoizedValue
in theuseEffect
dependency array and when rendering.
117-128
: LGTM: Proper structure for highlight.js usageThe code block structure using
<pre>
and<code>
tags is correct forhighlight.js
. Theref
is properly attached, and the dynamic language class is appropriately applied.Consider moving the inline styles to a CSS file for better separation of concerns:
// In your CSS file .code-block { font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; } // In your component <code ref={codeRef} className={`language-${language} code-block`} > {value} </code>
Line range hint
65-95
: Enhance security in file name handlingWhile the
downloadAsFile
function works as intended, there's a potential security risk when handling user-provided file names. Consider sanitizing the file name to prevent potential issues with special characters or malicious inputs.Add a sanitization step for the file name:
const sanitizeFileName = (name: string) => { return name.replace(/[^a-z0-9]/gi, '_').toLowerCase(); }; // In the downloadAsFile function const sanitizedFileName = sanitizeFileName(fileName || suggestedFileName);This ensures that the file name only contains alphanumeric characters and underscores, reducing the risk of potential security issues or errors when saving the file.
Line range hint
51-132
: Consider additional performance and robustness improvementsThe overall structure of the
CodeBlock
component is good, with proper use of memoization and hooks. However, there are a few areas where we can further improve performance and robustness:
- Validate the
language
prop against supported languages to prevent potential issues with unsupported languages.- Add error handling for failed highlighting attempts.
- Consider using
useMemo
for expensive computations ifvalue
changes frequently.Here's a suggested implementation incorporating these improvements:
const CodeBlock: FC<Props> = memo(({ language, value }) => { const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }); const codeRef = useRef<HTMLElement>(null); const safeLanguage = useMemo(() => { return Object.keys(programmingLanguages).includes(language) ? language : 'plaintext'; }, [language]); const highlightedCode = useMemo(() => { try { return hljs.highlight(value, { language: safeLanguage }).value; } catch (error) { console.error('Failed to highlight code:', error); return hljs.highlight(value, { language: 'plaintext' }).value; } }, [safeLanguage, value]); useEffect(() => { if (codeRef.current) { codeRef.current.innerHTML = highlightedCode; } }, [highlightedCode]); // ... rest of the component return ( <div className="codeblock relative w-full bg-zinc-950 font-sans"> {/* ... */} <pre className="border border-zinc-700"> <code ref={codeRef} className={`language-${safeLanguage} code-block`} /> </pre> </div> ); });This implementation validates the language, handles potential highlighting errors, and memoizes the highlighted code for better performance.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
- templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (1)
Pattern
templates/**
: For files under thetemplates
folder, do not report 'Missing Dependencies Detected' errors.
🔇 Additional comments (1)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (1)
3-4
: LGTM: Import statements updated correctlyThe import statements have been appropriately updated to include
highlight.js
and its CSS, while also addinguseRef
to the React imports. These changes align well with the switch fromreact-syntax-highlighter
tohighlight.js
.Also applies to: 6-6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (1)
helpers/typescript.ts (1)
Missing
backend
parameter ininstallTSTemplate
call
helpers/index.ts: await installTSTemplate(props);
is missing the requiredbackend
parameter.🔗 Analysis chain
Line range hint
29-29
: Ensure all calls toinstallTSTemplate
include the newbackend
parameterThe function
installTSTemplate
now includes an additionalbackend
parameter. Please verify that all invocations of this function are updated to include this new parameter to prevent any runtime errors.You can run the following script to find and review all calls to
installTSTemplate
:🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Find all calls to `installTSTemplate` and check for the `backend` parameter. # Search for the function usage and display the following 3 lines. rg --type typescript 'installTSTemplate\(' -A 3Length of output: 84
Script:
#!/bin/bash # Description: Find all calls to `installTSTemplate` in TypeScript files and check for the `backend` parameter. # Search for the function usage in .ts and .tsx files and display the following 3 lines. rg 'installTSTemplate\(' -A 3 -g '*.ts' -g '*.tsx'Length of output: 192
fontFamily: | ||
'Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@can't we just use the variable?
fontFamily: | |
'Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace', | |
fontFamily: "var(--font-mono)", |
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx
Show resolved
Hide resolved
…essage/codeblock.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (5)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (4)
3-4
: LGTM! Consider customizing the highlight.js theme.The import changes align well with the PR objective of replacing
react-syntax-highlighter
withhighlight.js
. However, as per a previous review comment, you might want to consider using a custom theme for better visual integration with your application.You can change line 4 to use a custom theme, for example:
-import "highlight.js/styles/atom-one-dark-reasonable.css"; +import "highlight.js/styles/github-dark-dimmed.css";See all available themes here.
Also applies to: 6-6
58-64
: LGTM! Effective use of hooks for syntax highlighting.The implementation of
useRef
anduseEffect
hooks is correct and efficient for applying syntax highlighting. The check to prevent unnecessary re-highlighting is a good performance optimization.Consider memoizing the
value
prop if it's an object or array to prevent unnecessary re-renders:const memoizedValue = useMemo(() => value, [JSON.stringify(value)]);Then update the effect dependency:
}, [language, memoizedValue]);This ensures that the effect only runs when the actual content of
value
changes, not just when its reference changes.
100-102
: LGTM! Proper implementation of the className prop.The
className
prop is correctly implemented in the main div, allowing for custom styling of theCodeBlock
component.Consider using a utility library like
clsx
orclassnames
for more robust class name management, especially if the component's styling complexity grows:import clsx from 'clsx'; // In the component: className={clsx( 'codeblock relative w-full bg-zinc-950 font-sans', className )}This approach can help manage conditional classes more easily in the future.
120-124
: LGTM! Simplified and standard-compliant code rendering structure.The new rendering structure using
<pre>
and<code>
tags is appropriate forhighlight.js
and follows HTML standards for code blocks. The dynamiclanguage
class is correctly applied for syntax highlighting.As per a previous review comment, consider using a CSS variable for the font family:
-<code ref={codeRef} className={`language-${language} font-mono`}> +<code ref={codeRef} className={`language-${language}`} style={{ fontFamily: "var(--font-mono)" }}>This approach allows for easier global font management and consistency across your application.
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/markdown.tsx (1)
Line range hint
122-138
: Improved citation link handling with a minor suggestionThe update to the 'a' component rendering function is a good improvement in handling citation links. It now correctly renders valid citations using the SourceNumberButton component and safely handles invalid ones.
However, for invalid citations (when the index is not a number), consider logging a warning or displaying a subtle error indicator instead of silently rendering nothing. This could help with debugging and provide better feedback to content creators.
Consider adding a warning log or subtle error indicator for invalid citations:
if (!isNaN(index)) { return <SourceNumberButton index={index} />; } else { - // citation is not looked up yet, don't render anything - return <></>; + console.warn(`Invalid citation index: ${children[0]}`); + return <span title="Invalid citation" style={{ color: 'red' }}>❗</span>; }🧰 Tools
🪛 Biome
[error] 115-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (4 hunks)
- templates/types/streaming/nextjs/app/components/ui/chat/chat-message/markdown.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (1)
Pattern
templates/**
: For files under thetemplates
folder, do not report 'Missing Dependencies Detected' errors.templates/types/streaming/nextjs/app/components/ui/chat/chat-message/markdown.tsx (1)
Pattern
templates/**
: For files under thetemplates
folder, do not report 'Missing Dependencies Detected' errors.
🔇 Additional comments (5)
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/codeblock.tsx (3)
13-13
: LGTM! Good addition for component flexibility.Adding an optional
className
prop enhances the reusability and customization options for theCodeBlock
component.
56-56
: LGTM! Component signature updated correctly.The
CodeBlock
component signature has been properly updated to include the newclassName
prop, maintaining the use ofmemo
for performance optimization.
Line range hint
1-132
: Great job on the CodeBlock component refactor!The changes successfully implement the switch from
react-syntax-highlighter
tohighlight.js
, aligning well with the PR objectives of enhancing performance for code block rendering. The implementation is clean, follows React best practices, and includes some performance optimizations.Key improvements:
- Simplified rendering structure using standard HTML tags.
- Efficient use of
useRef
anduseEffect
for applying syntax highlighting.- Added flexibility with the new
className
prop.Consider the minor suggestions provided in the previous comments for further optimization and consistency. Overall, this refactor should significantly improve the performance of code rendering in the application.
templates/types/streaming/nextjs/app/components/ui/chat/chat-message/markdown.tsx (2)
117-117
: LGTM: Improved CodeBlock stylingThe addition of the "mb-2" class to the CodeBlock component is a good styling improvement. It likely adds a bottom margin, which should enhance the visual separation between code blocks and surrounding content.
Line range hint
1-153
: Overall assessment: Good improvements with minor enhancement suggestionThe changes in this file are well-implemented and improve both the styling of code blocks and the handling of citation links. These modifications align with the PR's objective of enhancing performance, although their direct impact on performance might be minimal.
The code adheres to the provided coding guidelines, and no major issues were found. The suggestion for improving invalid citation handling is a minor enhancement that could further improve the user experience and debugging process.
🧰 Tools
🪛 Biome
[error] 115-115: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Currently, asking AI for generating inline code will make browser tag so lag.
The root cause is may because react-syntax-highlight re-render too many times.
Summary by CodeRabbit
New Features
highlight.js
.Bug Fixes