Skip to content

Commit 0b25b6a

Browse files
Merge pull request #51 from firefoxic/firefoxic/issue50
Больше улучшений сборки
2 parents ab72319 + 4e9edda commit 0b25b6a

File tree

13 files changed

+1230
-514
lines changed

13 files changed

+1230
-514
lines changed

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@ node_modules
33
build
44
.idea
55
.DS_Store
6-
source/.raw/
7-
!source/.raw/**/README.md
6+
raw/**/*.jpg
7+
raw/**/*.jpeg
8+
raw/**/*.png
9+
raw/**/*.svg
10+
!raw/**/README.md

README.md

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,14 @@
6767
│ └── workflows/ # Автоматизация для github actions
6868
│ ├── check.yml # Запускает линтеры на Гитхабе
6969
│ └── gh-pages.yml # Публикует проект и создаёт ссылку на проект
70+
├── raw/ # Папка для «сырых» файлов (игнорируются гитом)
71+
│ └── images/ # Папка для оригиналов картинок
72+
│ └── icons/ # Папка для оригиналов svg-иконок
7073
├── source/ # Исходники проекта
74+
│ ├── favicons/ # Папка для фавиконок (кроме favicon.ico)
7175
│ ├── fonts/ # Папка для шрифтов
72-
│ ├── images/ # Папка для хранения картинок
73-
│ │ └── icons/ # Специальная папка для преобразования svg в спрайт(stack)
76+
│ ├── images/ # Папка для оптимизированных картинок
77+
│ │ └── icons/ # Папка для оптимизированных svg-иконок для преобразования их в спрайт (stack)
7478
│ ├── scripts/ # Скрипты
7579
│ │ └── index.js # Главный скрипт
7680
│ ├── styles/ # Папка для препроцессорных файлов sass
@@ -101,7 +105,7 @@
101105

102106
## Дополнительные команды
103107

104-
- `npm run optimizeImages` - создаёт оптимизированные изображения в `source/images/`
108+
- `npm run optimizeImages` - создаёт оптимизированные изображения в `source/images/` и `source/icons/`
105109
- `npm run preview` - позволяет посмотреть результат работы prod-версии сборки
106110
- `npm run lint` - запускает все проверки (занимает длительное время)
107111
- `npm run lint:bem` - проверяет правильное использование БЭМ в разметке
@@ -171,33 +175,60 @@
171175

172176
## Работа с графикой
173177

174-
Абсолютно всю растровую графику с двухкратной плотностью из макета складывайте в `source/.raw`. Здесь графика игнорируется гитом.
178+
### Растр
179+
180+
Абсолютно всю растровую графику с двухкратной плотностью из макета складывайте в `raw/images/`. Здесь графика игнорируется гитом.
175181

176182
После того как добавите графику сразу запускайте команду `npm run optimizeImages` для оптимизации графики и создания `.webp`-версии. Команду нужно запускать один раз при появлении новой графики в проекте.
177183

178184
Новая оптимизированная графика разной плотностью и суффиксами плотности в именах файлов появится в `source/images`. Эту, уже оптимизированную графику нужно коммитить.
179185

180-
Векторную графику для спрайта складывайте в `source/images/icons/`. Автоматизация создаст из иконок файл `stack.svg`.
186+
### Вектор
187+
188+
Контентную векторную графику (логотип, графики, иллюстрации) также складывайте в `raw/images/`. Запуск той же команды `npm run optimizeImages` поместит оптимизированные копии этих svg-файлов в `source/images/`
189+
190+
```shell
191+
└── raw/
192+
└── images/
193+
```
194+
195+
Векторную графику для спрайта (иконки) складывайте в `raw/icons/`. Запуск той же команды `npm run optimizeImages` поместит оптимизированные копии этих svg-файлов в `source/images/`.
181196

182197
```shell
183198
└── source/
184-
├── .raw/
185199
└── images/
186200
└── icons/
187201
```
188202

