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

Symfony 如何从版本化的网页包Encore构建中获取CSS作为字符串,以便在电子邮件中使用它?,symfony,twig,webpack-encore,Symfony,Twig,Webpack Encore,我用细枝渲染电子邮件 要将CSS直接导入电子邮件,我执行了以下操作: <style> {{ source('@public/build/email.css') }} </style> 更新:我的解决方案 我编写了一个简单的细枝函数来解决这个问题: <?php namespace App\Twig; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; class AppExtensi

我用细枝渲染电子邮件

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

<style>
    {{ source('@public/build/email.css') }}
</style>
更新:我的解决方案 我编写了一个简单的细枝函数来解决这个问题:

<?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.');
    }

}

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

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

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

Webpack Encore在构建文件夹中创建一个名为“entrypoints.js”的文件。您需要使用
$decodedFile=json\u decode(file\u get\u contents('your/build/folder/entrypoints.json'))获取并解析该文件

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

在获得这些内容之后,您需要对该数组中的每个文件执行
file\u get\u contents($yourCssFile)
,以从每个文件中获取CSS。请记住,该文件中的路径是可通过web访问的路径,而不是本地路径,因此您可能需要对它们进行操作

当然,您只能在PHP中完成所有这些,因此您需要创建一个细枝扩展,以允许您在模板中使用它

我很惊讶在Symfony没有更好的方法来做到这一点——如果有,我很想知道

完整代码(用于细枝扩展方法,或只需将
$css
传递到模板中):

$files=json\u decode(文件获取内容('your/build/folder/entrypoints.json'))
->入口点
->电子邮件
->css
;
$css='';
foreach($files作为$file){
$css.=file_get_contents('your/build/folder/')。basename($file));
}

您还可以使用禁用特定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\u 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>

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

在您的网页配置中,您谈论的是JS文件(“仅适用于app.JS”),但您的问题在于css版本控制,对吗?你有css的条目吗?嗯,实际上我不确定webpack到底是如何工作的,但我遵循了symfony的教程。我的
email.js
文件中包含以下内容:
import'../css/email.scss'
事实上,我不理解您的问题,为什么版本控制会影响您的电子邮件模板?
{source('@public/build/email.css')}
是一个将文件内容加载到当前模板中的细枝函数。因为我想在我的电子邮件模板中使用SCS,所以我需要配置一个构建过程
source
,而不是
asset
,不使用manifest.json文件将干净路径转换为版本化路径。因此Twig认为,该文件可以在
build/email.css
找到,而实际上它位于
build/email.sdf3121.css
我认为您需要使用asset()而不是source(){asset('build/email.css')}谢谢!。幸运的是,在发布这个问题几天后,我发现了一个非常类似的解决方法,添加到我的问题中。酷,是的,我想你现在可能已经把它分类了:)希望这个答案能帮助其他人
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>