Как получить CSS в виде строки из версированной сборки 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>

В конфигурации вашего веб-пакета вы говорите о файлах JS ("только для app.js"), но ваша проблема заключается в управлении версиями css, верно? У вас есть запись для css?

qdequippe 12.10.2018 11:25

На самом деле я не уверен, как именно работает webpack, но я следовал руководствам Symfony. В моем файле email.js есть это: import '../css/email.scss';

user4521733 12.10.2018 11:28

На самом деле я не понимаю вашей проблемы, почему управление версиями влияет на ваш шаблон электронной почты?

qdequippe 12.10.2018 11:45
{{ source('@public/build/email.css') }} - это функция Twig, которая загружает содержимое файла в текущий шаблон. Поскольку я хочу использовать SCSS в своем шаблоне электронной почты, мне нужно настроить процесс сборки. source, кроме asset, не использует файл manifest.json для преобразования чистого пути в версионный путь. Так думает Твиг, файл можно найти по адресу build/email.css, тогда как на самом деле он находится по адресу build/email.sdf312321.css.
user4521733 12.10.2018 12:50

Я думаю, вам нужно использовать asset () вместо source () {{asset ('build / email.css')}} symfony.com/doc/current/frontend/encore/…

Vyctorya 12.10.2018 14:44

Конечно, но вы не можете сделать это с электронной почтой. Для правильной работы электронной почты требуется встроенный CSS. Я уже думал о создании настраиваемой функции, такой как asset_embed, но я надеялся, что смогу добиться этого из коробки, не создавая некоторых настраиваемых основных функций.

user4521733 12.10.2018 15:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
3
6
1 067
3

Ответы 3

Не уверен, что это хорошее решение, но вы можете попробовать добавить плагин ignore-loader и сопоставить файлы, чтобы игнорировать их, например в webpack.config.js игнорировать все файлы .css

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

Хотя это не отвечает на вопрос в вашем заголовке, это позволит вам получить 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 из каждого файла. Однако имейте в виду, что пути в этом файле - это пути, доступные в Интернете, а не локальные пути, поэтому вам может потребоваться изменить их.

Конечно, вы можете делать все это только в 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));
}

Спасибо!. К счастью, я нашел очень похожий обходной путь через несколько дней после публикации этого вопроса, добавленный к моему вопросу.

user4521733 01.04.2019 16:45

Круто, да, я подумал, что вы, наверное, уже разобрали это :) Надеюсь, ответ поможет кому-то другому

Rich Court 02.04.2019 11:04

Также вы можете отключить управление версиями для определенного файла css (email.css) с помощью Encore множественная конфигурация

Что-то вроде этого в вашем 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>

Другие вопросы по теме