189-
Всю графику автоматизация перенесёт в `build/images/`.
203+
При сборке автоматизация перенесёт всю графику из `source/images/` в `build/images/`, а из иконок в `source/images/icons/` создаст спрайт `build/images/icons/stack.svg`.
190204

191205
```shell
192206
└── build/
193207
└── images/
194-
├── icons # папка для спрайта
208+
├── icons/ # папка для спрайта
195209
│ └── stack.svg # спрайт
196210
├── bg.jpg
197211
├── bg.webp
198212
├── hero.png
199213
├── hero.webp
200-
└── burger.svg
214+
└── logo.svg
215+
```
216+
217+
### Фавиконки
218+
219+
Варианты фавиконок форматов PNG и SVG следует размещать в `source/favicons/`.
220+
221+
Файлы `favicon.ico` и `manifest.webmanifest` — в `source/`:
222+
223+
```shell
224+
└── source/
225+
├── favicons/
226+
│ ├── 180.png
227+
│ ├── 192.png
228+
│ ├── 512.png
229+
│ └── icon.svg
230+
├── favicon.ico
231+
└── manifest.webmanifest
201232
```
202233

203234
## Работа со шрифтами
@@ -208,9 +239,7 @@
208239
└── build/
209240
└── fonts/
210241
├── open-sans.woff2
211-
├── open-sans.woff
212-
├── open-sans-bold.woff
213-
└── open-sans-bold.woff
242+
└── open-sans-bold.woff2
214243
215244
```
216245

gulpfile.js

Lines changed: 124 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,84 @@
1+
import { readFileSync, rmSync } from 'node:fs';
2+
13
import gulp from 'gulp';
24
import plumber from 'gulp-plumber';
5+
import { nunjucksCompile } from 'gulp-nunjucks';
6+
import htmlmin from 'gulp-htmlmin';
37
import * as dartSass from 'sass';
48
import gulpSass from 'gulp-sass';
59
import postcss from 'gulp-postcss';
610
import postUrl from 'postcss-url';
711
import autoprefixer from 'autoprefixer';
812
import csso from 'postcss-csso';
9-
import terser from 'gulp-terser';
13+
import { createGulpEsbuild } from 'gulp-esbuild';
14+
import browserslistToEsbuild from 'browserslist-to-esbuild';
1015
import sharp from 'gulp-sharp-responsive';
1116
import svgo from 'gulp-svgmin';
1217
import { stacksvg } from 'gulp-stacksvg';
13-
import { deleteAsync } from 'del';
14-
import browser from 'browser-sync';
18+
import server from 'browser-sync';
1519
import bemlinter from 'gulp-html-bemlinter';
1620

21+
const { src, dest, watch, series, parallel } = gulp;
1722
const sass = gulpSass(dartSass);
23+
const PATH_TO_SOURCE = './source/';
24+
const PATH_TO_DIST = './build/';
25+
const PATH_TO_RAW = './raw/';
26+
const PATHS_TO_STATIC = [
27+
`${PATH_TO_SOURCE}fonts/**/*.{woff2,woff}`,
28+
`${PATH_TO_SOURCE}*.ico`,
29+
`${PATH_TO_SOURCE}*.webmanifest`,
30+
`${PATH_TO_SOURCE}favicons/*.{png,svg}`,
31+
`${PATH_TO_SOURCE}vendor/**/*`,
32+
`${PATH_TO_SOURCE}images/**/*`,
33+
`!${PATH_TO_SOURCE}images/icons/**/*`,
34+
`!${PATH_TO_SOURCE}**/README.md`,
35+
];
1836
let isDevelopment = true;
1937

2038
export function processMarkup () {
21-
return gulp.src('source/*.html')
22-
.pipe(gulp.dest('build'));
39+
return src(`${PATH_TO_SOURCE}**/*.html`)
40+
.pipe(nunjucksCompile())
41+
.pipe(htmlmin({ collapseWhitespace: !isDevelopment }))
42+
.pipe(dest(PATH_TO_DIST))
43+
.pipe(server.stream());
2344
}
2445

2546
export function lintBem () {
26-
return gulp.src('source/*.html')
47+
return src(`${PATH_TO_SOURCE}*.html`)
2748
.pipe(bemlinter());
2849
}
2950

3051
export function processStyles () {
31-
return gulp.src('source/styles/*.scss', { sourcemaps: isDevelopment })
52+
return src(`${PATH_TO_SOURCE}styles/*.scss`, { sourcemaps: isDevelopment })
3253
.pipe(plumber())
3354
.pipe(sass().on('error', sass.logError))
3455
.pipe(postcss([
3556
postUrl({ assetsPath: '../' }),
3657
autoprefixer(),
3758
csso()
3859
]))
39-
.pipe(gulp.dest('build/styles', { sourcemaps: isDevelopment }))
40-
.pipe(browser.stream());
60+
.pipe(dest(`${PATH_TO_DIST}styles`, { sourcemaps: isDevelopment }))
61+
.pipe(server.stream());
4162
}
4263

4364
export function processScripts () {
44-
return gulp.src('source/scripts/**/*.js')
45-
.pipe(terser())
46-
.pipe(gulp.dest('build/scripts'))
47-
.pipe(browser.stream());
65+
const gulpEsbuild = createGulpEsbuild({ incremental: isDevelopment });
66+
67+
return src(`${PATH_TO_SOURCE}scripts/*.js`)
68+
.pipe(gulpEsbuild({
69+
bundle: true,
70+
format: 'esm',
71+
// splitting: true,
72+
platform: 'browser',
73+
minify: !isDevelopment,
74+
sourcemap: isDevelopment,
75+
target: browserslistToEsbuild(),
76+
}))
77+
.pipe(dest(`${PATH_TO_DIST}scripts`))
78+
.pipe(server.stream());
4879
}
4980

