Skip to content

Fix/canvas performance #1314

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

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

1degrees
Copy link
Contributor

@1degrees 1degrees commented Apr 15, 2025

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

Issue Number: #1279

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Added automated copying of the canvas.js asset into build outputs, ensuring it is available as a static file rather than an inlined resource.
    • Enabled direct import of the canvas asset via a new export path.
  • Chores

    • Updated build configurations to support the new asset handling.
    • Added a development dependency for static asset copying.

Copy link
Contributor

coderabbitai bot commented Apr 15, 2025

Walkthrough

This update introduces a new Vite plugin, vitePluginCopyCanvas, designed to copy a canvas.js asset into the build output, with its source path determined by build options. The plugin is integrated into the base Vite configuration for the engine, and related configuration options are refactored for consistency. The canvas package's build process is adjusted to generate and export the canvas.js asset as a file rather than an inlined base64 string, and the package's exports are updated to expose this new asset. The design-core package is also updated to include the static copy plugin for its own build process.

Changes

Files/Paths Change Summary
packages/build/vite-config/src/default-config.js Added import and integration of vitePluginCopyCanvas; refactored config destructuring and plugin usage.
packages/build/vite-config/src/vite-plugins/vitePluginCopyCanvas.js New file: Implements the vitePluginCopyCanvas Vite plugin for copying the canvas asset.
packages/canvas/package.json Added export subpath "./canvas" pointing to "./dist/assets/canvas.js".
packages/canvas/scripts/vite-plugin-separate-build.ts Modified asset emission logic: emits canvas.js as file if needAsset is true, adjusts module export method.
packages/canvas/vite.config.ts Added needAsset: true to Vite config to enable asset file output.
packages/design-core/package.json Added vite-plugin-static-copy to devDependencies.
packages/design-core/vite.config.js Added vite-plugin-static-copy to plugins to copy canvas.js into build output.

Sequence Diagram(s)

sequenceDiagram
    participant Builder as Vite Build Process
    participant CanvasPkg as @opentiny/tiny-engine-canvas
    participant CopyPlugin as vitePluginCopyCanvas
    participant Output as Build Output

    Builder->>CanvasPkg: Build canvas package (needAsset: true)
    CanvasPkg-->>Output: Emit assets/canvas.js
    Builder->>CopyPlugin: Execute vitePluginCopyCanvas
    CopyPlugin->>Output: Copy canvas.js to build output assets/
Loading

Poem

In the meadow of code where the canvas lies,
A rabbit hops, with assets to prize.
Copy and bundle, with plugins anew,
Canvas.js now shines, in the build it grew.
Exports expanded, configs aligned,
This bunny’s work is neatly designed! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17e4570 and 86237b3.

📒 Files selected for processing (1)
  • packages/design-core/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/design-core/package.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the bug Something isn't working label Apr 15, 2025
@1degrees
Copy link
Contributor Author

1degrees commented Apr 15, 2025

调整画布的编译策略,将canvas 独立编译,并以静态资源形式引入页面,且增加了配套插件vitePluginCopyCanvas进行复制。
1、源码方式编译发布 - 测试通过
2、pnpm安装包方式编译发布 - 测试通过
官方大佬审核下,酌情考量是否合并

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Adjust the compilation strategy of the canvas, compile canvas independently, and introduce the page in the form of static resources, and add the supporting plug-in vitePluginCopyCanvas for copying.

  1. Source code method, compile and release test pass
  2. Pnpm installation package method, compile and release test pass
    Under the review of the official boss, merge as appropriate

1 similar comment
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Adjust the compilation strategy of the canvas, compile canvas independently, and introduce the page in the form of static resources, and add the supporting plug-in vitePluginCopyCanvas for copying.

  1. Source code method, compile and release test pass
  2. Pnpm installation package method, compile and release test pass
    Under the review of the official boss, merge as appropriate

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33b02c7 and 7891aaf.

📒 Files selected for processing (7)
  • packages/build/vite-config/src/default-config.js (4 hunks)
  • packages/build/vite-config/src/vite-plugins/vitePluginCopyCanvas.js (1 hunks)
  • packages/canvas/package.json (1 hunks)
  • packages/canvas/scripts/vite-plugin-separate-build.ts (2 hunks)
  • packages/canvas/vite.config.ts (1 hunks)
  • packages/design-core/package.json (1 hunks)
  • packages/design-core/vite.config.js (2 hunks)
🔇 Additional comments (10)
packages/design-core/package.json (1)

119-120: Dependencies updated appropriately for new functionality.

The addition of vite-plugin-static-copy as a development dependency is necessary to support the new static asset copy functionality for improved canvas performance. This aligns with the changes in the vite config files.

packages/canvas/vite.config.ts (1)

23-23:

✅ Verification successful

Good addition to enable separate asset generation.

Adding the needAsset: true configuration enables the canvas.js file to be generated as a separate asset rather than being embedded as a base64 string. This should improve performance by:

  1. Reducing the main bundle size
  2. Allowing the canvas asset to be loaded on demand
  3. Enabling better caching of the canvas asset

Let's verify that the vitePluginBuildEntry properly handles this new flag:


🏁 Script executed:

#!/bin/bash
# Check how the needAsset flag is used in the separate build plugin
echo "Checking how needAsset flag is used in vite-plugin-separate-build.ts:"
cd $(git rev-parse --show-toplevel)
rg -A 5 "needAsset" packages/canvas/scripts/vite-plugin-separate-build.ts

Length of output: 666


Asset Generation Verified

The configuration setting needAsset: true in packages/canvas/vite.config.ts is correctly picked up in the separate build plugin. The verification shows that when the flag is enabled, the plugin in packages/canvas/scripts/vite-plugin-separate-build.ts:

  • Emits assets/canvas.js using saveEmitBundleAssets
  • Returns an export pointing to the asset ('./assets/canvas.js') rather than embedding a base64 string

This change effectively reduces the main bundle size, supports on-demand asset loading, and improves caching.

packages/design-core/vite.config.js (1)

5-5:

✅ Verification successful

Static copy plugin properly integrated for canvas asset.

The integration of the viteStaticCopy plugin is well-implemented to copy the canvas.js asset from the canvas package to the assets directory during build.

Consider using the newly created vitePluginCopyCanvas instead of directly using viteStaticCopy to maintain consistency across the codebase:

 import vueJsx from '@vitejs/plugin-vue-jsx'
