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;