50-
export function optimizeImages () {
81+
export function optimizeRaster () {
5182
const RAW_DENSITY = 2;
5283
const TARGET_FORMATS = [undefined, 'webp']; // undefined — initial format: jpg or png
5384

@@ -70,90 +101,119 @@ export function optimizeImages () {
70101
return { formats };
71102
}
72103

73-
return gulp.src('source/.raw/**/*.{png,jpg,jpeg}')
104+
return src(`${PATH_TO_RAW}images/**/*.{png,jpg,jpeg}`)
74105
.pipe(sharp(createOptionsFormat()))
75-
.pipe(gulp.dest('source/images'));
106+
.pipe(dest(`${PATH_TO_SOURCE}images`));
76107
}
77108

78109
export function optimizeVector () {
79-
return gulp.src(['source/images/**/*.svg', '!source/images/icons/**/*.svg'])
110+
return src([`${PATH_TO_RAW}**/*.svg`])
80111
.pipe(svgo())
81-
.pipe(gulp.dest('build/images'));
112+
.pipe(dest(PATH_TO_SOURCE));
113+
}
114+
115+
export function optimizeImages (done) {
116+
parallel(
117+
optimizeVector,
118+
optimizeRaster
119+
)(done);
82120
}
83121

84122
export function createStack () {
85-
return gulp.src('source/images/icons/**/*.svg')
86-
.pipe(svgo())
123+
return src(`${PATH_TO_SOURCE}images/icons/**/*.svg`)
87124
.pipe(stacksvg())
88-
.pipe(gulp.dest('build/images/icons'));
125+
.pipe(dest(`${PATH_TO_DIST}images/icons`));
89126
}
90127

91128
export function copyAssets () {
92-
return gulp.src([
93-
'source/fonts/**/*.{woff2,woff}',
94-
'source/*.ico',
95-
'source/*.webmanifest',
96-
'source/vendor/**/*',
97-
'source/images/**/*',
98-
'!source/images/icons/**/*',
99-
'!source/**/README.md',
100-
], {
101-
base: 'source'
102-
})
103-
.pipe(gulp.dest('build'));
129+
return src(PATHS_TO_STATIC, { base: PATH_TO_SOURCE })
130+
.pipe(dest(PATH_TO_DIST));
104131
}
105132

106-
export function startServer (done) {
107-
browser.init({
133+
export function startServer () {
134+
server.init({
108135
server: {
109-
baseDir: 'build'
136+
baseDir: PATH_TO_DIST
110137
},
138+
serveStatic: [
139+
{
140+
route: '/fonts',
141+
dir: `${PATH_TO_SOURCE}fonts`,
142+
},
143+
{
144+
route: '/*.ico',
145+
dir: `${PATH_TO_SOURCE}*.ico`,
146+
},
147+
{
148+
route: '/*.webmanifest',
149+
dir: `${PATH_TO_SOURCE}*.webmanifest`,
150+
},
151+
{
152+
route: '/favicons',
153+
dir: `${PATH_TO_SOURCE}favicons`,
154+
},
155+
{
156+
route: '/vendor',
157+
dir: `${PATH_TO_SOURCE}vendor`,
158+
},
159+
{
160+
route: '/images',
161+
dir: `${PATH_TO_SOURCE}images`,
162+
},
163+
],
111164
cors: true,
112165
notify: false,
113166
ui: false,
167+
}, (err, bs) => {
168+
bs.addMiddleware('*', (req, res) => {
169+
res.write(readFileSync(`${PATH_TO_DIST}404.html`));
170+
res.end();
171+
});
114172
});
115-
done();
173+
174+
watch(`${PATH_TO_SOURCE}**/*.{html,njk}`, series(processMarkup));
175+
watch(`${PATH_TO_SOURCE}styles/**/*.scss`, series(processStyles));
176+
watch(`${PATH_TO_SOURCE}scripts/**/*.js`, series(processScripts));
177+
watch(`${PATH_TO_SOURCE}images/icons/**/*.svg`, series(createStack, reloadServer));
178+
watch(PATHS_TO_STATIC, series(copyAssets, reloadServer));
116179
}
117180

118181
function reloadServer (done) {
119-
browser.reload();
182+
server.reload();
120183
done();
121184
}
122185

123-
function watchFiles () {
124-
gulp.watch('source/styles/**/*.scss', gulp.series(processStyles));
125-
gulp.watch('source/scripts/**/*.js', gulp.series(processScripts));
126-
gulp.watch('source/*.html', gulp.series(processMarkup, reloadServer));
127-
}
128-
129-
function compileProject (done) {
130-
gulp.parallel(
131-
processMarkup,
132-
processStyles,
133-
processScripts,
134-
optimizeVector,
135-
createStack,
136-
copyAssets,
137-
)(done);
138-
}
139-
140-
function deleteBuild () {
141-
return deleteAsync('build');
186+
export function removeBuild (done) {
187+
rmSync(PATH_TO_DIST, {
188+
force: true,
189+
recursive: true,
190+
});
191+
done();
142192
}
143193

144194
export function buildProd (done) {
145195
isDevelopment = false;
146-
gulp.series(
147-
deleteBuild,
148-
compileProject
196+
series(
197+
removeBuild,
198+
parallel(
199+
processMarkup,
200+
processStyles,
201+
processScripts,
202+
createStack,
203+
copyAssets,
204+
),
149205
)(done);
150206
}
151207

152208
export function runDev (done) {
153-
gulp.series(
154-
deleteBuild,
155-
compileProject,
209+
series(
210+
removeBuild,
211+
parallel(
212+
processMarkup,
213+
processStyles,
214+
processScripts,
215+
createStack,
216+
),
156217
startServer,
157-
watchFiles
158218
)(done);
159219
}

0 commit comments

Comments
 (0)