Розбір планів розробки OpenCart 4.2

OpenCartBot - 03.10.2026
Розбір планів розробки OpenCart 4.2

29 вересня 2026 року в репозиторії opencart/opencart відкрили обговорення #15713 з планом розробки гілки 4.2.x.x. Ініціатором виступив один із колабораторів проєкту, і за чотири дні до нього долучилися розробники, які принесли ідеї про оптимізацію розміру дистрибутива, підрахунки викликів jQuery і пропозиції щодо адмінки. План ще не затверджений, і саме зараз вирішується, з якими змінами доведеться жити власникам магазинів і авторам розширень в наступному релізі.

Ми давно розробляємо модулі для OpenCart і дивимось на цей план очима людини, якій доведеться адаптувати під нову версію власний каталог розширень. Тому давайте розбиремо кожну пропозицію: що вона змінить у базі даних, фронтенді та адмінці, де вона створює ризики для сумісності і яке рішення, на мою думку, є найбільш виваженим.

Знову зміни в структурі бази даних

Перший пункт плану — наблизити схему бази 4.2 до гілки main. Йдеться про три таблиці: oc_product_tag для тегів товарів, oc_manufacturer_description для багатомовних описів виробників і oc_product_code для товарних ідентифікаторів на кшталт GTIN, EAN чи MPN. Для розробника модулів це добра новина: чим менше розбіжностей між гілками, тим простіше підтримувати один код для кількох версій ядра.

Найцікавіше питання стосується oc_product_code. У main ця таблиця вже вдруге змінилася порівняно з 4.1 і має автоінкрементний первинний ключ product_code_id. В обговоренні запропоновано складений ключ PRIMARY KEY (product_id, identifier_id), за тією ж схемою, за якою давно працюють oc_product_description та oc_product_attribute. Я цілком підтримую цей варіант.

Причина криється в тому, як OpenCart зберігає товар. Метод editProduct у моделі адмінки традиційно видаляє всі пов'язані записи і вставляє їх заново. З автоінкрементним ключем товар із трьома кодами після тисячі збережень спалить три тисячі значень лічильника, і кожен код отримуватиме новий product_code_id. Переповнення INT UNSIGNED із його 4,29 млрд значень магазину не загрожує. Реальна проблема проявиться в модулях: фід для Google Merchant Center, синхронізація з 1С чи імпорт від постачальника, що зберігає посилання на product_code_id, втрачає зв'язок після кожного редагування товару в адмінці.

Складений ключ дає стабільну адресу запису і дозволяє писати атомарні INSERT ... ON DUPLICATE KEY UPDATE без попереднього SELECT. Обмеження «один код кожного типу на товар» відповідає вимогам GS1 і маркетплейсів, де одна товарна позиція має один GTIN. Рідкісні випадки з кількома штрихкодами для різних пакувань чесніше оформлювати через варіанти товару, які в четвертій версії вже є.

Оновлення до jQuery 4.0.0

Друга пропозиція — оновити jQuery з 3.7.1 до 4.0.0. Фінальний реліз вийшов 17 січня 2026 року, майже десять років після попередньої мажорної версії. Команда бібліотеки прибрала підтримку IE 10 і старіших браузерів, видалила застарілі методи і скоротила розмір файлу на понад 3 КБ у gzip. Додалася підтримка Trusted Types, корисна для магазинів із суворою Content Security Policy.

Для розширень це означає цілком конкретну роботу. Зникли jQuery.trim, jQuery.isArray, jQuery.parseJSON, jQuery.now і jQuery.isFunction, з прототипу прибрали push, sort і splice. Події focus і blur тепер спрацьовують у порядку за специфікацією W3C, і це може змінити поведінку валідації форм у модулях оформлення замовлення. Автоматичне перетворення AJAX-запитів на JSONP також видалене.

У коді, перенесеному з OpenCart 2.x і 3.x, найчастіше трапляються $.trim і $.isArray. Їх знаходить звичайний пошук по проєкту, заміна на String.prototype.trim() та Array.isArray() займає хвилини. Складніше з патчами OCMOD, які вставляють JavaScript у чужі шаблони: такий код видно лише після застосування модифікаторів.

Рішення перейти на jQuery 4 саме в 4.2 я вважаю правильним. Відкладання оновлення на версію 4.3 лише збільшить обсяг застарілого коду в екосистемі. До плану я б додав опцію підключення jQuery Migrate у режимі розробника. Цей плагін пише в консоль попередження про кожен видалений виклик і дає авторам модулів готовий перелік правок прямо на живому магазині.

Або взагалі без jQuery

Підрахунок викликів у коді 4.x показує, що вітрина залежить від jQuery зовсім незначно. Уся важка залежність зосереджена в адмінці.

Частина

Файлів із jQuery

Викликів $()

Плагіни на jQuery

catalog

25

552

magnific-popup

admin

187

2958

jquery-ui, flot, jqvmap, magnific-popup

У каталозі використовуються лише базові методи: .on(), .find(), .closest(), addClass, $.ajax. Анімацій fadeIn, slideUp чи animate, які зазвичай найскладніше переписати на чистий JavaScript, у коді вітрини немає жодної. Bootstrap 5 працює без jQuery від самого релізу, тож єдиним залежним компонентом вітрини залишається magnific-popup для галереї товару. Переписавши ці 25 файлів, стандартна тема перестане вантажувати кожному відвідувачу близько 88 КБ мініфікованого коду бібліотеки.

У маркетплейсі OpenCart тисячі розширень розраховані на те, що jQuery вже є на сторінці. Якщо ядро прибере бібліотеку одним рішенням, автори модулів почнуть вкладати власні копії jQuery в архіви. На магазині з десятком розширень це дасть три-чотири версії бібліотеки на одній сторінці, конфлікти обробників подій і результат гірший за поточний.

Найрозумнішим варіантом вважаю компроміс, до якого в підсумку дійшла дискусія. В 4.2 ядро переписує власний код вітрини на чистий JavaScript невеликими пакетами (акаунт, оформлення, картка товару, CMS), jQuery 4.0.0 лишається доступним для розширень, повне видалення переноситься на 4.3. Адмінка залишається на jQuery надовго: jquery-ui, flot і jqvmap не мають готових замінників, і вага скриптів для кількох менеджерів магазину ніяк не впливає на SEO чи конверсію.

Після того як ядро вітрини перестане залежати від jQuery, відкриється можливість підключати бібліотеку з атрибутом defer або лише тоді, коли її запитує розширення. Для цього вистачить прапорця залежності у виклику додавання скрипту в документ. Магазин без старих модулів одразу отримає чисту сторінку, і це помітно покращить показники Core Web Vitals на мобільних пристроях.

JavaScript у шаблонах Twig і сумісність з OCMOD

Окремо обговорювалася ідея винести весь inline-JavaScript із файлів .twig у зовнішні .js. Для архітектури це правильний вектор на перспективу, і запроваджувати його варто після 4.2. Для такої позиції є дві причини.

Перша причина технічна. У блоках <script> майже всіх шаблонів вітрини є змінні Twig: перекладені рядки, URL маршрутів, код мови. Рядок на кшталт {{ text_shipping_method|escape('js') }} у статичному файлі просто перестане працювати. Спочатку треба вирішити, як дані потраплятимуть у скрипт: через data-атрибути, глобальний об'єкт конфігурації, рендеринг .js-файлів через Twig або клієнтський шаблонізатор. Останній варіант найнебезпечніший, бо переносить рендеринг у браузер і втрачає серверний рендеринг для цих блоків, що б'є по індексації та швидкості першого відображення.

Друга причина стосується екосистеми. Майже жоден магазин не працює на «чистому» OpenCart, і чимало модулів через OCMOD чи VQMOD дописують свій код прямо в inline-скрипти шаблонів кошика чи оформлення. Якщо цей код переїде в common.js, кожне розширення патчитиме один і той самий файл, і перший же конфлікт двох модифікаторів зламає вітрину цілком.

На мою думку, для 4.3 найкраще підходить поєднання трьох рішень. Дані конкретного елемента передаються через data-атрибути, переклади і URL рендеряться сервером в один глобальний об'єкт конфігурації, логіка живе в файлах і генерує власні події через нативний CustomEvent. Розширення тоді підписується на подію додавання товару в кошик чи зміни способу доставки і жодного чужого файлу не патчить. Додатковий бонус — можливість увімкнути сувору Content Security Policy без 'unsafe-inline', що зараз для OpenCart фактично недосяжно. Така система потребує ретельного проєктування і документації подій, тому її варто закладати в наступну версію разом із видаленням jQuery.

Зайві мегабайти у зібрці і спільна тека assets

Тека upload у поточній четвертій гілці важить близько 62 МБ, і від 15 до 20 МБ із них ніколи не завантажується браузером. Для магазину на віртуальному хостингу, куди файли досі часто заливають по FTP, кожна тисяча зайвих файлів означає довше встановлення і більше шансів на обірване завантаження. Аудит дистрибутива показав такі джерела зайвої ваги:

  • Source map файли: 37 штук загальним обсягом 9,9 МБ, значна частина лежить у теці install, яка видаляється після встановлення.
  • Шість збірок Bootstrap JS у кожній теці, з яких шаблони підключають лише bootstrap.bundle.min.js на 79 КБ. Разом із map-файлами це близько 2,4 МБ на теку і 4,8 МБ для admin та catalog разом.
  • Демонстраційна тека flot/examples: 65 файлів обсягом 1,2 МБ, перенесена з оригінального дистрибутива бібліотеки.
  • Font Awesome обсягом 784 КБ, дубльований тричі в admin, catalog і install.

З текою flot/examples і збірками bootstrap.esm усе очевидно: ESM-версії призначені для збирачів на кшталт Webpack чи Vite, яких OpenCart не використовує, і їх можна прибирати без жодних наслідків. SCSS-джерела Bootstrap 5.3.8 треба залишити в ядрі, бо на них спираються сторонні теми і модулі з власним оформленням. До цього ж блоку належить дрібна і дуже корисна правка: вітрина віддає немініфікований bootstrap.css, який генерує scssphp. Один рядок $scss->setOutputStyle(\ScssPhp\ScssPhp\OutputStyle::COMPRESSED); у catalog/controller/startup/sass.php зменшує CSS на кожній сторінці магазину.

Щодо source map файлів я бачу рішення, яке задовольнить обидва табори. Файли лишаються в репозиторії для розробників, рядок *.map export-ignore у .gitattributes виключає їх із ZIP-архівів, які GitHub формує для релізів. Той самий механізм застосовний до демо-файлів і тестів.

Проблему дублів розв'язує спільна тека для бібліотек, доступна з admin і catalog. У гілці main вона вже існує під назвою upload/assets, і для 4.2 я б взяв саме цей варіант: модулям не доведеться перевивчати шляхи вдруге після переходу на наступну мажорну версію. Підхід із текою public за зразком Laravel вимагає змінити корінь сайту на сервері. На багатьох дешевих хостингах document root фіксований, тому таку реорганізацію логічно залишити для OpenCart 5.

Перенесення бібліотек у спільну теку зачепить модулі, які підключають jQuery, Bootstrap чи Font Awesome за жорстко прописаним шляхом на кшталт catalog/view/javascript/jquery/. Таких розширень на ринку чимало, і їхнім авторам варто перевірити шаблони заздалегідь.

Дерево категорій для великих каталогів

Єдина пропозиція щодо інтерфейсу адмінки стосувалася категорій: менеджер із перетягуванням гілок мишею і дерево чекбоксів у формі товару з фільтром за назвою. Аргументи на користь цієї ідеї серйозні: OpenCart дозволяє необмежену вкладеність категорій, і в каталозі на 600 категорій із п'ятьма рівнями вкладеності стандартний список із полем sort_order перетворюється на головоломку.

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

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

З перетягуванням є нюанс, про який рідко згадують. OpenCart зберігає ієрархію ще й у таблиці oc_category_path, де для кожної категорії записано весь ланцюжок предків. Перенесення гілки з сотнею нащадків потребує перерахунку шляхів для всієї гілки і скидання кешу SEO URL. У драг-енд-дроп інтерфейсі це має відбуватися в одній транзакції, інакше випадковий рух мишею залишить каталог у нецілісному стані. Тому менеджер категорій я би спершу випустив окремим розширенням і переносив у ядро після обкатки на реальних великих каталогах.

Підготовка модулів до OpenCart 4.2

План розробки ще змінюватиметься, і частина напрямів уже зрозуміла: jQuery 4.0.0, схема бази з main і поступове звільнення вітрини від jQuery. Розробнику розширень вигідно почати адаптацію до виходу релізу, поки підтримка не засипана зверненнями клієнтів після оновлення. Я для себе визначив такий порядок дій:

  1. Пройтися пошуком по коду та XML-файлах OCMOD і замінити $.trim, $.isArray, $.parseJSON, $.isFunction, $.now на нативні аналоги. Ці заміни сумісні і з jQuery 3.7.1, тож їх можна випускати в поточних версіях модулів.
  2. Підняти тестову копію магазину на 4.1, підмінити jQuery на 4.0.0 разом із jQuery Migrate і пройти кошик, оформлення та картку товару з відкритою консоллю браузера.
  3. Прибрати з шаблонів жорстко прописані шляхи до jQuery, Bootstrap і Font Awesome. Після переїзду бібліотек у спільну теку такі посилання дадуть 404.
  4. Новий JavaScript писати на чистому JS із fetch, querySelector і classList. Код без залежності від jQuery без переробок переживе і 4.2, і 4.3.
  5. У модулях фідів і синхронізації адресувати товарні коди парою product_id і тип ідентифікатора. Зберігати product_code_id у власних таблицях небезпечно при будь-якому варіанті фінальної схеми.
  6. Мінімізувати OCMOD-патчі всередину чужих <script>. Обробники, підв'язані з власного файлу через делегування подій на document, переживають переписування шаблонів ядра значно краще.

Обговорення відкрите для всіх, і думка розробників розширень там реально впливає на рішення - саме аргумент про тисячі модулів у маркетплейсі відклав повне видалення jQuery до 4.3. Якщо ваш модуль залежить від структури oc_product_code, шляхів до бібліотек чи inline-скриптів оформлення, саме зараз найкращий момент описати свій сценарій у треді на GitHub.


Рекомендовані модулі


Інші статті