@videinfra/static-website-builder 1.17.0 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [2.0.0] - 2026-01-27
8
+ ### Added
9
+ - Replaced webpack with rolldown
10
+
11
+ ## [1.17.1] - 2026-01-23
12
+ ### Added
13
+ - Sitemap generation in watch mode too
14
+
7
15
  ## [1.17.0] - 2026-01-15
8
16
  ### Added
9
17
  - Added sitemap task
package/README.md CHANGED
@@ -5,7 +5,11 @@
5
5
 
6
6
  [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url]
7
7
 
8
- `static-website-builder` is a customizable static site project builder powered by Gulp, Webpack, Babel, SASS, PostCSS, TwigJS, BrowserSync
8
+ `static-website-builder` is a customizable static site project builder powered by Gulp, Rolldown, SASS, PostCSS, TwigJS, BrowserSync
9
+
10
+ ## Requirements
11
+
12
+ - Node.js >= 20.0.0
9
13
 
10
14
  ## Features
11
15
 
@@ -15,7 +19,7 @@
15
19
  - TWIG: Optional TwigJS template engine with optional plugins for additional functions and filters
16
20
  - Stylesheets: Autoprefixing and minification with PostCSS support
17
21
  - SASS: Optional SASS / SCSS compilation
18
- - Javascript: Transpilation with Babel, bundling and minification
22
+ - Javascript/Typescript: Transpilation, bundling and minification with rolldown
19
23
  - SVG icons: Sprite generation from individual SVG files
20
24
 
21
25
 
package/bin/builder.js CHANGED
File without changes
@@ -1,3 +1,9 @@
1
1
  {% extends 'layouts/base.twig' %}
2
2
 
3
- {% block body %}Another file{% endblock %}
3
+ {% block head %}
4
+ <link rel="stylesheet" href="/assets/stylesheets/nested-calc-test.css">
5
+ {% endblock %}
6
+ {% block body %}
7
+ Another file
8
+ <script type="module" src="/assets/javascripts/other.js"></script>
9
+ {% endblock %}
@@ -2,12 +2,9 @@
2
2
  * All files listed in here are created / compiled and additionally
3
3
  * shared.js is automatically created, which contains all common JS (chunks / modules imported from more than 1 entry files).
4
4
  */
