如何从版本化的Webpack Encore构建中获取CSS作为字符串,以在电子邮件中使用它?

时间:2018-10-12 09:11:56

标签: symfony twig webpack-encore

我使用Twig渲染电子邮件。

要直接将CSS导入电子邮件,我执行了以下操作:

<style>
    {{ source('@public/build/email.css') }}
</style>

这在开发环境中效果很好,但在资产已版本化(例如email.dfase343.css)的生产环境中无效。

是否可以仅对此单个文件禁用版本控制?

我的webpack.config.js基本知识:

var Encore = require('@symfony/webpack-encore');

    Encore
        .setOutputPath('public/build/')
        .setPublicPath('/build')
        .addEntry('app', './assets/js/app.js')
        .addEntry('email', './assets/js/email.js')
        .cleanupOutputBeforeBuild()
        .enableBuildNotifications()
        .enableSourceMaps(!Encore.isProduction())

        .enableVersioning(Encore.isProduction()) // --> only for app.js

        .enableSassLoader()
    ;

module.exports = Encore.getWebpackConfig();

更新:我的解决方案

我写了一个简单的Twig函数来解决这个问题:

<?php

namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class AppExtension extends AbstractExtension
{

    private $assetsManager;

    public function __construct(\Symfony\Component\Asset\Packages $assetsManager)
    {
        $this->assetsManager = $assetsManager;
    }

    public function getFunctions()
    {
        return array(
            new TwigFunction('asset_embed', array($this, 'assetEmbed')),
        );
    }

    public function assetEmbed($uri, $package = null)
    {
        $file = __DIR__.'/../../public'.$this->assetsManager->getUrl($uri, $package);

        if (is_file($file)) {
            return file_get_contents($file);
        }

        throw new \Twig_Error('File "'.$file.'" not found.');
    }

}

用法

<style>
    {{ asset_embed('build/email.css') }}
</style>

3 个答案:

答案 0 :(得分:1)

虽然这不能回答标题中的问题,但可以让您从webpack生成的文件中获取CSS并包含在电子邮件中。

Webpack Encore在您的构建文件夹中创建一个名为“ entrypoints.js”的文件。您将要使用$decodedFile = json_decode(file_get_contents('your/build/folder/entrypoints.json'));获取并解析该文件。

然后可以将该文件的内容作为对象来遍历。所需的文件路径将位于$decodedFile->entrypoints->email->css之类,它将为您提供该条目的CSS文件数组(可以有多个文件,例如,如果您使用.splitEntryChunks()方法在您的webpack.config.js文件中。

掌握了这一点之后,您将需要对该数组中的每个文件执行file_get_contents($yourCssFile),以从每个文件中获取CSS。请记住,尽管该文件中的路径是可通过Web访问的路径,而不是本地路径,所以您可能需要操纵它们。

当然,您只能在PHP中完成所有操作,因此您需要创建一个Twig扩展名以允许您在模板中使用它。

令我惊讶的是,在Symfony中没有更好的方法可以做到这一点-我很想知道是否有这种方法。

完整代码(要在Twig扩展方法https://symfony.com/doc/current/templating/twig_extension.html中使用,或仅将$css传递到模板中)

$files = json_decode(file_get_contents('your/build/folder/entrypoints.json'))
    ->entrypoints
    ->email
    ->css
;

$css = '';

foreach ($files as $file) {
    $css .= file_get_contents('your/build/folder/') . basename($file));
}

答案 1 :(得分:0)

不确定这是否是一个好的解决方案,但是您可以尝试添加ignore-loader plugin并匹配文件以忽略它们,例如webpack.config.js中的文件忽略所有.css文件

module.exports = {
  // ... other configurations ...
  module: {
    loaders: [
      { test: /\.css$/, loader: 'ignore-loader' }
    ]
  }
};

答案 2 :(得分:0)

您还可以使用Encore multiple config禁用某些CSS文件(email.css)的版本控制

webpack.config.js中类似的内容:

Encore
    .setOutputPath('public/build/email')
    .setPublicPath('/build/email')
    .cleanupOutputBeforeBuild()
    .disableSingleRuntimeChunk()
    .enableBuildNotifications()
    .enableSassLoader()
    .addStyleEntry('emails', './assets/css/email.scss')
    .enableSourceMaps(!Encore.isProduction())
;

然后webpack_encore.yaml

webpack_encore:
    output_path: '%kernel.project_dir%/public/build'
    builds:
        frontend: '%kernel.project_dir%/public/build'
        emails: '%kernel.project_dir%/public/build/email'

最后是您的电子邮件模板:

    <style>
        {{ source('@public/build/email.css') }}
    </style>