如何在Gulp+Juice邮件生成流程中提取并重注入深色模式媒体查询
Gulp+Juice邮件生成器深色模式样式丢失问题解决
问题背景
使用Gulp搭配Juice构建HTML邮件时,深色模式相关样式被意外移除:
- 标准深色模式媒体查询
@media (prefers-color-scheme: dark)的内容未被保留 - Outlook专属的属性选择器样式(如
[data-ogsc] body { background-color: #2a2c2e !important; }、[data-ogsb] body { background-color: #2a2c2e !important; })从最终HTML中消失
现有配置代码如下:
tasks/juice.js
"use strict"; module.exports = function(gulp, $, fromRoot) { var juice = require('gulp-juice-concat'); var removeUnused = require("gulp-email-remove-unused-css"); gulp.task("juice", function(done) { gulp .src(fromRoot("dist") + "/*.html") .pipe( juice({ applyStyleTags: true, applyLinkTags: true, removeStyleTags: true, preservePseudos: true, preserveMediaQueries: true, applyAttributesTableElements: true, preserveImportant: true, preserveFontFaces: true, applyWidthAttributes: true }) ) .pipe( removeUnused({ whitelist: [ ".External*", ".ReadMsgBody", ".yshortcuts", ".Mso*", "#outlook", "#preheader", "#MessageViewBody", "#body", "u", "[data-ogsc]", "[data-ogsb]" ], }) ) .pipe(gulp.dest(fromRoot("dist"))); done(); }); };
gulpfile.js
'use strict'; const gulp = require('gulp'), fromRoot = require('../utils/from-root'), $ = require('gulp-load-plugins')({ pattern: '*', config: '../../package.json', scope: ['dependencies', 'devDependencies', 'peerDependencies'], rename: { 'lodash.assign': 'assign' } }); $.loadSubtasks('./tasks/**/*.js', $, fromRoot); gulp.task('dist', gulp.series('clean:dist', 'sass:dist', 'src:dist', 'juice'));
解决方案
在juice任务之后新增一个自定义任务,提取需要保留的深色模式样式并重新注入HTML的<head>标签中:
步骤1:安装依赖
npm install cheerio --save-dev
步骤2:添加inject-dark-styles任务
修改tasks/juice.js,在现有代码后添加以下任务:
// 新增注入深色模式样式的任务 gulp.task("inject-dark-styles", function(done) { const fs = require('fs'); const cheerio = require('cheerio'); const cssPath = fromRoot("dist") + "/styles.css"; // 替换为你的编译后CSS文件路径 // 读取原始CSS内容 const cssContent = fs.readFileSync(cssPath, 'utf8'); // 提取深色模式媒体查询和Outlook专属样式 const darkMediaQuery = cssContent.match(/@media \(prefers-color-scheme: dark\) {[\s\S]*?}/)?.[0] || ''; const outlookStyles = cssContent.match(/\[data-ogsc\].*?|\[data-ogsb\].*?/g)?.join('\n') || ''; const injectedStyles = `${darkMediaQuery}\n${outlookStyles}`; if (!injectedStyles) { done(); return; } return gulp .src(fromRoot("dist") + "/*.html") .pipe($.through2.obj(function(file, enc, cb) { const $ = cheerio.load(file.contents.toString()); // 在head末尾插入样式标签 $('head').append(`<style type="text/css">${injectedStyles}</style>`); file.contents = Buffer.from($.html()); cb(null, file); })) .pipe(gulp.dest(fromRoot("dist"))); });
步骤3:更新dist任务
修改gulpfile.js中的dist任务,将新任务加入执行序列:
gulp.task('dist', gulp.series('clean:dist', 'sass:dist', 'src:dist', 'juice', 'inject-dark-styles'));
关键说明
- 确保
cssPath指向正确的编译后CSS文件(如果使用Sass,通常是dist目录下的编译产物) - 正则表达式会精准提取深色模式媒体查询块和Outlook专属的属性选择器样式
- 通过
cheerio操作DOM,确保样式被插入到<head>中,避免被Juice再次处理 - 即使
removeUnused插件误删样式,重新注入的方式能保证最终HTML包含所需的深色模式代码
内容的提问来源于stack exchange,提问作者Kornelius
相关产品推荐
相关产品推荐

