• записей
    10
  • комментариев
    0
  • просмотров
    2698

1.4 Создание сборщика проекта. Руководство верстальщика

klierik

855 просмотров

1.1 Основные требования к сборщику

Сборщик проекта — это система сборки и задач, которая выполняет типовые задания автоматически, тем самым экономит время разработки проекта. Написанный нами сборщик (или билдер от англ. builder) должен стабильно работать в рамках проекта на протяжении всего его существования.

Определимся со списком задач, которыми должден владеть сборщик:

  1. Иметь единый конфигурационный файл, в котором описываются настройки проекта и пакетов, которые участвуют в обработке ресурсов проекта
  2. Обрабатывать ресурсы проекта "на лету", после внесения в них изменений
  3. Генерировать стили проекта
    1. Генерировать prod-версию (максимальное сжатие и оптимизация) и dev-версию (без сжатия)
    2. Поддерживать Sourcemaps — для отладки стилей
    3. Поддерживать AutoPrefixer — для автоматического генерирования стилей под старые версии браузеров
    4. Поддерживать cssBase64 — для встраивания маленьких картинок (иконок размером, обычно, до 2048КБ) непосредственно в CSS
    5. Поддерживать CSSO — структурная оптимизация стилей
    6. Генерировать criticalCSS (про это можно ознакомится в статье Разбираемся с критичным CSS)
  4. Автоматически организовать стили проекта. При помощи csscomb.com приводить все стили к единому стандрату форматирования, что очень удобно для ситуаций, когда над проектом работает больше одного разработчика
  5. Собирать и генерировать скрипты проекта
    1. Генерировать prod-версию (максимальное сжатие и оптимизация) и dev-версию (без сжатия)
    2. Проверять код при помощи eslint — это инструмент проверки качества написанного программного кода на JavaScript
    3. Делать конкатенацию js-фалов (собирать все файлы в один)
  6. Оптимизировать изображения, которые используются в проекте

Хочу обратить внимание на то, что требования составлены из целей создавать оптимизированный код и иметь гибкий инструмент для этого.
В большинстве случаев бОльшую часть из этого списка Заказчик не требует (так как это повышает стоимость проекта). Но, так как автор последние пол десятилетия работает с высоконагруженными системами, где высокие требования к клиентской оптимизации идут "из коробки", то было решено использовать именно такой подход в данном обучении.  Более простую версию билдера, имея эти знания, Вы сможете создать когда угодно. А за более сложную — Вы честно потребуете больший оклад, и будуте правы :)

Но, так же обращаю внимание что нет пределу совершенству в оптимизации. В рамках обучения мы будем собирать все ресурсы (JS/CSS) в один файл. Но есть методы которые позволяют асинхронно подгружать как CSS (редкий случай), так и JS (обычное являние).

Если Вам интересно углубится в мир клиентской оптимизации я советую начать с просмотра лекции Виталий Фридман: Responsive Web-дизайн. Трюки и уловки (всего 1:40 но море полезной информации).

1.2 Инициализация

Этот этап разработки крайне прост. Да бы не повторятся в том о чём уже было сказанно в Интернетах множество раз я предлагаю посмотреть видео, в котором рассказываются шаги, которые будут проделанны на данном этапе:

Скрытый текст

 

1.3 Установка NPM пакетов

Пакеты, которые мы будем в разработке условно поделим на 2 типа:

  • ресурсы проекта (такие как jQuery, bootstrap, прочее)
  • пакеты сборщика (ПО которое будет использоватся для обработки ресурсов для оптимизации, проверки кода, прочее)

1.3.1 Установка пакетов проекта

Первым шагом установим пакеты, которые будут использоватся непосредственно в вёрстке:

$ npm install -D jquery popper.js bootstrap

1.3.2 Установка пакетов сборщика

Следующей командой установим пакеты которые будут использоватся для сборки ресурсов проекта

$ npm i -D gulp-autoprefixer gulp-concat gulp-css-base64 gulp-csscomb gulp-debug gulp-if gulp-imagemin gulp-load-plugins gulp-sass gulp-sourcemaps gulp-uglify require-dir gulp-newer browser-sync gulp-notify gulp-notify through2 stream-combiner2 gulp-eslint penthouse gulp-csso gulp-babel babel-preset-latest babel-core

Краткое описание предназначения устанавливаемых пакетов:

Скрытый текст
  • gulp-autoprefixer — автоматическая растановка вендорных префиксов в стили: -webkit, -ms, -o, -moz

  • gulp-concat — объединение множества файлов в один (на пример объединение всех js-файлов в один итоговый)

  • gulp-css-base64 — маленькие картинки (иконки) конвертируются в base64 формат и вставляются непосредственно в CSS

  • gulp-csscomb — форматирует исходные стили в единый формат

  • gulp-debug — выводит дополнительную информацию при выполнении задач (полезно при отладке)

  • gulp-if — позволяет делать проверки в задачах

  • gulp-imagemin — минификация PNG, JPEG, GIF and SVG картинок

  • gulp-load-plugins — загружает все доступные gulp-пакеты автоматически

  • gulp-sass — компиляция sass/scss файлов в css

  • gulp-sourcemaps — вставляет сорсмапы в файлы, что упрощает их отладку

  • gulp-uglify — минификация JavaScript при помощи UglifyJS2

  • require-dir — загружает всё содержимое указанной директории

  • gulp-newer — позволяет оптимизировать процесс сборки кешируя не изменённые файлы

  • browser-sync — позволяет автоматически перегружать разрабатываемую страничку в браузере, в случае изменений на сервере (исходные файлы)

  • gulp-notify — выводит системные уведомления в случаях когда в процессе выполнения задач обнаружены ошибки

  • through2 — небольшая оболочка над потоком Node. Мы будем использовать для написания своих плагинов для Gulp

  • stream-combiner2 — позволяет объеденить несколько потоков в один

  • gulp-eslint — позволяет проводить анализ качества кода, написанного на любом выбранном стандарте JavaScript

  • penthouse — позволяет создавать criticalCss из общих стилей

  • gulp-csso — позволяет применять структурную оптимизацию стилей

  • gulp-babel — транспилирует js код в ES5

  • gulp-pxtorem — позволяет конвертировать PX в стилях в REM

1.4 Сборщик проекта

Ветка сборщика:

$ git checkout 1.4-gulp-builder

1.4.1 Структура

Файлы и директории которые отвечают за сборку проекта:

.
├── gulp/
│   ├── .csscomb.json		- файл настроек cssComb
│   ├── .eslintrc 		- файл настроек eslint https://goo.gl/4K6TyF
│   ├── config.js		- файл настроек задач и пакетов Gulp
│   └── tasks/			- задачи Gulp
│       ├── scripts.js
│       ├── server.js
│       └── styles.js
└── gulpfile.js			- основной файл конфигурации Gulp

Далее пройдём по всем файлам и обсудим что каждый делает.

1.4.2 Основной файл конфигурации Gulp

Содержимое файла gulpfile.js

'use strict';

require('require-dir')('./gulp/tasks/');

const gulp = require('gulp');

// Default tasks
gulp.task('default', gulp.series('styles', 'scripts'));
gulp.task('dev', gulp.series('default', gulp.parallel('styles:watch', 'scripts:watch', 'server')));

Это основной файл конфигурации сборщика. Он легковеснее того, который Вы видели в Скринкасте по Gulp и вот почему...

require('require-dir')('./gulp/tasks/');

Эта строка загрузки всех задачи, которые размещаются в директории "./gulp/tasks". После её выпонения будут загружены написанные нами задачи автоматически.

const gulp = require('gulp');

Следующим шагом мы загружаем Gulp, так как ниже мы используем его для объявления задач

// Default tasks
gulp.task('default', gulp.series('styles', 'scripts'));
gulp.task('dev', gulp.series('default', gulp.parallel('styles:watch', 'scripts:watch', 'server')));

А эти строки объявляют задачи, которые мы будем запускать для выпонения тех или иных операций.

Первая задача "default" — это задача, которая запускается по умолчанию при запуске Gulp (если задачи для выполнения не указаны явным образом). На пример команда:

$ gulp

запустит те же задачи, которые будут запущенны если мы выполним:

$ gulp default

Значит при выполнении этой команды будут запущены задачи "styles" и "scripts", а чём нас проинформирует терминал:

$ gulp
[16:48:19] Using gulpfile ~/http/htdocs/aworker/aworker-education/gulpfile.js
[16:48:19] Starting 'default'...
[16:48:19] Starting 'styles'...
[16:48:20] Finished 'styles' after 1.36 s
[16:48:20] Starting 'scripts'...
[16:48:21] Finished 'scripts' after 250 ms
[16:48:21] Finished 'default' after 1.61 s

Вторая задача "dev" будет выпонять другой набор. Для начала будут веполнены задачи, описанный в "default". Потом паралельно запустятся задачи:

  • "styles:watch" — мотиторинг фалов стилей в ожидании изменений
  • "scripts:watch" — мониторинг файлов скриптов в ожидании изменений
  • "server" — запустится локально статичный веб-сервер, который будет доступен оп адресу http://localhost:3000/. А так же автоматически откроется окно с этим путём в браузере Googlee Chrome.

Вот как это выглядит в терминале:

Скрытый текст

$ gulp dev
[16:59:26] Using gulpfile ~/http/htdocs/aworker/aworker-education/gulpfile.js
[16:59:26] Starting 'dev'...
[16:59:26] Starting 'default'...
[16:59:26] Starting 'styles'...
[16:59:28] Finished 'styles' after 1.53 s
[16:59:28] Starting 'scripts'...
[16:59:28] Finished 'scripts' after 240 ms
[16:59:28] Finished 'default' after 1.77 s
[16:59:28] Starting 'styles:watch'...
[16:59:28] Starting 'scripts:watch'...
[16:59:28] Starting 'server'...
[Browsersync] Access URLs:
 —————————————-
       Local: http://localhost:3000
    External: http://192.168.100.111:3000
 —————————————-
          UI: http://localhost:3001
 UI External: http://192.168.100.111:3001
 —————————————-
[Browsersync] Serving files from: ./

 

Что бы посмотреть весь список задач которые доступны для запуска выполните команду:

Скрытый текст

$ gulp -T
[17:16:15] Tasks for ~/http/htdocs/aworker/aworker-education/gulpfile.js
[17:16:15] ├── scripts
[17:16:15] ├── scripts:lint
[17:16:15] ├── scripts:watch
[17:16:15] ├── server
[17:16:15] ├── styles
[17:16:15] ├── styles:organise
[17:16:15] ├── styles:watch
[17:16:15] ├─┬ default
[17:16:15] │ └─┬ <series>
[17:16:15] │   ├── styles
[17:16:15] │   └── scripts
[17:16:15] └─┬ dev
[17:16:15]   └─┬ <series>
[17:16:15]     ├─┬ default
[17:16:15]     │ └─┬ <series>
[17:16:15]     │   ├── styles
[17:16:15]     │   └── scripts
[17:16:15]     └─┬ <parallel>
[17:16:15]       ├── styles:watch
[17:16:15]       ├── scripts:watch
[17:16:15]       └── server

 

1.4.3 Режим отладки

Сборщик позволяет выпонять задачи как для продакшена (минимизация стилей, скриптов, картинок, прочее) так и версию для разработки. По умолчанию задачи выполняются для продакшена. Что бы запустить сборщик в режиме отладки, требуется выполнить следующую команду

$ NODE_ENV=develop gulp

Если требуется запустить мониторинг файлов и сервер то выполните следующее

NODE_ENV=develop gulp dev

1.4.4 Файл конфигурации проекта

Почти все настройки, которые мы будем использовать в задачах Gulp, для большего удобства, были вынесены в индивидуальный файл. Это позволяет использовать в задачах только переменные, значения которых определены в одном месте. Такой подход упрощает процесс конфигурации сборщика проекта.

Файл размещается по адресу — "gulp/config.js". Полную версию файла Вы можете увидеть в репозитории, я лишь приведу наглядный пример как он оформлен:

Скрытый текст

'use strict';

//
// Global Gulp configuration file
module.exports = function () {

	//
	// Init Config
	const config = {};

	//
	// Folders configuration
	const rootDir      = "./"
		, assetsDir    = rootDir + "assets/"
		, publicDir    = rootDir + "public/"
		, templatesDir = rootDir + "templates/";

	config.path = {
		rootDir:        rootDir
		, assetsDir:    assetsDir
		, publicDir:    publicDir
		, templatesDir: templatesDir

		, sourceImages: assetsDir + "images/"
		, sourceJS:     assetsDir + "js/"
		, sourceStyles: assetsDir + "scss/"

		, deployImages: publicDir + "images/"
		, deployJS:     publicDir + "js/"
		, deployStyles: publicDir + "css/"

		, modulesDir: rootDir + "node_modules/"
	};

	//
	// Check for Development mode
	config.isDevelopment = process.env.NODE_ENV == 'develop'; // run as "NODE_ENV=develop gulp" for development mode

  	// Other settings here

	return config;
};

 

1.4.5 Настройки eslint

Для проверки JavaScript кода используется gulp-eslint пакет. Он требует присутвия файла настроек, согласно которых будет проверятся код.

Файл размещается по адресу "gulp/.eslintrc" и содержит настройки, которые так же можно сгенерировать самостоятельно в онлайн генераторе

Скрытый текст

{
	"parserOptions": {
		"ecmaVersion": 6,
		"sourceType": "script",
		"ecmaFeatures": {}
	},
	"rules": {},
	"env": {
		"es6": true
	}
}

 

1.4.6 Настройки форматирования стилей CssComb

Файл "gulp/.csscomb.json" отвечает за то, как будут автоматически форматироватся исходные стили проекта, приводя их к единому формату.

Файл достаточно большой, выкладывать его здесь будет избыточно. Посмотрите на его содержимое в репо.

Свой файл настроек CssComb можно создать в онлайн генераторе

1.4.7 Настройки Autoprefixer

Согласно оффициальной документации gulp-autoprefixer, указать в директиве "browsers" для каких браузеров следует применять вендорные префиксы можно непосредственно в конфигурации:

const gulp = require('gulp');
const autoprefixer = require('gulp-autoprefixer');
 
gulp.task('default', () =>
    gulp.src('src/app.css')
        .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
        .pipe(gulp.dest('dist'))
);

Но, в официальной документации Autoprefixer сказано несколько иначе:

Цитата

Try to not use it.  The best practice is to use .browserslistrc config or browserslist key in package.json to share target browsers with Babel, ESLint and Stylelint. See Browserslist docs for available queries and default value.

Они рекомендуют использовать или файл ".browserslistrc" (который должен лежать в корне проекта) или директиву в файле "package.json". Требуется это для того, что бы другие плагины (такие как: Babel, postcss-preset-env, eslint-plugin-compat, stylelint-no-unsupported-browser-features, postcss-normalize) так же пользовались этими настройками. Об этом рассказано на странице плагина Browserslist.

По этому мы добавим эти настройки в файл package.json

"browserslist": ["last 2 version", "> 5%", "iOS >= 7"]

1.4.8 Задачи Gulp

Теперь давайте перейдём обсуждению непосредственно задач, которые присутвуют в сборщике проекта.

ℹ️ Обращаю внимание читателя на то, что описанные ниже задачи могут быть не полностью описанны (или не все). Только те задачи и в том виде, когда автор писал эти строки. Но, скорее всего, у Вас не будет проблем в понимании как они работают и для чего созданы. В случае если что-то будет не понятно — задавайте вопросы 🙂

1.4.8.1 Сборка стилей

Файл задачи сборки стилей расположен по адресу "gulp/tasks/styles.js". Полную версию файла Вы можете найти в репо, а тут давайте обсудим что он делает.

Задача "styles" выполняет сборку стилей SCSS -> CSS. Настройки, которые используются в задачах предварительн описанны в файле "gulp/config.js"

Скрытый текст

gulp.task('styles', () => {

	return combine(
		/* Загрузить файл стилей */
		gulp.src(cfg.styles.sourceFile, { since: gulp.lastRun('styles') })
		/* Обработать только те файлы, которые были изменены. Остальные будут взяты из кеша */
		, $.newer(cfg.path.deployStyles)
		/* Если сборщик запущен в режиме develop, вывести файлы которые будут обработаны */
		, $.if(cfg.isDevelopment, $.debug({ title: 'src' }))
		/* Если сборщик запущен в режиме develop, запустить инициализацию sourcemaps */
		, $.if(cfg.isDevelopment, $.sourcemaps.init())
		/**
		 * Если сборщик запущен в режиме develop, произвести сборку стилей используя
		 * параметры, описанные в настройках "cfg.plugins.sass.dev"
		 * В ином случае использовать параметры, описанные в cfg.plugins.sass.prod
		 * и не применять сжатие стилей
		 * */
		, $.if(cfg.isDevelopment, $.sass(cfg.plugins.sass.dev), $.sass(cfg.plugins.sass.prod))
		/* Применить autoprefixer к стилям используя параметры, описанные в cfg.plugins.autoprefixer */
		, $.autoprefixer(cfg.plugins.autoprefixer)
		/* Применить cssBase64 к стилям используя параметры, описанные в cfg.plugins.cssBase64 */
		, $.cssBase64(cfg.plugins.cssBase64)
		/* Применить структурную оптимизацию стилей */
		, $.csso()
		/* Если сборщик запущен в режиме develop, записать sourcemaps в итоговый файл */
		, $.if(cfg.isDevelopment, $.sourcemaps.write(cfg.plugins.sourcemaps))
		/*  Сохранить конечный результат в директорию, указанную в настройках cfg.path.deployStyles */
		, gulp.dest(cfg.path.deployStyles)
	).on('error', $.notify.onError((err) => {
		return {
			title:   'Styles build error',
			message: err.message
		}
	}))

});

 

1.4.8.2 Форматирование стилей

Ещё одной важной для нас задачей будет форматирование стилей. Эта задача приведёт в порядок все стили

Скрытый текст

gulp.task('styles:organise', () => {

	return combine(
		/**
		 * Загрузить все .scss файлы, за исключением тех, в имени которых присутвует "variables"
		 * */
		gulp.src([cfg.path.sourceStyles + '**/*.scss', '!' + cfg.path.sourceStyles + '**/*variables*'], { since: gulp.lastRun('styles:organise') })
		/* Обработать только те файлы, которые были изменены. Остальные будут взяты из кеша */
		, $.newer(cfg.path.sourceStyles + '**/*.scss')
		/* Если сборщик запущен в режиме develop, вывести файлы которые будут обработаны */
		, $.if(cfg.isDevelopment, $.debug({ title: 'src' }))
		/* Обработать файлы стилей CssComb используя параметры, описанные в файле 'gulp/.csscomb.json' */
		, $.csscomb(cfg.path.rootDir + 'gulp/.csscomb.json')
		/* Сохранить итоговые файлы в исходную директорию */
		, gulp.dest(cfg.path.sourceStyles)
	).on('error', $.notify.onError((err) => {
		return {
			title:   'Styles Organize error',
			message: err.message
		}
	}))

});

 

Поясню почему "*variables*" вынесены из обработки под катом.

Скрытый текст

Дело в том что CssComb после обработки файлов с переменными, такой  вариант форматирования:


$block-radius-base: 			$border-radius-base !default;
$block-title-bg:			$gray-light !default;
$block-title-color:			#fff !default;
$block-content-border:			1px solid $gray-lighter !default;

приведёт к виду:


$block-radius-base: $border-radius-base !default;
$block-title-bg: $gray-light !default;
$block-title-color: #fff !default;
$block-content-border: 1px solid $gray-lighter !default;

и сделает код менее читабельным. Потому файлы с переменными удобнее форматировать вручную.

1.4.8.3 Создание criticalCss

В нашей разработке мы так же будем генерировать criticalCss. В одной из следующих статья мы поговорим как эти стили должны использоватся а пока обсудим как их создавать.

Сама задача, которая генерирует criticalCss-файл имеет мало кода:

Скрытый текст

gulp.task('styles:critical', () => {

	return penthouse(cfg.plugins.penthouse)
		.then(criticalCss => {
			fs.writeFileSync(cfg.styles.crticalFile, criticalCss);
		})

});

 

Для выполнения задачи в файле "gulp/config.js" есть список параметров, приблизительно такой:

Скрытый текст

penthouse:    {
	url:                       'http://' + config.server.host + ':' + config.server.port
	, css:                     config.styles.deployFile
	, width:                   1200
	, height:                  960
	, strict:                  true
	, maxEmbeddedBase64Length: 2 * 1024
	, forceInclude:            []
	, timeout:                 30000
	, phantomJsOptions:        {
		'ssl-protocol': 'any'
	}
},

 

Все настройки описанны в на офф. странице в соответствующем разделе Options. Я лишь обращаю Ваше внимание одни из наиболее важных параметров:

  • forceInclude — принимает массив, согласно которого будут добавлены стили, которые не были добавлены в criticalCss автоматически
  • propertiesToRemove — принимает массив, согласно которого будут удалены стили из criticalCss

Что же делает penthouse?

Пакет создаёт виртуальное окно браузера (для этого используется puppeteer), размер которого указан в настройках (в выше приведённом примере это 1200x960). Далее penthouse проверяет какие из стилей присутвуют в этой области документа (в частности проверяет какие элементы присутвуют в области) и сохраняет их в указанном файле. Остальные стили, которые не попадают в область видимости (находятся за экраном) — не учитываются.

ℹ️ Обращаю Ваше внимание на то, что зачастую в criticalCss так же не попадают стили элементов (или не полностью), которые по тем или иным причинам не отображались в момент их генерирования. Но разработчик может добавить их самостоятельно, указав в настройках. На пример:

forceInclude: [
	/^\.dialog/,	// Будут добавленны все стили классов, которые начинаются с ".dialog"
	'.configurator'	// Будут добавленны стили, которые применены к классу ".configurator"
],

Режим отладки penthouse

В случае если возникнут какие либо проблемы в создании "critical.css" следующей командой можно запустить задачу с выводом в терминал служебной информации:

$ env DEBUG="penthouse,penthouse:*" gulp styles:critical

ℹ️ В случае если Вам требуется создать criticalCss сразу для нескольких URL обратите внимание на оффициальный пример

1.4.8.4 Сборки скриптов

Одной из не мало важных задач так же является сборка и минимизация скриптов. Задача расположена в файле по адресу "gulp/tasks/scripts.js".

Скрытый текст

gulp.task('scripts', () => {

	return combine(
		/**
		 * Загрузить все .js файлы, указанные в cfg.scripts.files
		 * */
		gulp.src(cfg.scripts.files, { since: gulp.lastRun('scripts') })
		/* Обработать только те файлы, которые были изменены. Остальные будут взяты из кеша */
		, $.newer(cfg.path.deployJS)
		/* Если сборщик запущен в режиме develop, вывести файлы которые будут обработаны */
		, $.if(cfg.isDevelopment, $.debug({ title: 'src' }))
		/* Если сборщик запущен в режиме develop, запустить инициализацию sourcemaps */
		, $.if(cfg.isDevelopment, $.sourcemaps.init())
		/* Транспилировать код, который был написан на стандарте ES6 в ES5 */
		, $.babel(cfg.plugins.babel)
		/* Объеденить все файлы в один */
		, $.concat(cfg.scripts.concatFile)
		/* Если сборщик НЕ запущен в режиме develop, применить сжатие */
		, $.if(!cfg.isDevelopment, $.uglify(cfg.plugins.uglify))
		/* Если сборщик запущен в режиме develop, записать sourcemaps в итоговый файл */
		, $.if(cfg.isDevelopment, $.sourcemaps.write(cfg.plugins.sourcemaps))
		/*  Сохранить конечный результат в директорию, указанную в настройках cfg.path.deployJS */
		, gulp.dest(cfg.path.deployJS)
	).on('error', $.notify.onError((err) => {
		/* В случае возникновения ошибки вывести уведомление */
		return {
			title:   'Scripts build error',
			message: err.message
		}
	}))

});

 

1.4.8.5 Линтер скриптов

Как работает данная задача шикарно изложенно в скринкасте Ильи Кантора — Более сложный поток: eslint, gulp-if, stream-combiner2

Прихований текст

 

Особо тут добавить нечего, потому выложу только сам код, который используется в рамках нашего обучения

Прихований текст

gulp.task('scripts:lint', () => {

	let eslintResults = {};

	try {
		eslintResults = JSON.parse(fs.readFileSync(cfg.plugins.eslint.cacheFilePath))
	} catch (e) {
		// do nothing, no cache file found
	}

	return gulp
		.src(cfg.path.sourceJS + '**/*.js', { read: false })
		.pipe($.if(cfg.isDevelopment, $.debug({ title: 'JS src' })))
		.pipe($.if(
			(file) => {
				return eslintResults[file.path] && eslintResults[file.path].mtime == file.stat.mtime.toJSON();
			},
			through2((file, enc, callback) => {
				file.eslint = eslintResults[file.path].eslint;
				callback(null, file);
			}),
			combine(
				through2((file, enc, callback) => {
					file.contents = fs.readFileSync(file.path);
					callback(null, file);
				}),
				$.eslint(cfg.plugins.eslint.options),
				$.if(cfg.isDevelopment, $.debug({ title: 'lint src' })),
				through2((file, enc, callback) => {
					eslintResults[file.path] = {
						eslint: file.eslint,
						mtime:  file.stat.mtime
					};
					callback(null, file);
				})
			)
		))
		.pipe($.eslint.format())
		.on('end', () => {
			fs.writeFileSync(cfg.plugins.eslint.cacheFilePath, JSON.stringify(eslintResults));
		})
		.pipe($.eslint.failAfterError())
		.on('error', $.notify.onError((err) => {
			return {
				title:   'eslint',
				message: err.message
			}
		}));
});

 

Итоги подведём

Подводя черту под вышесказанным хочу сказать, что мы рассмотрели более-менее универсальный вариант сборщика, под нашу задачу.

От проекта к проекту на Вашум пути в разработке будут попадатся разные задачи, которые можно будет реализовать разными способами. Выбирайте тот который проще для понимания и поддержки другими разработчиками на сколько это возможно. Не создавайте слишком сложные конфиги но и не дробите их на множества файлов — это излишне. Соблюдайте баланс между гибкостью в коде и сложности его исполнения.

Эти простые рекомендации позволят Вашему коду годами выполнять свою задачу, поддерживатся и изменятся без особых трудозатрат.

Добра и удачи 🙏



0 комментариев


Рекомендованные комментарии

Нет комментариев для отображения

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас
  • Сейчас в сети   0 пользователей, 0 анонимных, 79 гостей (Полный список)

    Нет пользователей в сети в данный момент.

  • Пишут сейчас

    • Есть несколько вариантов которые позволяют развиваться профессионально: Ask friend for help. Опросить друзей знакомых на предмет предлагаемых услуг, заявить о себе. Выполнить несколько простых проектов для опыта/портфолио. Тем самым продвигать себя в качестве специалиста (сарафанное радио) Freelance. Вход сложный. Зато на мелочах можно поднять опыт за символическую стоимость. Потом развивать свой аккаунт, "обрастать" клиентами и поднимать уровень квалификации. Важно: почитайте пару гайдов как получить заказ новичку, как оформить профиль и прочие рекомендации. Сайты по теме: https://freelansim.ru https://www.fl.ru https://www.upwork.com — я бы выбрал этот Remote. Full-time. Ещё один хороший вариант найти работу — утроится в компанию работать удалённо. Без территориально ограничения. Компания может быть из СНГ, с юр. лицом. Заключаете договор и сотрудничаете на ставку. Part-time. Тоже самое что и предыдущий пункт но формат сотрудничества на правах почасовой работы. Office. Работа в офисе на позции Junior с перспективой роста. Хорошо подойдут галеры по типу ЕПАМ, Ciklum, LuxSoft, и тд. Денег мало (в начале), но компенсируется опытом. За 9-12 месяцев можете вырасти в Middle. Дальше плыть будет легче. Для поиска работы для Remote и Office вариантов можно использовать стандартные инструменты, на пример: djinni.co или linkedin.com. Рекомендации к заполнению профилю/CV Опишите всё что можете предложить заказчику. Расскажите о своих скилах, что непосредственно Вы делали выполняя работу над тем или иным проектом. Расскажите о своём опыте, даже если он не значительный. Если опыта совсем мало, инвестируйте месяц-два и выполните несколько простых задач, которые Вы сможете показать заказчику. И профиль и CV должно быть на английском языке, в первую очередь, и лишь копия русскоязычная (у меня такой нет, так как рынок предполагает знание английского языка с уровня pre-intermediate)
    • Сидеть дома и развиваться до уровня Senior годами без реальной работы?! 
    • Факт есть факт — специалистов как было мало так и осталось. Можно выбирать любую интересующую себя нишу и развиваться в ней до уровня Senior и иметь на себя спрос в последствии.
  • Лучшие авторы

  • Текущие цели пожертвований