Просунута конфігурація Webpack

Дата оновлення перекладу 2024-05-27

Просунута конфігурація Webpack

Узагальнено, Encore генерує конфігурацію Webpack, яка використовується у вашому файлі webpack.config.js. Encore не підтримує додавання усіх опцій конфігурації Webpack, так як багато з них ви з легкістю можете додати самі.

Наприклад, уявіть, що вам потрібно автоматично розвʼязати нове розширення. Щоб зробити це, змініть конфігурацію після її вилучення з Encore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// webpack.config.js

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

// ... тут вся конфігурація Encore

// отримайте конфігурацію, а потім змініть ії!
const config = Encore.getWebpackConfig();

// додайте розширення
config.resolve.extensions.push('json');

// ескпортуйте фінальну конфігурацію
module.exports = config;

Але будьте обережні, щоб випадково не перевизначити ніяку конфігурацію з Encore:

1
2
3
4
5
6
7
8
// webpack.config.js
// ...

// ДОБРЕ - змінює масив config.resolve.extensions
config.resolve.extensions.push('json');

// ПОГАНО - заміняє будь-які розширення, додані Encore
// config.resolve.extensions = ['json'];

Конфігурація опцій спостереження та опитування

Encore надає метод configureWatchOptions() для конфігурації Опцій спостереження при запуску encore dev --watch або encore dev-server:

1
2
3
4
5
Encore.configureWatchOptions(function(watchOptions) {
    // включити опитування та перевіряти зміни кожні 250 мс
    // опитування корисні при запуску Encore всередині віртуальної машини
    watchOptions.poll = 250;
});

Визначення множини конфігурацій Webpack

Webpack підтримує передачу масиву конфігурацій, які обробляються паралельно. Webpack Encore містить в собі обʼєкт reset(), який дозволяє перезапустити стан поточної конфігурації, щоб побудувати нову:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// визначити першу конфігурацію
Encore
    .setOutputPath('public/build/first_build/')
    .setPublicPath('/build/first_build')
    .addEntry('app', './assets/app.js')
    .addStyleEntry('global', './assets/styles/global.scss')
    .enableSassLoader()
    .autoProvidejQuery()
    .enableSourceMaps(!Encore.isProduction())
;

// побудувати першу конфігурацію
const firstConfig = Encore.getWebpackConfig();

// Встановити унікальне імʼя для конфігурації (знадобиться пізніше!)
firstConfig.name = 'firstConfig';

// перезапустити Encore, щоб побудувати другу конфігурацію
Encore.reset();

// визначити другу конфігурацію
Encore
    .setOutputPath('public/build/second_build/')
    .setPublicPath('/build/second_build')
    .addEntry('mobile', './assets/mobile.js')
    .addStyleEntry('mobile', './assets/styles/mobile.less')
    .enableLessLoader()
    .enableSourceMaps(!Encore.isProduction())
;

// побудувати другу конфігурацію
const secondConfig = Encore.getWebpackConfig();

// Встановити унікальне імʼя для конфігурації (знадобиться пізніше!)
secondConfig.name = 'secondConfig';

// експортувати фінальну конфігурацію в якості масиву множини конфігурацій
module.exports = [firstConfig, secondConfig];

При запуску Encore, обидві конфігурації будуть побудовані паралельно. Якщо ви бажаєте будувати конфігурації окремо, передайте опцію --config-name:

1
2
3
4
5
# якщо ви використовуєте менеджер пакетів Yarn
$ yarn encore dev --config-name firstConfig

# якщо ви використовуєте менеджер пакетів npm
$ npm run dev -- --config-name firstConfig

Далі, перевизначіть каталоги виведення кожної побудови:

1
2
3
4
5
6
# config/packages/webpack_encore.yaml
webpack_encore:
    output_path: '%kernel.project_dir%/public/default_build'
    builds:
        firstConfig: '%kernel.project_dir%/public/first_build'
        secondConfig: '%kernel.project_dir%/public/second_build'

