Building MJML email templates with Gulp
This is the second post in the series about building email templates with MJML and deploying them on AWS. In the previous post, we learned about MJML and Handlebars.js for creating cross-browser email templates with dynamic content. In this post, I will show you how you can script the building process of MJML emails and prepare them for upload on AWS.
Let's do a quick recap. In the previous post, I created a simple mail template in MJML:
<mjml>
<mj-body>
<mj-text>Hello {{firstname}}</mj-text>
<mj-text>Here are some movie recommendations for you:</mj-text>
<mj-text>
<ul>
{{#each movies}}
<li>{{this}}</li>
{{/each}}
</ul>
</mj-text>
</mj-body>
</mjml>
When running through the online MJML editor, we get an HTML output that should look decent in most browsers. This has been a manual process so far, so let's automate it to limit the amount of work we need to do when needing changes. I'll use Gulp for this example, but there's an MJML CLI that you can use if you prefer another scripting language. Start by creating a new npm project and install the necessary npm packages:
npm init
npm install gulp
npm install gulp-json-editor
npm install gulp-mjml
npm install html-minifier
npm install mjml
During the npm init
command just accept the defaults or input values if you prefer something else. The next step is to produce HTML from the MJML file. When uploaded as an AWS template we need to produce the following template.json
file:
{
"Template": {
"TemplateName": "test",
"SubjectPart": "The subject",
"HtmlPart": ""
}
}
The HTML output from the MJML processor will need to go into the HtmlPart
property in the JSON file. The Gulp script needs to:
- Convert MJML to HTML.
- Minify the HTML.
- Insert the minified HTML in
template.json
.
Here's a script that will do all steps:
const gulp = require('gulp');
const mjml = require('gulp-mjml');
const mjmlEngine = require('mjml');
const htmlMinify = require('html-minifier');
const jsonEditor = require('gulp-json-editor');
let htmlContents = null;
gulp.task('mjml-to-html', function () {
return gulp.src('./test.mjml')
.pipe(mjml(mjmlEngine))
.on('data', function(file) {
const buferFile = Buffer.from(htmlMinify.minify(file.contents.toString(), {
collapseWhitespace: true,
minifyCSS: true,
processConditionalComments: true
}));
htmlContents = '"' + buferFile.toString() + '"';
return file.contents = buferFile;
})
.pipe(gulp.dest('./html'))
});
gulp.task('update-json', function () {
return gulp.src('./template.json')
.pipe(jsonEditor(function(json) {
json.Template.HtmlPart = htmlContents;
return json;
}))
.pipe(gulp.dest('./'))
});
gulp.task('run', gulp.series('mjml-to-html', 'update-json'));
The Gulp script has three tasks. The mjml-to-html
task will run the MJML processor and output minified HTML to a folder named html
. Outputting the HTML to a file only acts as additional debug information and can be removed if you prefer. The update-json
task will take the in-memory minified HTML and insert it into the template.json
file. Finally, the run
task will run both tasks in the right order.
Run the script using Gulp:
gulp run
You should see that the template.json
file now contains a minified HTML email template:
{
"Template": {
"TemplateName": "test",
"SubjectPart": "The subject",
"HtmlPart": "\"<!doctype html><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><head><title></title><!--[if !mso]><!--><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><!--<![endif]--><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style type=\"text/css\">#outlook a{padding:0}body{margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}table,td{border-collapse:collapse;mso-table-lspace:0;mso-table-rspace:0}img{border:0;height:auto;line-height:100%;outline:0;text-decoration:none;-ms-interpolation-mode:bicubic}p{display:block;margin:13px 0}</style><!--[if mso]><noscript><xml><o:officedocumentsettings><o:allowpng><o:pixelsperinch>96</o:pixelsperinch></o:officedocumentsettings></xml></noscript><![endif]--><!--[if lte mso 11]><style type=\"text/css\">.mj-outlook-group-fix{width:100%!important}</style><![endif]--><!--[if !mso]><!--><link href=\"https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700\" rel=\"stylesheet\" type=\"text/css\"><style type=\"text/css\">@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);</style><!--<![endif]--><style type=\"text/css\"></style><style type=\"text/css\"></style></head><body style=\"word-spacing:normal\"><div style=\"\"><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\">Hello {{firstname}}</div><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\">Here are some movie recommendations for you:</div><div style=\"font-family:Ubuntu,Helvetica,Arial,sans-serif;font-size:13px;line-height:1;text-align:left;color:#000\"><ul>{{#each movie}}<li>{{this}}</li>{{/each}}</ul></div></div></body></html>\""
}
}
The JSON file is ready for upload in AWS. In the next post, I'll finish the series. There we will automatically build the MJML template using the script from this post, and upload it on AWS.