GrapesJS / GrapesJS/mjml

BUG: mj-image flickers / reloads on every non-src attribute or style edit

Open
#431 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
716
Forks
251
PR merge metrics
No merged PRs in 30d

Description

### GrapesJS version

- [x] I confirm to use the latest version of GrapesJS

### GrapesJS MJML version

- [x] I confirm to use the latest version of GrapesJS MJML

### What browser are you using?

Chrome (latest) — the root cause is at the DOM level, so it isn't browser-specific.

### Reproducible demo link

https://stackblitz.com/github/geonsang-jo/grapesjs-mjml-image-reconcile-demo/tree/fix/canvas-height-and-visible-flicker?file=src%2Fmain.ts&startScript=dev&view=preview

### Describe the bug

**How to reproduce the bug?**
1. Add an `mj-image` to the canvas.
2. Edit any of its **non-`src`** attributes or styles — `alt`, `title`, `padding`, `width`, alignment — in the Trait/Style Manager.
3. Watch the rendered image.

The StackBlitz demo above is a side-by-side **Baseline vs. Patched** repro (use *Toggle width once* / *Start auto toggle*); the page reports whether the rendered `` DOM object was replaced.

**What is the expected behavior?**
Editing a non-`src` attribute or style updates the image in place; the already-loaded image stays visible and does not reload.

**What is the current behavior?**
The `` visibly flickers on every edit — it briefly disappears, then reloads and repaints.

Root cause: the MJML view re-renders a component by rebuilding its entire subtree on every `change:attributes` / `change:src` event:

```js
// src/components/index.ts — coreMjmlView.render()
this.el.innerHTML = this.getTemplateFromMjml();
```

Because the whole subtree is replaced, the existing `` node is destroyed and recreated each time, so the browser drops the decoded image and refetches and repaints it — even when `src` did not change.

Confirmed on `grapesjs-mjml@1.0.8`.

> I searched the existing issues: the closest are #385 (wrapper losing its children on a property edit) and #389 (redo not restoring an image), which share the same "an edit triggers a destructive full re-render" mechanism, but neither reports the `mj-image` flicker/reload specifically. I have an `mj-image`-scoped DOM-reconciliation fix ready and will open a PR.

### Code of Conduct

- [x] I agree to follow this project's Code of Conduct

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.