Також визначіть маніфести ресурсів для кожної побудови:

1
2
3
4
5
6
7
8
# config/packages/assets.yaml
framework:
    assets:
        packages:
            first_build:
                json_manifest_path: '%kernel.project_dir%/public/first_build/manifest.json'
            second_build:
                json_manifest_path: '%kernel.project_dir%/public/second_build/manifest.json'

Нарешті, використайте третій необовʼязковий параметр функцій encore_entry_*_tags(), щоб вказати, яку побудову використати:

1
2
3
4
5
6
7
{# Використовуючи файл entrypoints.json, розташований в ./public/first_build #}
{{ encore_entry_script_tags('app', null, 'firstConfig') }}
{{ encore_entry_link_tags('global', null, 'firstConfig') }}

{# Використовуючи файл entrypoints.json, розташований в ./public/second_build #}
{{ encore_entry_script_tags('mobile', null, 'secondConfig') }}
{{ encore_entry_link_tags('mobile', null, 'secondConfig') }}

Уникнення пропуску CSS під час відображення декількох шаблонів

Коли ви відображаєте два або більше шаблонів в одному запиті, наприклад, два emailʼи, вам слід викликати метод reset() в інтерфейсі EntrypointLookupInterface. Для цього впровадьте в інтерфейс EntrypointLookupInterface:

1
2
3
4
5
6
7
public function __construct(EntrypointLookupInterface $entryPointLookup) {}

public function send() {
    $this->twig->render($emailOne);
    $this->entryPointLookup->reset();
    $this->render($emailTwo);
}

Якщо ви використовуєте декілька конфігурацій Webpack (наприклад, одну для адміністратора і одну для email), вам потрібно буде впровадити правильний сервіс EntrypointLookupInterface. Скористайтеся наступною командою, щоб знайти потрібний сервіс:

1
2
3
4
5
6
7
8
9
$ php bin/console console debug:container entrypoint_lookup

# Ви побачите результат, схожий на цей:
Оберіть один з наступним сервісів для відображення інформації про нього:
[0] webpack_encore.entrypoint_lookup_collection
[1] webpack_encore.entrypoint_lookup.cache_warmer
[2] webpack_encore.entrypoint_lookup[_default]
[3] webpack_encore.entrypoint_lookup[admin]
[4] webpack_encore.entrypoint_lookup[email]

У цьому прикладі конфігурацією, пов'язаною з конфігурацією email, є та, що має назву webpack_encore.entrypoint_lookup[email].

Щоб впровадити цей сервіс у ваш клас, скористайтеся опцією bind:

1
2
3
4
5
# config/services.yaml
services:
    _defaults
        bind:
            Symfony\WebpackEncoreBundle\Asset\EntrypointLookupInterface $entryPointLookupEmail: '@webpack_encore.entrypoint_lookup[email]'

Тепер ви можете впровадити ваш сервіс у ваш клас:

1
2
3
4
5
6
7
public function __construct(EntrypointLookupInterface $entryPointLookupEmail) {}

public function send() {
    $this->twig->render($emailOne);
    $this->entryPointLookupEmail->reset();
    $this->render($emailTwo);
}

Генерування обʼєкта конфігурації Webpack без використання інтерфейсу командного рядку

Зазвичай ви використовуватимете ваш файл webpack.config.js, викликаючи Encore з інтерфейсу командного рядку. Але іноді, доступ до згенерованої конфігурації Webpack може знадобитися інструментам, які не використовують Encore (наприклад, виконавцю тестів, на кшталт Karma).

Проблема в тому, що якщо ви спробуєте згенерувати цей обʼєкт конфігурації Webpack без використання команди encore, ви зіштовхнетеся з наступною помилкою:

1
Error: Encore.setOutputPath() be called yet because the runtime environment doesn't appear to be configured. Make sure you're using the encore executable or call Encore.configureRuntimeEnvironment() first if you're purposely not calling Encore directly.

Причиною цього повідомлення є те, що Encore необхідно знати декілька речей перед тим, як створити обʼєкт конфігурації, і найважливіша з них - яке цільове середовище.

Щоб вирішити цю проблему, ви можете використати configureRuntimeEnvironment. Цей метод повинен бути викликаний з файлу JavaScript до вимоги webpack.config.js.

Например:

1
2
3
4
5
6
7
const Encore = require('@symfony/webpack-encore');

// Встановити середовище виконання
Encore.configureRuntimeEnvironment('dev');

// Вилучити обʼєкт конфігурації Webpack
const webpackConfig = require('./webpack.config');

Якщо необхідно, ви також можете передати цьому методу всі опції, які ви зазвичай використовували б з інтерфейсу командного рядку:

1
2
3
4
5
6
Encore.configureRuntimeEnvironment('dev-server', {
    // Ті ж опції, які ви б використовували з утилітою
    // CLI, з іменами в camelCase.
    https: true,
    keepPublicPath: true,
});

Повний контроль над правилами завантажувачів

Метод configureLoaderRule() надає прямий шлях для конфігурації правил завантажувачів Webpack (module.rules, див. Конфігурація).

Це метод нижнього рівня. Всі ваші модифікації будуть застосовані прямо перед відправкою правил завантажувачів у Webpack. Це означає, що ви можете перевизначити конфігурацію за замовчуванням надану Encore, що може щось зламати. Будьте обережні при використанні.

Одним зі способів застосування може бути сконфігурувати eslint-loader, щоб контролювати ще й файли Vue. Наступний код є еквівалентним:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Вручну
const webpackConfig = Encore.getWebpackConfig();

const eslintLoader = webpackConfig.module.rules.find(rule => rule.loader === 'eslint-loader');
eslintLoader.test = /\.(jsx?|vue)$/;

return webpackConfig;

// Використовуючи Encore.configureLoaderRule()
Encore.configureLoaderRule('eslint', loaderRule => {
    loaderRule.test = /\.(jsx?|vue)$/
});

return Encore.getWebpackConfig();
Наступні завантажувачі можна сконфігурувати за допомогою configureLoaderRule():
  • javascript (псевдонім js)
  • css
  • images (але замість нього використовуйте configureImageRule())
  • fonts (але замість нього використовуйте configureFontRule())
  • sass (псевдонім scss)
  • less
  • stylus
  • svelte
  • vue
  • eslint
  • typescript (псевдонім ts)
  • handlebars

Конфігурація псевдонимів під час імпорту або запиту модулів

Опція Webpack resolve.alias дозволяє створювати псевдоніми для спрощення
import або require певних модулів (наприклад, шляхом псевдонімізації загальновживаних папок src/). У Webpack Encore ви можете скористатися цією опцією за допомогою методу addAliases():

1
2
3
4
Encore.addAliases({
    Utilities: path.resolve(__dirname, 'src/utilities/'),
    Templates: path.resolve(__dirname, 'src/templates/')
})

З конфігурацією вище ви тепер зможете імпортувати певні модулі більш точно:

1
2
-import Utility from '../../utilities/utility';
+import Utility from 'Utilities/utility';

Виключення деяких залежностей з пакетів виведення

Опція Webpack externals дозволяє запобігти пакуванню певних імпортованих
пакетів і натомість отримати ці зовнішні залежності під час виконання. Ця можливість здебільшого корисна для розробників бібліотек JavaScript, тому вам вона, ймовірно, не знадобиться.

У Webpack Encore ви можете використовувати цю опцію за допомогою методу addExternals():

1
2
3
4
5
6
7
// це не включатиме jQuery та React у пакети виведення, згенеровані 
// за допомогою Webpack Encore. Вам потрібно буде завантажити ці залежності самостійно
// (наприклад, за допомогою тегу `<script>`), щоб змусити додаток або веб-сайт працювати.
    Encore.addExternals({
    jquery: 'jQuery',
    react: 'react'
})