Webpack Encore - управление CSS JavaScript image

В официальной документации по symfony нет чёткого решения как работать с изображениями, приведены примеры только для js css. Поэтому шустрим англоязычные ресурсы и пишем своё руководство.

Структура ресурсов

Для удобства представим следующуу структуру ресурсов

-/web/
----/assets_dev/
----/assets_prod/

Где /assets_dev/ папка с ресурсами для разработки, именно в этой папке лежат все js скрипты css файлы и img изображения.  /assets_prod/ - папка с компилированными и упакованными ресурсами.

Шаг 1 - установка Webpack Encore

yarn add @symfony/webpack-encore --dev

После установки нужно добавить каталог node_modules в .gitignore

Шаг 2 - в папке /assets_dev/ создадим файл app.css - главный файл для css ресурсов. Содержимое файла может быть такое.

//app.css
/* Тут можно определить свои стили или подключить собственные библиотеки */
@import "css/app.css";
@import "css/form.css";
@import url("http://fonts.googleapis.com/css?family=Open+Sans&subset=latin,cyrillic-ext");

Шаг 3 - в папке /assets_dev/ создадим файл app.js - главный файл для js ресурсов. Содержимое файла может быть такое.

//app.js
const imagesContext = require.context('.', true, /\.(png|jpg|jpeg|gif|ico|svg|webp)$/);
imagesContext.keys().forEach(imagesContext);

import './js/fn.js';
import './core/fn.js';

Шаг 4 - создаём инструкции для плагина Webpack Encore - файл webpack.config.js

//webpack.config.js
/* подключим плагин */
var Encore = require('@symfony/webpack-encore');

Encore
   /* Установим путь куда будет осуществляться сборка */
   .setOutputPath('web/assets_prod/')// работает
   
   /* Укажем web путь до каталога web/build */
   .setPublicPath('/assets_prod')

   /* Каждый раз перед сборкой будем очищать каталог /build */
   .cleanupOutputBeforeBuild()

   /* --- Добавим основной JavaScript в сборку --- */
   .addEntry('scripts', './web/assets_dev/app.js')
   /* Добавим наш главный файл ресурсов в сборку */
   .addStyleEntry('styles', './web/assets_dev/app.css')
   /* Включим поддержку sass/scss файлов */
    
   .createSharedEntry('vendor', [
        // создаём общую библиотеку для js и css файлов 
        // этот CSS больше *не* будет включён в page1.css или page2.css
        './web/assets_dev/js/jquery.ui/jquery-ui.css',
        './web/assets_dev/css-bootstrap/bootstrap.min.css',
        './web/assets_dev/js/prism/prism.css',
		'./web/assets_dev/js/jquery/1.4.4/jquery.js',
		'./web/assets_dev/js/jquery.ui/jquery-ui-1.8.6.custom.min.js',
    ])
	
	Encore.configureFilenames({
		images: '[path][name].[ext]',
		fonts: '[path][name].[ext]'
	})
	;
module.exports = Encore.getWebpackConfig();

// для дополнительной обработки можно использовать
// if (Encore.isProduction()) {}

Шаг 5 - запуск сборки

./node_modules/.bin/encore dev
./node_modules/.bin/encore production
yarn run encore dev
yarn run encore dev --watch
yarn run encore production

При запуске через yarn run encore - происходит интуитивная подсветка вывода. Отличие сборки dev от production в том что при production - происходит минификация ресурсов

Шаг 6 - подключение ресурсов к проекту

Шаг 6.1 - создание глобальной переменной для переключения между dev и production в файле config.yml

#config.yml
twig:
    globals:
        # global_dev_mode: 'dev'
        global_dev_mode: 'prod'

Шаг 6.2 - разметка файла base.html.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>{% block title %}Welcome!{% endblock %}</title>
		{% block stylesheets %}
			{% if global_dev_mode == 'dev' %}
				<link rel="stylesheet" href="{{ asset('/assets_dev/css-bootstrap/bootstrap.min.css') }}">
				<link rel="stylesheet" href="{{ asset('/assets_dev/css/app.css') }}">
				<link rel="stylesheet" href="{{ asset('/assets_dev/css/form.css') }}">
			{% else %}
				<link rel="stylesheet" href="{{ asset('assets_prod/vendor.css') }}" />
				<link rel="stylesheet" href="{{ asset('assets_prod/styles.css') }}">
			{% endif %}
        {% endblock %}
        <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
    </head>
    <body>
		<div class="center_block">
			{% block body %}{% endblock %}
		</div>
		{% block javascripts %}
			{% if global_dev_mode == 'dev' %}
				<script src="{{ asset('/assets_dev/js/jquery/1.4.4/jquery.js') }}"></script>
				<script src="{{ asset('/assets_dev/js/jquery.ui/jquery-ui-1.8.6.custom.min.js') }}"></script>
				<script src="{{ asset('/assets_dev/js/fn.js?v=4') }}"></script>
			{% else %}
				<!-- первые два файла должны быть включены в каждую страницу -->
				<script src="{{ asset('assets_prod/manifest.js') }}"></script>
				<script src="{{ asset('assets_prod/vendor.js') }}"></script>
				<script src="{{ asset('assets_prod/scripts.js') }}"></script>
			{% endif %}
        {% endblock %}
    </body>
</html>

 

Источники:
Webpack Encore - управление CSS и JavaScript - [official]
Managing CSS and JavaScript - [official][en]
Symfony: Webpack Encore — плагин для управления ресурсами - [habr]
How to manage static images with Symfony’s Webpack Encore
How are static assets handled - [github]
Missing assets in Twig autocompletation when using manifest.json and Webpack-Encore versioning - [github]
Webpack encore docs - [official] [github]
Symfony Webpack Encore, Multiple JS/CSS Files to one file - [stackoverflow]
symfony 4 webpack + encore handle image in template more info- [ stackoverflow]
Handling Images with the CopyPlugin