-import { viteStaticCopy } from 'vite-plugin-static-copy'
+import { vitePluginCopyCanvas } from '../build/vite-config/src/vite-plugins/vitePluginCopyCanvas'
 import nodeGlobalsPolyfillPluginCjs from '@esbuild-plugins/node-globals-polyfill'
 import nodeModulesPolyfillPluginCjs from '@esbuild-plugins/node-modules-polyfill'
 import nodePolyfill from 'rollup-plugin-polyfill-node'
 import { fileURLToPath } from 'node:url'

 const nodeGlobalsPolyfillPlugin = nodeGlobalsPolyfillPluginCjs.default
 const nodeModulesPolyfillPlugin = nodeModulesPolyfillPluginCjs.default

 const __filename = fileURLToPath(import.meta.url)
 const __dirname = path.dirname(__filename)

 export default defineConfig({
   plugins: [
     vue(),
     vueJsx(),
-    viteStaticCopy({
-      targets: [
-        {
-          src: path.resolve(__dirname, '..', 'canvas/dist/assets/canvas.js'),
-          dest: 'assets/'
-        }
-      ]
-    })
+    ...vitePluginCopyCanvas({
+      assetsDir: path.resolve(__dirname, '..', 'canvas/dist/assets/canvas.js')
+    })
   ],

Let's check if the path to the canvas.js file is correctly specified:

Also applies to: 18-29


🏁 Script executed:

#!/bin/bash
# Check if the canvas.js file exists at the specified location
echo "Checking canvas.js path in design-core:"
cd $(git rev-parse --show-toplevel)
CANVAS_PATH="packages/canvas/dist/assets/canvas.js"
if [ -f "$CANVAS_PATH" ]; then
  echo "$CANVAS_PATH exists"
else
  echo "$CANVAS_PATH does not exist"
  # Check if the directory structure exists
  mkdir -p "$(dirname "$CANVAS_PATH")"
  echo "  Directory structure has been created"
  echo "  The file will be generated during build"
fi

Length of output: 635


Canvas Asset Copy Integration - Verified and Approved

The verification confirms that the path for the canvas asset is correct. Although the file itself isn’t present at the moment (as it is generated during the build), the change to use vitePluginCopyCanvas is consistent with our codebase practices.

  • The new diff snippet correctly replaces the direct use of viteStaticCopy with the custom vitePluginCopyCanvas.
  • The path to packages/canvas/dist/assets/canvas.js is properly specified, keeping in mind that the file is generated at build time.

Overall, no further modifications are required.

packages/canvas/package.json (1)

23-25: Well-structured export addition for the canvas asset.

The new export path allows consumers to directly import the canvas.js asset via @opentiny/tiny-engine-canvas/canvas. This aligns with the broader changes to emit the canvas.js as a separate asset file rather than an inlined base64 string.

packages/build/vite-config/src/default-config.js (4)

16-16: Clean import for the new Vite plugin.

The import statement for the new vitePluginCopyCanvas plugin is properly placed with other plugin imports.


135-135: Appropriate variable destructuring for configuration clarity.

Good practice to destructure useSourceAlias and assetsDir from engineConfig, making these variables available for consistent use throughout the function.


157-160: Plugin integration with proper configuration.

The vitePluginCopyCanvas plugin is correctly integrated into the plugin list with the required options.


184-184: Consistent usage of destructured variables.

The code now consistently uses the destructured useSourceAlias variable instead of accessing it through engineConfig, improving code consistency and readability.

Also applies to: 186-186

packages/canvas/scripts/vite-plugin-separate-build.ts (2)

30-36: New asset handling mode for canvas.js.

The code now extracts the code property and conditionally saves it as a separate asset with a fixed filename when config.needAsset is true. This supports the performance improvement by allowing the canvas.js to be loaded as a separate file rather than being inlined.


97-105: Conditional export strategy based on configuration.

The module now exports different values based on the config.needAsset flag:

  • When true: exports a path to the external asset file (./assets/canvas.js)
  • When false: maintains backward compatibility by exporting the base64-encoded data URL

This change is central to the performance fix, allowing the canvas bundle to be loaded separately instead of being inlined in the JavaScript, which can improve initial load times.

Comment on lines +4 to +21
export function vitePluginCopyCanvas(options = {}) {
let { useSource, assetsDir } = options
if (!assetsDir) {
assetsDir = useSource
? path.resolve(process.cwd(), '..', 'packages/design-core/dist/assets/canvas.js')
: path.resolve(process.cwd(), 'node_modules/@opentiny/tiny-engine/dist/assets/canvas.js')
}
return [
...viteStaticCopy({
targets: [
{
src: assetsDir,
dest: 'assets/'
}
]
})
]
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Well-structured plugin for canvas.js copying.

The implementation creates a flexible Vite plugin that handles copying the canvas.js asset file to the build output based on configuration options. This is a good approach to improve canvas performance by avoiding base64 encoding.

However, there are a few potential improvements:

Consider adding some error handling to check if the source file exists before attempting to copy it:

 export function vitePluginCopyCanvas(options = {}) {
   let { useSource, assetsDir } = options
   if (!assetsDir) {
     assetsDir = useSource
       ? path.resolve(process.cwd(), '..', 'packages/design-core/dist/assets/canvas.js')
       : path.resolve(process.cwd(), 'node_modules/@opentiny/tiny-engine/dist/assets/canvas.js')
   }
+  // Check if the file exists - for better error reporting
+  try {
+    require('fs').accessSync(assetsDir, require('fs').constants.R_OK)
+  } catch (err) {
+    console.warn(`Warning: Canvas.js asset not found at ${assetsDir}. Build will continue but canvas may not function correctly.`)
+  }
   return [
     ...viteStaticCopy({
       targets: [
         {
           src: assetsDir,
           dest: 'assets/'
         }
       ]
     })
   ]
 }

The path resolution relies on specific directory structures. Let's check if this could cause issues in different environments:


🏁 Script executed:

#!/bin/bash
echo "Checking canvas.js paths..."
echo "From process.cwd():"
# Check if the relative paths would resolve correctly from different potential working directories
cd $(git rev-parse --show-toplevel)
echo "From repository root:"
[ -d "packages/design-core/dist/assets" ] && echo "✓ packages/design-core/dist/assets exists" || echo "✗ packages/design-core/dist/assets does not exist"
[ -d "node_modules/@opentiny/tiny-engine/dist/assets" ] && echo "✓ node_modules/@opentiny/tiny-engine/dist/assets exists" || echo "✗ node_modules/@opentiny/tiny-engine/dist/assets does not exist"
cd packages/build
echo "From packages/build:"
[ -d "../design-core/dist/assets" ] && echo "✓ ../design-core/dist/assets exists" || echo "✗ ../design-core/dist/assets does not exist"
[ -d "../../node_modules/@opentiny/tiny-engine/dist/assets" ] && echo "✓ ../../node_modules/@opentiny/tiny-engine/dist/assets exists" || echo "✗ ../../node_modules/@opentiny/tiny-engine/dist/assets does not exist"

Length of output: 998


Enhance Error Handling for Canvas.js Asset Copy Plugin

The plugin is well-structured and flexible in its configuration options, which is great. However, since the verification output shows that the expected asset directories (both for the design core and tiny engine) aren’t found from the repository or build paths, it would be wise to guard against missing files. Please consider adding error handling that checks whether the resolved asset file exists before attempting to copy it. This will ensure clearer warnings and help prevent unexpected behavior during the build process. For example:

 export function vitePluginCopyCanvas(options = {}) {
   let { useSource, assetsDir } = options
   if (!assetsDir) {
     assetsDir = useSource
       ? path.resolve(process.cwd(), '..', 'packages/design-core/dist/assets/canvas.js')
       : path.resolve(process.cwd(), 'node_modules/@opentiny/tiny-engine/dist/assets/canvas.js')
   }
+  // Check if the canvas.js file exists for better error reporting
+  try {
+    require('fs').accessSync(assetsDir, require('fs').constants.R_OK)
+  } catch (err) {
+    console.warn(`Warning: Canvas.js asset not found at ${assetsDir}. Build will continue but canvas may not function correctly.`)
+  }
   return [
     ...viteStaticCopy({
       targets: [
         {
           src: assetsDir,
           dest: 'assets/'
         }
       ]
     })
   ]
 }
  • Verify that the resolved paths for canvas.js are correct in your working environment.
  • Add a file existence check to improve error reporting if the asset isn’t present.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function vitePluginCopyCanvas(options = {}) {
let { useSource, assetsDir } = options
if (!assetsDir) {
assetsDir = useSource
? path.resolve(process.cwd(), '..', 'packages/design-core/dist/assets/canvas.js')
: path.resolve(process.cwd(), 'node_modules/@opentiny/tiny-engine/dist/assets/canvas.js')
}
return [
...viteStaticCopy({
targets: [
{
src: assetsDir,
dest: 'assets/'
}
]
})
]
}
export function vitePluginCopyCanvas(options = {}) {
let { useSource, assetsDir } = options
if (!assetsDir) {
assetsDir = useSource
? path.resolve(process.cwd(), '..', 'packages/design-core/dist/assets/canvas.js')
: path.resolve(process.cwd(), 'node_modules/@opentiny/tiny-engine/dist/assets/canvas.js')
}
// Check if the file exists - for better error reporting
try {
require('fs').accessSync(assetsDir, require('fs').constants.R_OK)
} catch (err) {
console.warn(`Warning: Canvas.js asset not found at ${assetsDir}. Build will continue but canvas may not function correctly.`)
}
return [
...viteStaticCopy({
targets: [
{
src: assetsDir,
dest: 'assets/'
}
]
})
]
}

@1degrees 1degrees closed this Apr 28, 2025
@1degrees 1degrees reopened this Apr 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants