Prakk
@Prakk
Frontend-разработчик

Как ускорить сборку проекта?

Структура проекта
63aabbcdc728e455110528.png

gulpfile.js на pastebin

gulpfile.js
const { src, dest, series, parallel, watch, lastRun } = require('gulp');
const path = require('path');
const pug = require('gulp-pug');
const sass = require('gulp-sass')(require('sass'));
const clean = require('gulp-clean');
const browserSync = require('browser-sync').create();
const autoprefixer = require('gulp-autoprefixer');
const csso = require('gulp-csso');
const sourcemaps = require('gulp-sourcemaps');
 
const cleanBuildDir = () => {
  return src('build/', {
    read: false,
    allowEmpty: true
  })
    .pipe(clean())
};
 
const pugHandler = () => {
  return src(['src/pages/**/*.pug', '!src/pages/layout.pug'], {since: lastRun(pugHandler)})
    .pipe(pug({
      pretty: true,
      basedir: path.join(__dirname, '/src')
    }))
    .pipe(dest('build/pages/'))
    .pipe(browserSync.reload({stream: true}));
};
 
const scssHandler = () => {
  return src(['src/pages/**/*.scss'], {base: './src', since: lastRun(scssHandler)})
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(sourcemaps.write())
    .pipe(dest('build/'))
    .pipe(browserSync.reload({stream: true}));
};
 
const scssBuildHandler = () => {
  return src(['src/pages/**/*.scss'], {base: './src'})
    .pipe(sass().on('error', sass.logError))
    .pipe(autoprefixer())
    .pipe(csso())
    .pipe(dest('build/'));
};
 
const jsHandler = () => {
  return src('src/pages/**/*.js')
    .pipe(dest('build/pages/'))
    .pipe(browserSync.reload({stream: true}));
};
 
const imagesHandler = () => {
  return src('src/images/**/*.{png,jpg,jpeg,webp,svg}', {
    allowEmpty: true,
    since: lastRun(imagesHandler)
  })
    .pipe(dest('build/images'))
    .pipe(browserSync.reload({stream: true}));
};
 
const fontsHandler = () => {
  return src('src/fonts/*.{woff,woff2}')
    .pipe(dest('build/fonts/'))
    .pipe(browserSync.reload({stream: true}));
};
 
const serve = () => {
  browserSync.init({
    server: 'build/',
    open: false,
    tunnel: 'livelib-testy'
  });
  
  watch(
    [
      'src/pages/**/*.pug', 
      'src/components/**/*.pug'
    ],
    {
      usePolling: true
    },
    pugHandler
  );
  
  watch(
    [
      'src/pages/**/*.scss', 
      'src/components/**/*.scss', 
      'src/scss/*.scss'
    ], 
    {
      usePolling: true
    },
    scssHandler
  );
  
  watch(
    'src/**/*.js', 
    {
      usePolling: true
    },
    jsHandler
  );
  
  watch(
    'src/images/*.{png,jpg,jpeg,webp,svg}', 
    {
      usePolling: true
    },
    imagesHandler
  );
  
  watch(
    'src/fonts/*.{woff,woff2}', 
    {
      usePolling: true
    },
    fontsHandler
  );
};
 
exports.build = series(
  cleanBuildDir,
  parallel(
    pugHandler,
    scssBuildHandler,
    jsHandler,
    imagesHandler,
    fontsHandler
  )
);
 
exports.default = series(
  cleanBuildDir,
  parallel(
    pugHandler,
    scssHandler,
    jsHandler,
    imagesHandler,
    fontsHandler
  ),
  serve
);


В проекте 120+ страниц, что приводит к большому времени полной сборки проекта. Сейчас изменение разметки/стилей страницы или компонента приводит к полной пересборке, что занимает много времени.

Пробовал решить проблему с помощью встроенного решения gulp.src({since: lastRun('taskName')}), а так же gulp-cache и emitty.
Всё это не работает из-за того, что папка src/components не попадает в поток обработки, мы просто не можем отслеживать изменения в ней.

Возможно стоит как-то изменить структуру папок или есть ещё какой-то способ решить мою проблему?
  • Вопрос задан
  • 117 просмотров
Пригласить эксперта
Ответы на вопрос 1
@joseffie
Front-end developer
Моё решение данной проблемы:

Инициализируем переменную watching (или любое другое название, это не играет значения) и присваиваем ей значение false, затем внутри таска Pug инициализируем плагин emitty:

const emittyPug = emitty.setup('src', 'pug', { makeVinylFile: true })


Затем возвращаем промис, внутри которого сканируем глобальную переменную emittyPugChangedFile (она будет нужна, чтобы потом присвоить ей необходимое значение в gulp.watch()). Также не забудьте функции таска Pug указать аргумент-коллбэк (в данном случае done), так как Gulp может жаловаться на отсутствие асинхронного завершения.

return new Promise(() => {
  emittyPug.scan(global.emittyPugChangedFile).then(() => {
    .src()
    ...
    .pipe(gulpif(watch, emittyPug.filter(global.emittyPugChangedFile)))
    ...
    dest()
  })

  done()
});


Затем в начале вашей функции serve присвойте переменной watching значение true и напишите следующий gulp.watch() для Pug:

watch(['src/pages/**/*.pug', 'src/components/**/*.pug'], pugHandler).on('all', (event, filepath) => {
  global.emittyPugChangedFile = event === 'unlink' ? undefined : filepath; 
});


После этих действий сборка должна стать инкрементальной. Также вы можете всё это рассмотреть на примере моей собственной сборки: gulpfile, Pug-таск, watch.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы