yarn mjml 5.0.0-beta.1
v5.0.0-beta.1

6 hours ago

Upgrade Guide

These are the changes users need to actively consider when upgrading to the MJML 5 beta from MJML 4.x (and early MJML 5 alphas):

Highlights

  • Replaced legacy html-minifier and js-beautify with htmlnano + cssnano. [breaking change]
  • Added templating syntax sanitization (runs before PostCSS and is restored afterwards)
  • Safer, stricter handling of mj-include and ignoreIncludes [breaking change]
  • Restructured outer HTML: the <body> tag is now driven by mj-body, not the global skeleton. [breaking change]
  • mjml-browser build/minification pipeline updated
  • Better attribute consistency across components (including more flexible border-radius). [breaking change]
  • Migration helper removed [breaking change]
  • Updated toolchain: Node 20/22/24 in CI. Removed Node 16/18 [breaking change]

HTML/CSS minification & formatting

What changed

  • HTML minification now uses htmlnano instead of html-minifier.
  • CSS minification now uses cssnano presets wired via mjml-core.
  • Minification options can be added via .mjmlconfig.js

Impact [potential breaking changes]

  • Generated HTML is more aggressively minified. If you rely on exact formatting (e.g. diffing raw HTML, parsing by regex, or checking snapshots), you may see changes.
  • Some obscure html-minifier specific options used in custom tooling will no longer apply; options are now expressed as htmlnano/cssnano configs.
  • Template tags may error in PostCSS (see Template syntax handling and sanitization below)
  • Fixes this issue: #2589

What to do

  • Review any automation that assumes pretty‑printed HTML (tests, diffs, CI snapshot comparisons).
  • If you previously passed minify/beautify flags or custom minifier options, re‑map them to the new htmlnano/cssnano config.

Notes

  • cssnano uses lite preset by default. Due to this issue: #2919. default preset can be used if your fonts don’t contain numerals

More detail: (#2858 (comment))


Template syntax handling and sanitization (PostCSS)

What changed

  • Template syntax (e.g. {{ }}) is now sanitized before PostCSS and with syntax restored post-processing.

Impact

  • A CssSyntaxError error will occur when applying CSS minification to files with some template syntax
  • Fixes this issue: #2858 (comment)

What to do

  • If you use a templating engine on top of MJML (Handlebars, Liquid, Twig, etc.), run your existing templates and visually verify output.
  • Pay special attention to templates that put templating markers in CSS or style attributes.

More detail: (#2858 (comment))


Includes are more locked down

What changed

  • ignoreIncludes / allowIncludes (CLI) defaults and behavior have changed to be more secure. Includes are ignored by default
  • A new includePath option is introduced to explicitly control where includes can be loaded from outside of a templates filePath
  • Support MJML, HTML and CSS includes only

Impact [potential breaking changes]

  • Includes are ignored by default, you will need to explicitly allow them
  • Projects that relied on implicit include behavior (e.g. loading templates from arbitrary paths without explicit configuration) may now fail, warn, or simply skip includes.
  • In locked‑down environments (containers, CI, hosting), path resolution for includes may change and require configuration.
  • Fixes this issue: #2589

What to do

  • Audit usage of mj-include and any config that touches ignoreIncludes / allowIncludes.
  • Explicitly configure includePath (and related options) in your .mjmlconfig or CLI usage to match your desired include directories (see docs)
  • Expect safer, stricter defaults; don’t rely on includes working without explicit configuration.

More detail: (#2858 (comment))


mj-body and skeleton structure

What changed

  • The <body> HTML tag is now generated under mj-body instead of a global skeleton file.
  • Added id attribute to mj-body
  • mj-body attributes have been refactored:
    • class attribute is applied to the body tag rather than the child div
    • background-color removed from body, applies to child div only

Impact [potential breaking changes]

  • If you rely on the exact skeleton (where <body> lived, what attributes were on it), this structure is now different.
  • External CSS that relies on the specific placement of the class may no longer apply
  • Fixes this issue: #2396

What to do

  • Re‑check any tooling that injects or manipulates the outer HTML skeleton around MJML output.
  • Re‑verify any CSS relating to class or background-color attributes that were applied to mj-body

Notes


Browser bundle / build scripts

What changed

  • mjml-browser build/minification pipeline has been updated to use new minifiers

Why

  • New minifiers were not compatible

Impact

  • If you import mjml-browser directly or depended on its legacy build scripts, behavior and bundle size/shape might change.
  • Bundle size down from 1.22M to 1.04M

What to do

  • Re‑build any tools using mjml-browser and verify they still load, minify, and run as expected.

Attributes & layout consistency

What changed

  • All border-radius attributes now accept a string, previously this was inconsistent across components. Allows more flexible input
  • Updated the inner-padding attributes of mj-hero and fixed an Outlook issue with width/padding

Impact [potential breaking changes]

  • For some components, border-radius values are less strict
  • inner-padding for mj-hero is now applied to all clients, not just Outlook

What to do

  • Visual regression‑test focusing on all instances border-radius and mj-hero's inner-padding

Migration helper removal

What changed

  • The standalone mjml-migrate tool and associated noMigrateWarn option are removed.

Impact [potential breaking changes]

  • You can no longer rely on MJML 5 to automatically migrate very old MJML syntax (3.x/early 4.x) on the fly.

What to do

  • If you still have legacy MJML, migrate those templates with MJML 4 tooling before moving the project to MJML 5, or update them manually.

Node.js version support

What changed

  • CI now runs against Node LTS 20, 22 and 24; older Node versions are effectively deprecated/unsupported.

Impact [potential breaking changes]

  • MJML 5 may not work (or will be untested) on Node 16/18 in the long term.

What to do

  • Plan to run MJML 5 on Node 20, 22 or 24 in CI and production.

Full Changelog: v5.0.0-alpha.11...v5.0.0-beta.1

Don't miss a new mjml release

NewReleases is sending notifications on new releases.