Hugo + Gulp

Матеріал з Wiki.Zina
Версія від 11:45, 20 березня 2020, створена Romych (обговорення | внесок)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

←Hugo

В чем проблема

[ред. | ред. код]

Сложность использования Hugo в связке с Gulp в том, что нам нужно выполнять два процесса watch для наблюдения за изменениями файлов и автоматической сборки (компиляции) файлов сайта:

  • Gulp следит за файлами Sass *.scss и компилирует их в CSS (а также минифицирует, добавляет source maps и т.п.), плюс аналогично обрабатывает JavaScript файлы, собирает спрайты, оптимизирует изображения;
  • Hugo следит за готовыми файлами *.css и контентом сайта и собирает их в готовый статичный сайт.

Кроме того, и Gulp, и Hugo умеют запускать LiveReload сервер, который показывает сайт в браузере и автоматически обновляет окно браузера при изменениях на сайте.

Но делают все это они каждый по-своему, а нам нужно объединить оба процесса.

Подготовка

[ред. | ред. код]

Установите Gulp:

npm init --yes
bower init
bower install --save bootstrap-sass
cp bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss src/sass/
npm install --save-dev gulp gulp-sass gulp-autoprefixer gulp-uglify gulp-rigger gulp-sourcemaps gulp.spritesmith gulp-plumber gulp-watch browser-sync child_process run-sequence del

Замечание: последнюю команду можно выполнить в сокращенном виде npm install --save-dev, если предварительно положить в корневую директорию проекта файл gulpfile.js с инициализацией нужных пакетов, на основе которого команда npm init --yes сформирует файл package.json с перечнем пакетов.

Установите Hugo:

hugo new site --format yaml --force .

Добавьте в config.yaml:

publishdir = "html"

Структура директорий

[ред. | ред. код]

Разберемся c директориями:

  • src — директории sass, js, sprite, fonts. Здесь вручную редактируются файлы Sass, JavaScript и изображений, а затем обрабатываются Gulp'ом и в обработанном виде складываются в директорию static.

  • static — директории css, img, js, fonts — сюда Gulp кладет обработанные файлы, а затем их использует Hugo при сборке статичного сайта.
  • layouts — шаблоны сайта для Hugo.
  • content — файлы сайта для Hugo: страницы в виде файлов .md и разделы сайта в виде директорий.

  • html — готовый статичный сайт. Hugo берет содержимое папок static, layouts и content и собирает сайт в папку html.

В процессе работы над сайтом нам нужно:

  1. Наблюдать за директорией src и собирать Gulp'ом в директорию static
  2. Наблюдать за директориями static, layouts и content и делать:
    1. run_hugo — собирать сайт в папку html
    2. livereload — обновить окно браузера

gulpfile.js

[ред. | ред. код]

С помощью этого gulpfile.js работа над проектом Hugo сводится к запуску в корне проекта команды gulp, после которой начинается магия: сначала очищается папка html, затем компилируются CSS и JS, запускается hugo и сразу собирает html-файлы сайта, затем запускается сервер BrowserSync и в браузере на порту 3131 открывает локальный хост проекта (должен быть создан в Apache), после чего запускается процесс watch — наблюдение за изменяемыми файлами в проекте и автоматическая сборка проекта и обновление окна браузера.

Иногда, если Hugo выдает ошибки, бывает полезно прервать gulp по команде Ctrl-C, очистить html-файлы командой gulp clear и затем запустить hugo, чтобы посмотреть более подробно, какую именно ошибку он возвращает.

'use strict';

var gulp = require('gulp');
var sass = require('gulp-sass');
var prefixer = require('gulp-autoprefixer');
var uglify = require('gulp-uglify');
var rigger = require('gulp-rigger');
var sourcemaps = require('gulp-sourcemaps');
var spritesmith = require('gulp.spritesmith');
var plumber = require('gulp-plumber');
var watch = require('gulp-watch');
var browserSync = require('browser-sync').create();
var exec = require('child_process').execSync;
var runSequence = require('run-sequence').use(gulp); // Последовательное выполнение задач
var del = require('del');

// var reload = browserSync.reload;

var reload_timeout = null;

function reload() {
  if(reload_timeout) {
    return;
  }
  reload_timeout = setTimeout(function() {
    browserSync.reload();
    reload_timeout = null;
  }, 0);
}

var rootDir   = process.cwd();
var hugoDir   = rootDir + '/hugo';
var srcDir    = rootDir + '/src';
var htmlDir   = rootDir + '/html';
var staticDir = rootDir + '/static';
var path = {
  src: {   // Где брать исходники
    style:  srcDir + '/sass/style.scss',
    sprite: srcDir + '/sprite/*.png',
    js:     srcDir + '/js/main.js',
    img:    srcDir + '/img/**/*.{png,gif,jpg,jpeg}',
    fonts:  srcDir + '/fonts/**/*.otf',
  },
  static: { // Куда складывать после сборки готовые файлы для Gulp
    style:  staticDir + '/css/',
    sprite: staticDir + '/img/',
    js:     staticDir + '/js/',
    img:    staticDir + '/img/',
    fonts:  staticDir + '/fonts/',
  },
  watch: { // За изменением каких файлов будем наблюдать
    src_style:    srcDir  + '/sass/**/*.scss',
    src_js:       srcDir  + '/js/**/*.js',
    src_sprite:   srcDir  + '/sprite/**/*.png',
    // hugo:         hugoDir + '/(static|layouts)/**/*',
    hugo_config:  rootDir + '/config.yaml',
    hugo_layouts: hugoDir + '/layouts/**/*',
    hugo_static:  rootDir + '/static/**/*',
    hugo_content: rootDir + '/content/**/*',
    public_html:  htmlDir + '/**/*.html',
    public_css:   htmlDir + '/css/*.css',
    public_js:    htmlDir + '/js/*.js',
    public_img:   htmlDir + '/img/**/*.{png,gif,jpg,jpeg}',
    public_fonts: htmlDir + '/fonts/**/*.otf',
  }
};

// console.log(path); // Вывести список всех путей

// Компилирование Sass в CSS
gulp.task('style', function () {
  return gulp.src(path.src.style) // Возьмем наш основной Sass файл 'style.scss'
  .pipe(sourcemaps.init()) // Инициализируем SourceMap
  .pipe(sass({ // Скомпилируем Sass в CSS
    includePaths: [ // Включим папки для поиска файлов Bootstrap
      rootDir + '/src/sass/',
      rootDir + '/bower_components/bootstrap-sass/assets/stylesheets/',
    ],
    // outputStyle: 'compressed', // Минифицируем CSS
  }))
  .pipe(prefixer({ // Добавим вендорные префиксы
    browsers: [
      'last 2 versions',
      '> 1%'
    ]
  }))
  // .pipe(sourcemaps.write()) // Добавим SourceMap
  .pipe(gulp.dest(path.static.style)) // Положим готовый 'style.css' в build
});

// Сборка JavaScript файлов
gulp.task('js', function () {
  return gulp.src(path.src.js) // Возьмем наш основной файл 'main.js'
  .pipe(rigger()) // Включим в него все импортируемые файлы
  .pipe(sourcemaps.init()) // Инициализируем SourceMap
  .pipe(uglify()) // Сожмем полученный JS
  .pipe(sourcemaps.write()) // Добавим SourceMap
  .pipe(gulp.dest(path.static.js)) // Положим готовый 'main.js' в build
});

// Сборка CSS спрайтов
gulp.task('sprite', function () {
  var spriteData = gulp.src(rootDir + '/src/sprite/*.png')
  .pipe(spritesmith({
    imgName: 'sprite.png',
    cssName: 'sprite.css'
  }));
  spriteData.img.pipe(gulp.dest(path.static.img));
  spriteData.css.pipe(gulp.dest(path.static.style));
  return spriteData;
});

gulp.task('img', function() {
  return gulp.src(path.src.img) // Возьмем наши файлы изображений
  .pipe(gulp.dest(path.static.img)); // и положим в build
});

gulp.task('fonts', function() {
  return gulp.src(path.src.fonts) // Возьмем файлы шрифтов
  .pipe(gulp.dest(path.static.fonts)); // и положим в build
});

// gulp.task('copyfonts', function() {
//    gulp.src('./bower_components/font-awesome/fonts/**/*.{ttf,woff,eof,svg}')
//    .pipe(gulp.dest('./fonts'));
// });

// Сборка статичного сайта средствами Hugo
gulp.task('hugo', function() {
  // process.chdir(hugoDir);
  exec('hugo', {encoding: 'utf-8'});
  // process.chdir(rootDir);
});

// Очистка папок static и html
gulp.task('clear', function() {
  return del([htmlDir + '/*', path.static.style, path.static.js]).then(paths => {
    // console.log('Deleted content of folders: \n' + htmlDir + '\n' + path.static.style + '\n' + path.static.js)
    console.log('Deleted content of folders:');
    console.log(' ' + htmlDir);
    console.log(' ' + path.static.style);
    console.log(' ' + path.static.js);
  })
});

// Сборка проекта (запуск нескольких задач)
gulp.task('build', function() {
  return runSequence([
    // 'sprite',
    // 'img',
    // 'fonts',
    'style',
    'js'],
    'hugo',
    function() {console.log('Сборка сайта завершена.');}
  );
});

// Отслеживание изменений файлов и запуск соответствующих задач
gulp.task('watch', function() {
  watch([path.watch.src_style], function(event, cb) {
    gulp.start('style');
  });
  watch([path.watch.src_js], function(event, cb) {
    gulp.start('js');
  });
  watch([path.watch.src_sprite], function(event, cb) {
    gulp.start('sprite');
  });
  // watch([path.watch.src_img], function(event, cb) {
  //   gulp.start('img');
  // });
  // watch([path.watch.hugo_static], function(event, cb) {
  //   gulp.start('hugo');
  // });
  watch([path.watch.hugo_config], function(event, cb) {
    gulp.start('hugo');
  });
  watch([path.watch.hugo_layouts], function(event, cb) {
    gulp.start('hugo');
  });
  watch([path.watch.hugo_content], function(event, cb) {
    gulp.start('hugo');
  });
});

// Автоматическое обновление окна браузера с помощью BrowserSync
gulp.task('live', function () {
  browserSync.init({
    open: 'external',
    host: 'zina.design.dev',
    proxy: "zina.design.dev",
  });
  gulp.watch([path.watch.public_html]).on("change", reload);
  gulp.watch([path.watch.public_css]).on("change", reload);
  gulp.watch([path.watch.public_js]).on("change", reload);
  gulp.watch([path.watch.public_img]).on("change", reload);
  gulp.watch([path.watch.public_fonts]).on("change", reload);
});

// Задача по умолчанию
gulp.task('default', function() {
  // return runSequence('clean', ['sprite', 'img', 'fonts', 'style', 'js'], 'hugo', 'live', 'watch', function() {
  // return runSequence('clear', ['img', 'fonts', 'style', 'js'], 'hugo', 'live', 'watch', function() {
  return runSequence('clear', ['style', 'js'], 'hugo', 'live', 'watch', function() {
    console.log('Сборка сайта завершена.\nВключено автоматическое обновление окна браузера.');
  });
});

Ссылки

[ред. | ред. код]