Glossary overview

JS: Bun

Bun.build — это полноценный бандлер (как webpack/vite), он:

  • понимает ES-модули (import/export)
  • резолвит зависимости из node_modules
  • tree-shaking (убирает неиспользуемый код)
  • обрабатывает весь граф зависимостей и склеивает в один файл

Например, Gulp сам по себе не умеет поддеижвать модульный js — но можно подключить rollup или webpack как плагин. Но это по сути gulp как обёртка над другим бандлером — смысла мало. Проще уже сразу использовать rollup/webpack/vite/bun напрямую без gulp.

А они умеют собирать стили? rollup/webpack/vite/bun?

Да, все умеют, но по-разному:

Webpack — умеет всё из коробки через лоадеры:
import ‘./styles.scss’; // прямо в JS
sass-loader + css-loader + MiniCssExtractPlugin → отдельный .css файл.

Vite — тоже умеет SCSS из коробки, просто ставишь sass и импортируешь:
import ‘./styles.scss’;

Rollup — через плагины (rollup-plugin-scss), чуть сложнее.

Bun — умеет CSS/SCSS частично. CSS-модули поддерживает, но SCSS нативно не компилирует — нужен внешний sass. Поэтому мы и делаем отдельную функцию buildStyles() вручную.

Если бы это был обычный сайт, а не WordPress-плагин — взял бы Vite, он сейчас стандарт де-факто. Но для WordPress Vite сложнее интегрировать (нужен dev-сервер, HMR и т.д.),
поэтому наш подход с Bun для JS + sass напрямую для SCSS — разумный компромисс.

Пример как теперь можно писать js

import Swiper from 'swiper';

const affiliateModels = () => {

	document.addEventListener('click', (e) => {
		const btn = e.target.closest('.sprm-btn-js');
		if (!btn) return;

		const section = btn.closest('[data-ajax]');
		if (!section) return;

		const fd = new FormData();
		fd.append('action', 'sprm_affiliate_link');

		fetch(section.dataset.ajax, { method: 'POST', body: fd })
			.then((r) => r.json())
			.then((data) => {
				if (data.success && data.data.url) {
					window.open(data.data.url, '_blank', 'noopener,noreferrer');
				}
			});
	});

	document.querySelectorAll('.sprm-review-slider__photos.swiper').forEach((el) => {
		const swiper = new Swiper(el, {
			slidesPerView: 1,
			spaceBetween: 0,
			loop: true,
			allowTouchMove: true,
			grabCursor: true,
			preloadImages: false,
			watchSlidesProgress: true,
		});

		const prev = el.querySelector('.sprm-photos__arrow--prev');
		const next = el.querySelector('.sprm-photos__arrow--next');

		if (prev) prev.addEventListener('click', () => swiper.slidePrev());
		if (next) next.addEventListener('click', () => swiper.slideNext());
	});
};

export default affiliateModels;