5
- module.exports = {
6
- 'shared': [
7
- './common'
8
- ],
5
+ export default {
9
6
  'main': [
10
- './common',
11
- './main'
7
+ 'common.js',
8
+ 'main.js',
12
9
  ]
13
10
  };
@@ -2,16 +2,18 @@
2
2
  * All files listed in here are created / compiled and additionally
3
3
  * shared.js is automatically created, which contains all common JS (chunks / modules imported from more than 1 entry files).
4
4
  */
5
- module.exports = {
6
- 'shared': [
7
- './common'
8
- ],
5
+ export default {
9
6
  'main': [
10
- './common',
11
- './main'
7
+ 'common.js',
8
+ 'main.js',
12
9
  ],
13
10
  'other': [
14
- './common',
15
- './other'
16
- ]
11
+ 'common.js',
12
+ 'other.js',
13
+ ],
14
+ 'something': [
15
+ 'common.js',
16
+ 'something.ts',
17
+ ],
17
18
  };
19
+
@@ -0,0 +1,9 @@
1
+ type Something = {
2
+ name: string;
3
+ }
4
+
5
+ const something: Something = {
6
+ name: 'something',
7
+ }
8
+
9
+ console.log(something);
@@ -5,6 +5,15 @@ const { series, parallel } = require('gulp');
5
5
  const { DEFAULT_TASKS, BUILD_TASKS } = require('./task-order');
6
6
  const resolveDynamicTask = require('./gulp/resolve-dynamic-task');
7
7
 
8
+ /**
9
+ * Sort tasks by .order property
10
+ *
11
+ * @param {array} tasks Tasks
12
+ * @returns {array} Sorted tasks
13
+ */
14
+ function sortTasks (tasks) {
15
+ return tasks.sort((a, b) => (a.order || 0) - (b.order || 0));
16
+ }
8
17
 
9
18
  /**
10
19
  * Organize and order tasks
@@ -46,8 +55,8 @@ function generateTaskList (taskConfig) {
46
55
  }
47
56
  }
48
57
 
49
- taskList.default = filter(taskList.default, taskGroup => taskGroup.length);
50
- taskList.build = filter(taskList.build, taskGroup => taskGroup.length);
58
+ taskList.default = filter(taskList.default, taskGroup => taskGroup.length).sort(sortTasks);
59
+ taskList.build = filter(taskList.build, taskGroup => taskGroup.length).sort(sortTasks);
51
60
 
52
61
  return taskList;
53
62
  }
package/lib/get-path.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const path = require('path');
2
- const memoize = require('nano-memoize');
2
+ const { nanomemoize } = require('nano-memoize');
3
3
  const getConfig = require('./get-config');
4
4
 
5
5
 
@@ -9,7 +9,7 @@ const getConfig = require('./get-config');
9
9
  * @returns {object} Configuration
10
10
  */
11
11
 
12
- const getPathConfig = memoize(function () {
12
+ const getPathConfig = nanomemoize(function () {
13
13
  return getConfig.getConfig().paths;
14
14
  });
15
15
 
@@ -1,35 +1,67 @@
1
- const path = require('path');
2
- const flatten = require('lodash/flatten');
3
- const map = require('lodash/map');
4
- const filter = require('lodash/filter');
1
+ const path = require("path");
2
+ const flatten = require("lodash/flatten");
3
+ const map = require("lodash/map");
4
+ const filter = require("lodash/filter");
5
5
 
6
6
  const REGEX_DOT_PREFIX = /^\.+/;
7
7
  const REGEX_WINDOWS_BACKSLASH = /\\/g;
8
8
 
9
-
10
9
  class GlobObject {
11
- constructor () {
10
+ constructor() {
12
11
  this.hadEmptyPaths = false;
13
12
  this.isIgnore = false;
13
+ this.isAllFiles = false;
14
14
  this.hasExtensions = false;
15
+ this.extensions = [];
15
16
  this.pathsArr = [];
17
+ this.pathsArrRaw = [];
16
18
  }
17
19
 
18
- paths (paths) {
19
- const pathsArr = Array.isArray(paths) ? paths : (typeof paths === 'string' ? [paths] : []);
20
+ paths(paths) {
21
+ const pathsArr = Array.isArray(paths)
22
+ ? paths
23
+ : typeof paths === "string"
24
+ ? [paths]
25
+ : [];
20
26
 
21
27
  if (pathsArr.length) {
22
28
  if (this.pathsArr.length) {
23
29
  this.map((basePath) => {
24
30
  return pathsArr.map((subPath) => {
25
31
  // If subpath starts with specia character "!" then prepend that to the begining of full paths
26
- const negativePath = subPath[0] === '!' ? '!' : '';
27
- const subPathNormalized = negativePath ? subPath.substr(1) : subPath;
28
- return negativePath + path.join(basePath, subPathNormalized);
32
+ const negativePath = subPath[0] === "!" ? "!" : "";
33
+ const subPathNormalized = negativePath
34
+ ? subPath.substr(1)
35
+ : subPath;
36
+
37
+ return (
38
+ negativePath +
39
+ path.join(basePath, subPathNormalized)
40
+ );
41
+ });
42
+ });
43
+
44
+ this.mapRaw((basePath) => {
45
+ return pathsArr.map((subPath) => {
46
+ // If subpath starts with specia character "!" then prepend that to the begining of full paths
47
+ const negativePath = subPath[0] === "!" ? "!" : "";
48
+ const subPathNormalized = negativePath
49
+ ? subPath.substr(1)
50
+ : subPath;
51
+
52
+ if (negativePath) {
53
+ this.isIgnore = true;
54
+ }
55
+
56
+ return (
57
+ negativePath +
58
+ path.join(basePath, subPathNormalized)
59
+ );
29
60
  });
30
61
  });
31
62
  } else {
32
63
  this.pathsArr = pathsArr;
64
+ this.pathsArrRaw = pathsArr;
33
65
  }
34
66
  } else {
35
67
  this.hadEmptyPaths = true;
@@ -44,23 +76,27 @@ class GlobObject {
44
76
  * @param {string|array} extensions An extension or list of extensions
45
77
  * @returns {object} GlobObject
46
78
  */
47
- filesWithExtensions (extensions) {
48
- const extensionsArr = typeof extensions === 'string' ? [extensions] : extensions;
79
+ filesWithExtensions(extensions) {
80
+ const extensionsArr =
81
+ typeof extensions === "string" ? [extensions] : extensions;
49
82
 
50
83
  if (extensionsArr && extensionsArr.length) {
51
- let extensionString = '';
84
+ let extensionString = "";
52
85
 
53
86
  // Remove dot from the extension name
54
- let extensionsArrNormalized = map(extensionsArr, (extension) => extension.replace(REGEX_DOT_PREFIX, ''));
87
+ let extensionsArrNormalized = map(extensionsArr, (extension) =>
88
+ extension.replace(REGEX_DOT_PREFIX, ""),
89
+ );
55
90
 
56
91
  if (extensionsArrNormalized.length > 1) {
57
- extensionString = `/**/*.{${ extensionsArrNormalized.join(',') }}`;
92
+ extensionString = `/**/*.{${extensionsArrNormalized.join(",")}}`;
58
93
  } else {
59
- extensionString = `/**/*.${ extensionsArrNormalized }`;
94
+ extensionString = `/**/*.${extensionsArrNormalized}`;
60
95
  }
61
96
 
62
- this.hasExtensions = true;
63
- return this.map((path) => `${ path }${ extensionString }`);
97
+ this.extensions = this.extensions.concat(extensionsArr);
98
+ this.hasExtensions = !!this.extensions.length > 0;
99
+ return this.map((path) => `${path}${extensionString}`);
64
100
  } else {
65
101
  return this;
66
102
  }
@@ -71,8 +107,9 @@ class GlobObject {
71
107
  *
72
108
  * @returns {object} GlobObject
73
109
  */
74
- allFiles () {
75
- return this.map((path) => `${ path }/**`);
110
+ allFiles() {
111
+ this.isAllFiles = true;
112
+ return this.map((path) => `${path}/**`);
76
113
  }
77
114
 
78
115
  /**
@@ -80,9 +117,23 @@ class GlobObject {
80
117
  *
81
118
  * @returns {object} GlobObject
82
119
  */
83
- ignore () {
120
+ ignore() {
84
121
  this.isIgnore = true;
85
- return this.map((path) => `!${ path }`);
122
+ return this.map((path) => `!${path}`);
123
+ }
124
+
125
+ /**
126
+ * Itterates through all paths
127
+ *
128
+ * @param {function} fn Itteratee function
129
+ * @returns {object} GlobObject
130
+ */
131
+ map(fn) {
132
+ this.pathsArr = filter(
133
+ flatten(map(this.pathsArr, fn)),
134
+ (path) => !!path,
135
+ );
136
+ return this;
86
137
  }
87
138
 
88
139
  /**
@@ -91,8 +142,11 @@ class GlobObject {
91
142
  * @param {function} fn Itteratee function
92
143
  * @returns {object} GlobObject
93
144
  */
94
- map (fn) {
95
- this.pathsArr = filter(flatten(map(this.pathsArr, fn)), (path) => !!path);
145
+ mapRaw(fn) {
146
+ this.pathsArrRaw = filter(
147
+ flatten(map(this.pathsArrRaw, fn)),
148
+ (path) => !!path,
149
+ );
96
150
  return this;
97
151
  }
98
152
 
@@ -101,13 +155,29 @@ class GlobObject {
101
155
  *
102
156
  * @returns {array} Array of glob paths
103
157
  */
104
- toArray () {
158
+ toArray() {
105
159
  if (this.hadEmptyPaths && this.isIgnore) {
106
160
  // Since we exclude files / paths, don't return anything if path list was empty
107
161
  return [];
108
162
  } else {
109
163
  return map(this.pathsArr, (path) => {
110
- return path.replace(REGEX_WINDOWS_BACKSLASH, '/');
164
+ return path.replace(REGEX_WINDOWS_BACKSLASH, "/");
165
+ });
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Converts paths to an array of normalized glob paths
171
+ *
172
+ * @returns {array} Array of glob paths
173
+ */
174
+ toArrayRaw() {
175
+ if (this.hadEmptyPaths && this.isIgnore) {
176
+ // Since we exclude files / paths, don't return anything if path list was empty
177
+ return [];
178
+ } else {
179
+ return map(this.pathsArrRaw, (path) => {
180
+ return path.replace(REGEX_WINDOWS_BACKSLASH, "/");
111
181
  });
112
182
  }
113
183
  }
@@ -117,17 +187,79 @@ class GlobObject {
117
187
  *
118
188
  * @returns {array} Array of glob paths
119
189
  */
120
- generate () {
121
- return this.toArray();
190
+ generate(forChokidar = false) {
191
+ if (forChokidar) {
192
+ const paths = this.toArrayRaw().map((path) =>
193
+ this.isAllFiles || this.hasExtensions ? path + "/." : path,
194
+ );
195
+
196
+ if (this.hadEmptyPaths && this.isIgnore) {
197
+ return {
198
+ paths: [],
199
+ ignore: [],
200
+ };
201
+ } else if (this.isIgnore) {
202
+ return {
203
+ paths: paths,
204
+ ignore: chokidarFilterIgnorePaths(this.toArrayRaw()),
205
+ };
206
+ } else if (this.hasExtensions) {
207
+ return {
208
+ paths: paths,
209
+ ignore: [chokidarFilterOnlyExtensions(this.extensions)],
210
+ };
211
+ } else {
212
+ return {
213
+ paths: paths,
214
+ ignore: [],
215
+ };
216
+ }
217
+ } else {
218
+ return this.toArray();
219
+ }
220
+ }
221
+ }
222
+
223
+ function paths(paths) {
224
+ return new GlobObject().paths(paths);
225
+ }
226
+
227
+ function generate(...globs) {
228
+ const isLastArgBoolean = typeof globs[globs.length - 1] === "boolean";
229
+ const forChokidar = isLastArgBoolean ? globs.pop() : false;
230
+
231
+ if (forChokidar) {
232
+ const results = map(flatten(globs), (glob) => glob.generate(true));
233
+
234
+ return {
235
+ paths: flatten(results.map((result) => result.paths)),
236
+ ignore: flatten(results.map((result) => result.ignore)),
237
+ };
238
+ } else {
239
+ return flatten(map(flatten(globs), (glob) => glob.generate(false)));
122
240
  }
123
241
  }
124
242
 
125
- function paths (paths) {
126
- return (new GlobObject()).paths(paths);
243
+ /**
244
+ * Create chokidar filter function to only allow certain extensions
245
+ * @param {array} extensions
246
+ * @returns {function}
247
+ */
248
+ function chokidarFilterOnlyExtensions(extensions) {
249
+ return function (path, _stats) {
250
+ return !extensions.some((extension) => path.endsWith(`.${extension}`));
251
+ };
127
252
  }
128
253
 
129
- function generate (...globs) {
130
- return flatten(map(flatten(globs), (glob) => glob.toArray()));
254
+ /**
255
+ * Create chokidar filter function to ignore certain paths
256
+ * @param {array} ignorePaths
257
+ * @returns {function}
258
+ */
259
+ function chokidarFilterIgnorePaths(ignorePaths) {
260
+ return function (path, _stats) {
261
+ return ignorePaths.some((ignorePath) => path.startsWith(ignorePath));
262
+ };
131
263
  }
132
264
 
133
265
  module.exports = {
@@ -1,21 +1,20 @@
1
- const gulp = require('gulp');
2
- const chokidar = require('chokidar');
3
- const debounce = require('just-debounce');
4
- const asyncDone = require('async-done');
5
-
1
+ const { parallel } = require("gulp");
2
+ const chokidar = require("chokidar");
3
+ const debounce = require("lodash/debounce");
4
+ const asyncDone = require("async-done");
6
5
 
7
6
  /**
8
7
  * Gulp task watch function using latest chokidar
9
8
  * with better OSX support and file watching functionality
10
9
  * than outdated gulp.watch
11
10
  */
12
- module.exports = function taskWatch (globs, callback) {
13
- const parallelCallback = gulp.parallel(callback);
14
- const debouncedCallback = debounce(onChange, 200);
11
+ module.exports = function taskWatch(globs, callback, isParallel = false) {
12
+ const parallelCallback = isParallel ? callback : parallel(callback);
13
+ const debouncedCallback = debounce(onChange, 120);
15
14
  let running = false;
16
15
  let queued = false;
17
16
 
18
- function onChange () {
17
+ function onChange() {
19
18
  if (running) {
20
19
  queued = true;
21
20
  } else {
@@ -23,7 +22,7 @@ module.exports = function taskWatch (globs, callback) {
23
22
  asyncDone(parallelCallback, runComplete);
24
23
  }
25
24
  }
26
- function runComplete (err) {
25
+ function runComplete(_err) {
27
26
  running = false;
28
27
 
29
28
  // If we have a run queued, start onChange again
@@ -33,10 +32,35 @@ module.exports = function taskWatch (globs, callback) {
33
32
  }
34
33
  }
35
34
 
36
- return chokidar.watch(globs, {
37
- ignoreInitial: true
38
- })
39
- .on('add', debouncedCallback)
40
- .on('change', debouncedCallback)
41
- .on('unlink', debouncedCallback);
35
+ // Re-check that file matches!
36
+ // This is needed because for ignore filter for extensions we allow filter to go through if there is no Stats object,
37
+ // otherwise `chokidar` will not emit `change` event for new filters and sub-folders.
38
+ // That's why we need to re-check here to make sure that file matches!
39
+ function isIgnoredPath(path) {
40
+ return globs.ignore.some((ignore) => ignore(path));
41
+ }
42
+
43
+ if (!globs.paths) {
44
+ throw new Error("No paths provided for chokidar watch");
45
+ }
46
+
47
+ return chokidar
48
+ .watch(globs.paths, {
49
+ ignoreInitial: true,
50
+ })
51
+ .on("add", (path) => {
52
+ if (!isIgnoredPath(path)) {
53
+ debouncedCallback(path);
54
+ }
55
+ })
56
+ .on("change", (path) => {
57
+ if (!isIgnoredPath(path)) {
58
+ debouncedCallback(path);
59
+ }
60
+ })
61
+ .on("unlink", (path) => {
62
+ if (!isIgnoredPath(path)) {
63
+ debouncedCallback(path);
64
+ }
65
+ });
42
66
  };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@videinfra/static-website-builder",
3
- "version": "1.17.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "description": "Customizable static site project builder",
5
5
  "license": "MIT",
6
6
  "engines": {
7
- "node": ">=14.15.0 <17"
7
+ "node": ">=20.0.0"
8
8
  },
9
9
  "bugs": {
10
10
  "url": "https://github.com/videinfra/static-website-builder/issues"
@@ -25,21 +25,17 @@
25
25
  "test-watch": "gulp --config=init/test/config/config.js"
26
26
  },
27
27
  "dependencies": {
28
- "@babel/core": "^7.21.8",
29
- "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
30
- "@babel/plugin-proposal-optional-chaining": "^7.21.0",
31
- "@babel/preset-env": "^7.21.5",
32
- "@csstools/postcss-nested-calc": "^3.0.0",
33
- "autoprefixer": "^10.4.14",
34
- "babel-loader": "^8.3.0",
35
- "browser-sync": "^2.29.3",
36
- "chalk": "4.0.0",
37
- "chokidar": "^3.5.3",
38
- "cross-env": "^7.0.3",
39
- "cssnano": "^6.0.1",
28
+ "@csstools/postcss-nested-calc": "^5.0.0",
29
+ "@rollup/plugin-replace": "^6.0.3",
30
+ "autoprefixer": "^10.4.23",
31
+ "browser-sync": "^3.0.4",
32
+ "chalk": "4.1.2",
33
+ "chokidar": "^5.0.0",
34
+ "cross-env": "^10.1.0",
35
+ "cssnano": "^7.1.2",
40
36
  "del": "^6.0.0",
41
- "dotenv": "^16.4.7",
42
- "gulp": "^4.0.2",
37
+ "dotenv": "^17.2.3",
38
+ "gulp": "^5.0.1",
43
39
  "gulp-cached": "^1.1.1",
44
40
  "gulp-data": "^1.3.1",
45
41
  "gulp-dependents": "^1.2.5",
@@ -47,25 +43,24 @@
47
43
  "gulp-if": "^3.0.0",
48
44
  "gulp-ignore": "^3.0.0",
49
45
  "gulp-plumber": "^1.2.1",
50
- "gulp-postcss": "^9.0.1",
46
+ "gulp-postcss": "^10.0.0",
51
47
  "gulp-sass": "^5.1.0",
52
48
  "gulp-sitemap": "^8.0.0",
53
49
  "gulp-sizereport": "^1.2.1",
54
- "gulp-sourcemaps": "^3.0.0",
50
+ "gulp-sourcemaps": "^2.6.5",
55
51
  "gulp-svgmin": "^4.1.0",
56
52
  "gulp-svgstore": "^9.0.0",
57
53
  "lodash.clone": "^4.3.2",
58
54
  "lodash.some": "^4.2.2",
59
55
  "map-stream": "^0.1.0",
60
56
  "minimist": "^1.2.8",
61
- "nano-memoize": "1.3.0",
62
- "sass": "^1.93.2",
57
+ "nano-memoize": "3.0.16",
58
+ "sass": "^1.97.3",
63
59
  "through": "^2.3.8",
64
- "twig": "^1.10.5",
65
- "webpack": "^4.46.0",
66
- "webpack-watch-files-plugin": "^1.2.1"
60
+ "twig": "^1.17.1"
67
61
  },
68
62
  "devDependencies": {
69
- "jest": "^29.6.2"
63
+ "jest": "^30.2.0",
64
+ "rolldown": "^1.0.0-rc.1"
70
65
  }
71
66
  }
@@ -1,5 +1,5 @@
1
1
  const gulp = require('gulp');
2
- const memoize = require('nano-memoize');
2
+ const { nanomemoize } = require('nano-memoize');
3
3
 
4
4
  const globs = require('@videinfra/example-website-builder/lib/globs-helper');
5
5
  const getConfig = require('@videinfra/example-website-builder/lib/get-config');
@@ -12,7 +12,7 @@ const taskWatch = require('../../lib/gulp/task-watch');
12
12
 
13
13
  // Paths and files which gulp will watch and run on
14
14
  // Using memoize to cache the result, for performance
15
- const getGlobPaths = memoize(function () {
15
+ const getWatchGlobPaths = function (forChokidar = false) {
16
16
  const sourcePaths = getPaths.getSourcePaths('example');
17
17
  const extensions = getConfig.getTaskConfig('example', 'extensions');
18
18
  const ignore = getConfig.getTaskConfig('example', 'ignore');
@@ -22,6 +22,9 @@ const getGlobPaths = memoize(function () {
22
22
  globs.paths(sourcePaths).filesWithExtensions(extensions), // Files to watch
23
23
  globs.paths(sourcePaths).paths(ignore).ignore(), // Exclude files and folders from being processed
24
24
  );
25
+ };
26
+ const getGlobPaths = nanomemoize(function () {
27
+ return getWatchGlobPaths(false);
25
28
  });
26
29
 
27
30
 
@@ -41,7 +44,7 @@ function example () {
41
44
  }
42
45
 
43
46
  function exampleWatch () {
44
- return taskWatch(getGlobPaths(), example);
47
+ return taskWatch(getWatchGlobPaths(true), example);
45
48
  }
46
49
 
47
50
 
@@ -30,10 +30,5 @@ module.exports = function preprocessBrowserSyncConfig (config = {}, fullConfig)
30
30
  }
31
31
  }
32
32
 
33
- // Set additional files to watch, convert file paths to globs
34
- if (config.files) {
35
- config.files = globs.paths(getPaths.getProjectPath()).paths(files).generate();
36
- }
37
-
38
33
  return config;
39
34
  }
@@ -4,3 +4,6 @@ const getConfig = require('./../../lib/get-config');
4
4
  exports.watch = function browserSync (callback) {
5
5
  bs.init(getConfig.getTaskConfig('browserSync'));
6
6
  };
7
+
8
+ // Execute as first task
9
+ exports.watch.order = -2;
@@ -36,7 +36,8 @@ function getEnvData () {
36
36
  // dotenv file order is reversed, values in first file overwrite all other
37
37
  // file values
38
38
  path: envFiles.reverse(),
39
- processEnv: envVariables
39
+ processEnv: envVariables,
40
+ quiet: true,
40
41
  });
41
42
 
42
43
  // Remap property names