@videinfra/static-website-builder 1.11.0 → 1.12.0

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
+ ## [1.12.0] - 2024-02-25
8
+ ### Added
9
+ - Support for multiple entry lists which each has its own "shared" chunk file
10
+
11
+ ## [1.11.1] - 2024-02-24
12
+ ### Fixed
13
+ - Fixed dependencies
14
+
7
15
  ## [1.11.0] - 2024-02-24
8
16
  ### Updated
9
17
  - Added dynamic entries, webpack will rebuild when entries change
@@ -3,6 +3,7 @@ const assign = require('lodash/assign');
3
3
  const filter = require('lodash/filter');
4
4
  const { series, parallel } = require('gulp');
5
5
  const { DEFAULT_TASKS, BUILD_TASKS } = require('./task-order');
6
+ const resolveDynamicTask = require('./gulp/resolve-dynamic-task');
6
7
 
7
8
 
8
9
  /**
@@ -28,16 +29,16 @@ function generateTaskList (taskConfig) {
28
29
 
29
30
  // Create individual tasks, which can be run separatelly
30
31
  for (let gulpTaskName in gulpTaskList) {
31
- taskList.separate[`${ taskName }-${ gulpTaskName }`] = gulpTaskList[gulpTaskName];
32
+ taskList.separate[`${ taskName }-${ gulpTaskName }`] = resolveDynamicTask(gulpTaskList[gulpTaskName]);
32
33
  }
33
34
 
34
35
  for (let t = 0; t < DEFAULT_TASKS.length; t++) {
35
36
  if (DEFAULT_TASKS[t] in gulpTaskList) {
36
- const gulpTask = gulpTaskList[DEFAULT_TASKS[t]];
37
+ const gulpTask = resolveDynamicTask(gulpTaskList[DEFAULT_TASKS[t]]);
37
38
  taskList.default[t].push(gulpTask);
38
39
  }
39
40
  if (BUILD_TASKS[t] in gulpTaskList) {
40
- const gulpTask = gulpTaskList[BUILD_TASKS[t]];
41
+ const gulpTask = resolveDynamicTask(gulpTaskList[BUILD_TASKS[t]]);
41
42
  taskList.build[t].push(gulpTask);
42
43
  }
43
44
  }
package/lib/get-config.js CHANGED
@@ -1,157 +1,157 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const getPath = require('./get-path');
4
- const runPreprocess = require('./run-preprocess');
5
- const merge = require('./merge');
6
- const logError = require('./log-error');
7
-
8
- const each = require('lodash/each');
9
- const omit = require('lodash/omit');
10
- const isPlainObject = require('lodash/isPlainObject');
11
- const isArray = require('lodash/isArray');
12
- const reduce = require('lodash/reduce');
13
- const get = require('lodash/get');
14
-
15
-
16
- /**
17
- * Returns builder and project specific task and plugin configurations combined
18
- * Configuration is preprocessed
19
- *
20
- * @returns {object} Task configurations
21
- */
22
-
23
- let taskConfig = null;
24
-
25
- function getConfig (builderConfigFile) {
26
- if (!taskConfig) {
27
- // Load all task configs
28
- taskConfig = itterateConfig(loadConfig(), mergeConfigMode);
29
-
30
- // 1. First load project specific config.js
31
- const projectConfigPath = getPath.getProjectPath(builderConfigFile);
32
- let projectTaskConfig = {};
33
- let hasProjectConfigFile = true;
34
-
35
- try {
36
- fs.accessSync(projectConfigPath);
37
- } catch (err) {
38
- logError({'plugin': 'static-website-builder', 'message': `Couldn't find configuration file "${ projectConfigPath }"`});
39
- hasProjectConfigFile = false;
40
- }
41
-
42
- if (hasProjectConfigFile) {
43
- projectTaskConfig = itterateConfig(require(projectConfigPath), mergeConfigMode);
44
- }
45
-
46
- // 2. Marge plugins into the config, each plugin is just a config
47
- const plugins = (taskConfig.plugins || []).concat(projectTaskConfig.plugins || []);
48
- if (plugins) {
49
- taskConfig.plugins = null;
50
- projectTaskConfig.plugins = null;
51
-
52
- each(plugins, (plugin) => {
53
- taskConfig = merge(taskConfig, itterateConfig(plugin, mergeConfigMode));
54
- });
55
- }
56
-
57
- // 3. Only after plugins has been executed, merge project specific config.js into main config
58
- if (projectTaskConfig) {
59
- taskConfig = merge(taskConfig, projectTaskConfig);
60
- }
61
-
62
- // 4. Preprocess
63
- taskConfig = runPreprocess(taskConfig);
64
- }
65
-
66
- return taskConfig;
67
- };
68
-
69
- /**
70
- * Returns task sub-config by path
71
- *
72
- * @param {...string} path Path to the sub-config
73
- * @returns {any} Task sub-config
74
- */
75
- function getTaskConfig (...path) {
76
- return get(getConfig(), path, null);
77
- }
78
-
79
- /**
80
- * Itterate over each config property and call function on
81
- * each object or array
82
- *
83
- * @param {*} object
84
- * @param {*} fn
85
- * @protected
86
- */
87
- function itterateConfig (config, fn) {
88
- if (config === false) return false;
89
- const base = isPlainObject(config) ? {} : [];
90
-
91
- return reduce(config, (object, value, key) => {
92
- if (isPlainObject(value)) {
93
- object[key]= itterateConfig(fn(value), fn);
94
- } else if (isArray(value)) {
95
- object[key]= itterateConfig(value, fn);
96
- } else {
97
- object[key] = value;
98
- }
99
-
100
- return object;
101
- }, base);
102
- }
103
-
104
- /**
105
- * Merge 'production' or 'development' mode sub-ojbects into an object and remove
106
- * mode sub-objects
107
- *
108
- * @param {object} config Config
109
- * @returns {object} Config
110
- * @protected
111
- */
112
- function mergeConfigMode (config) {
113
- if ('production' in config || 'development' in config) {
114
- const mode = global.production ? 'production' : 'development';
115
- const value = merge(config, config[mode]);
116
-
117
- if (value !== false) {
118
- return omit(value, ['production', 'development']);
119
- } else {
120
- return value;
121
- }
122
- } else {
123
- return config;
124
- }
125
- }
126
-
127
- /**
128
- * Load config files
129
- *
130
- * @returns {object} Configuration
131
- * @protected
132
- */
133
- function loadConfig () {
134
- const taskFolder = path.resolve(__dirname, '../tasks');
135
- let taskConfig = {};
136
-
137
- fs.readdirSync(taskFolder).forEach(folderName => {
138
- // Ignore task folders which start with underscore
139
- if (folderName[0] !== '_') {
140
- const configFileName = path.resolve(taskFolder, folderName, 'config.js');
141
-
142
- try {
143
- fs.accessSync(configFileName);
144
- } catch (err) {
145
- return;
146
- }
147
-
148
- taskConfig = merge(taskConfig, require(configFileName));
149
- }
150
- });
151
-
152
- return taskConfig;
153
- };
154
-
155
-
156
- exports.getConfig = getConfig;
157
- exports.getTaskConfig = getTaskConfig;
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const getPath = require('./get-path');
4
+ const runPreprocess = require('./run-preprocess');
5
+ const merge = require('./merge');
6
+ const logError = require('./log-error');
7
+
8
+ const each = require('lodash/each');
9
+ const omit = require('lodash/omit');
10
+ const isPlainObject = require('lodash/isPlainObject');
11
+ const isArray = require('lodash/isArray');
12
+ const reduce = require('lodash/reduce');
13
+ const get = require('lodash/get');
14
+
15
+
16
+ /**
17
+ * Returns builder and project specific task and plugin configurations combined
18
+ * Configuration is preprocessed
19
+ *
20
+ * @returns {object} Task configurations
21
+ */
22
+
23
+ let taskConfig = null;
24
+
25
+ function getConfig (builderConfigFile) {
26
+ if (!taskConfig) {
27
+ // Load all task configs
28
+ taskConfig = itterateConfig(loadConfig(), mergeConfigMode);
29
+
30
+ // 1. First load project specific config.js
31
+ const projectConfigPath = getPath.getProjectPath(builderConfigFile);
32
+ let projectTaskConfig = {};
33
+ let hasProjectConfigFile = true;
34
+
35
+ try {
36
+ fs.accessSync(projectConfigPath);
37
+ } catch (err) {
38
+ logError({'plugin': 'static-website-builder', 'message': `Couldn't find configuration file "${ projectConfigPath }"`});
39
+ hasProjectConfigFile = false;
40
+ }
41
+
42
+ if (hasProjectConfigFile) {
43
+ projectTaskConfig = itterateConfig(require(projectConfigPath), mergeConfigMode);
44
+ }
45
+
46
+ // 2. Marge plugins into the config, each plugin is just a config
47
+ const plugins = (taskConfig.plugins || []).concat(projectTaskConfig.plugins || []);
48
+ if (plugins) {
49
+ taskConfig.plugins = null;
50
+ projectTaskConfig.plugins = null;
51
+
52
+ each(plugins, (plugin) => {
53
+ taskConfig = merge(taskConfig, itterateConfig(plugin, mergeConfigMode));
54
+ });
55
+ }
56
+
57
+ // 3. Only after plugins has been executed, merge project specific config.js into main config
58
+ if (projectTaskConfig) {
59
+ taskConfig = merge(taskConfig, projectTaskConfig);
60
+ }
61
+
62
+ // 4. Preprocess
63
+ taskConfig = runPreprocess(taskConfig);
64
+ }
65
+
66
+ return taskConfig;
67
+ };
68
+
69
+ /**
70
+ * Returns task sub-config by path
71
+ *
72
+ * @param {...string} path Path to the sub-config
73
+ * @returns {any} Task sub-config
74
+ */
75
+ function getTaskConfig (...path) {
76
+ return get(getConfig(), path, null);
77
+ }
78
+
79
+ /**
80
+ * Itterate over each config property and call function on
81
+ * each object or array
82
+ *
83
+ * @param {*} object
84
+ * @param {*} fn
85
+ * @protected
86
+ */
87
+ function itterateConfig (config, fn) {
88
+ if (config === false) return false;
89
+ const base = isPlainObject(config) ? {} : [];
90
+
91
+ return reduce(config, (object, value, key) => {
92
+ if (isPlainObject(value)) {
93
+ object[key]= itterateConfig(fn(value), fn);
94
+ } else if (isArray(value)) {
95
+ object[key]= itterateConfig(value, fn);
96
+ } else {
97
+ object[key] = value;
98
+ }
99
+
100
+ return object;
101
+ }, base);
102
+ }
103
+
104
+ /**
105
+ * Merge 'production' or 'development' mode sub-ojbects into an object and remove
106
+ * mode sub-objects
107
+ *
108
+ * @param {object} config Config
109
+ * @returns {object} Config
110
+ * @protected
111
+ */
112
+ function mergeConfigMode (config) {
113
+ if ('production' in config || 'development' in config) {
114
+ const mode = global.production ? 'production' : 'development';
115
+ const value = merge(config, config[mode]);
116
+
117
+ if (value !== false) {
118
+ return omit(value, ['production', 'development']);
119
+ } else {
120
+ return value;
121
+ }
122
+ } else {
123
+ return config;
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Load config files
129
+ *
130
+ * @returns {object} Configuration
131
+ * @protected
132
+ */
133
+ function loadConfig () {
134
+ const taskFolder = path.resolve(__dirname, '../tasks');
135
+ let taskConfig = {};
136
+
137
+ fs.readdirSync(taskFolder).forEach(folderName => {
138
+ // Ignore task folders which start with underscore
139
+ if (folderName[0] !== '_') {
140
+ const configFileName = path.resolve(taskFolder, folderName, 'config.js');
141
+
142
+ try {
143
+ fs.accessSync(configFileName);
144
+ } catch (err) {
145
+ return;
146
+ }
147
+
148
+ taskConfig = merge(taskConfig, require(configFileName));
149
+ }
150
+ });
151
+
152
+ return taskConfig;
153
+ };
154
+
155
+
156
+ exports.getConfig = getConfig;
157
+ exports.getTaskConfig = getTaskConfig;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Similar to parallel() and serial() but instead of getting tasks immediatelly
3
+ * it's executed after config has been loaded
4
+ */
5
+ module.exports = function dynamicTask (fn) {
6
+ fn.dynamicTasks = true;
7
+ return fn;
8
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Similar to parallel() and serial() but instead of getting tasks immediatelly
3
+ * it's executed after config has been loaded
4
+ */
5
+ module.exports = function resolveDynamicTask (fn) {
6
+ if (fn.dynamicTasks) {
7
+ return fn();
8
+ } else {
9
+ return fn;
10
+ }
11
+ }
@@ -19,7 +19,7 @@ module.exports = function runPreprocess (taskConfig) {
19
19
  if (newTaskConfig === false) {
20
20
  taskConfig[taskName] = false;
21
21
  break;
22
- } else if (newTaskConfig && isPlainObject(newTaskConfig)) {
22
+ } else if (newTaskConfig && (isPlainObject(newTaskConfig) || Array.isArray(newTaskConfig))) {
23
23
  // Safeguard against empty values
24
24
  taskConfig[taskName] = newTaskConfig;
25
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@videinfra/static-website-builder",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Customizable static site project builder",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -50,11 +50,14 @@
50
50
  "gulp-sourcemaps": "^3.0.0",
51
51
  "gulp-svgmin": "^4.1.0",
52
52
  "gulp-svgstore": "^9.0.0",
53
+ "lodash.clone": "^4.3.2",
54
+ "lodash.some": "^4.2.2",
53
55
  "map-stream": "^0.1.0",
54
56
  "minimist": "^1.2.8",
55
57
  "nano-memoize": "1.3.0",
56
58
  "node-sass": "^7.0.3",
57
59
  "sass": "^1.65.1",
60
+ "through": "^2.3.8",
58
61
  "twig": "^1.10.5",
59
62
  "webpack": "^4.46.0",
60
63
  "webpack-watch-files-plugin": "^1.2.1"
@@ -7,7 +7,15 @@ exports.javascripts = {
7
7
  extensions: ['js', 'json'],
8
8
 
9
9
  // Instead of 'entry' we provide filename which list all entries
10
- entryList: '_entries.js',
10
+ // Can be either an object or array of object to have multiple webpack
11
+ // build, one for each of the entry list files
12
+ entryList: {
13
+ // Path to the entry list file
14
+ name: '_entries.js',
15
+
16
+ // Entry shared chunk name, creates webpack.optimization chunks
17
+ shared: 'shared',
18
+ },
11
19
 
12
20
  // Webpack configuration
13
21
  // see https://webpack.js.org/configuration/
@@ -33,8 +41,11 @@ exports.javascripts = {
33
41
  ],
34
42
  },
35
43
 
44
+ // Default optimization, 'shared' will be overwritten by entryList.shared value
36
45
  optimization: {
37
- runtimeChunk: {name: 'shared'},
46
+ runtimeChunk: {
47
+ name: 'shared'
48
+ },
38
49
  splitChunks: {
39
50
  cacheGroups: {
40
51
  default: false,
@@ -2,6 +2,7 @@ const paths = require('../../lib/get-path');
2
2
  const merge = require('../../lib/merge');
3
3
  const get = require('lodash/get');
4
4
  const map = require('lodash/map');
5
+ const cloneDeep = require('lodash/cloneDeep');
5
6
  const webpack = require('webpack');
6
7
  const WatchExternalFilesPlugin = require('webpack-watch-files-plugin');
7
8
 
@@ -22,32 +23,10 @@ function requireUncached(module) {
22
23
  * @returns {object} List of entry files
23
24
  */
24
25
  function getEntry (config) {
25
- const entryFile = paths.getSourcePath('javascripts', config.entryList);
26
-
27
- // console.log(require(entryFile));
28
- // return () => {
29
- // return new Promise((resolve) => {
30
- // resolve(require(entryFile));
31
- // });
32
- // };
33
-
34
- // return () => new Promise((resolve) => {
35
- // resolve(['./demo', './demo2'])
36
- // });
26
+ const entryFile = paths.getSourcePath('javascripts', config.entryList.name);
37
27
 
38
28
  return function getEntries () {
39
- // const entryURL = pathToFileURL(entryFile).href + '?_invalidate-cache=' + (++entriesCounter);
40
-
41
- // console.log(require.cache.);
42
- // console.log('loading entries:', entryURL);
43
- // return import(entryURL).then((entries) => {
44
- // console.log('loaded entries:', entries.default);
45
- // return entries.default;
46
- // });
47
-
48
- const entries = requireUncached(entryFile);
49
- console.log('entries:', entries);
50
- return entries;
29
+ return requireUncached(entryFile);
51
30
  }
52
31
  }
53
32
 
@@ -65,56 +44,124 @@ module.exports = function preprocessJavascriptsConfig (config, fullConfig) {
65
44
  webpackPlugins = webpackPlugins(webpack);
66
45
  }
67
46
 
68
- return merge(config, {
69
- webpack: {
70
- mode: global.production ? 'production' : 'development',
71
-
72
- // Input files
73
- context: paths.getSourcePath('javascripts'),
74
- entry: getEntry(config),
75
-
76
- // Output folder
77
- output: merge({
78
- path: paths.getDestPath('javascripts'),
79
- publicPath: paths.getPublicPath('javascripts'),
80
- }, get(config, ['webpack', 'output'], null)),
81
-
82
- // Plugins, add ENV variables
83
- plugins: [
84
- new webpack.DefinePlugin({
85
- 'process.env.NODE_ENV': JSON.stringify(global.production ? 'production' : 'development'),
86
- }),
87
- new WatchExternalFilesPlugin.default({
88
- verbose: false,
89
- files: [
90
- paths.getSourcePath('javascripts', config.entryList),
47
+ // User may specify a function, execute it to get object / array
48
+ if (typeof config.entryList === 'function') {
49
+ config.entryList = config.entryList(config);
50
+ }
51
+
52
+ // User may specify multiple entry list files, convert to array
53
+ if (!Array.isArray(config.entryList)) {
54
+ config.entryList = [config.entryList];
55
+ }
56
+
57
+ // User may specify only a name of the entry file
58
+ // Set shared chunk name for each of the entry files
59
+ // Each entryList item is { name: '...', shared: '...' }
60
+ config.entryList = config.entryList.map((entry, index) => {
61
+ return {
62
+ name: typeof entry === 'string' ? entry : entry.name,
63
+ shared: typeof entry !== 'string' && entry && entry.shared ? entry.shared : (index === 0 ? 'shared' : ''),
64
+ };
65
+ });
66
+
67
+ return config.entryList.map((entryList) => {
68
+ const entryConfig = Object.assign({}, config);
69
+ entryConfig.webpack = Object.assign({}, entryConfig.webpack);
70
+
71
+ // One entry file per config
72
+ entryConfig.entryList = entryList;
73
+
74
+ const buildConfig = merge(entryConfig, {
75
+ webpack: {
76
+ mode: global.production ? 'production' : 'development',
77
+
78
+ // Input files
79
+ context: paths.getSourcePath('javascripts'),
80
+ entry: getEntry(entryConfig),
81
+
82
+ // Output folder
83
+ output: merge({
84
+ path: paths.getDestPath('javascripts'),
85
+ publicPath: paths.getPublicPath('javascripts'),
86
+ }, get(entryConfig, ['webpack', 'output'], null)),
87
+
88
+ // Plugins, add ENV variables
89
+ plugins: [
90
+ new webpack.DefinePlugin({
91
+ 'process.env.NODE_ENV': JSON.stringify(global.production ? 'production' : 'development'),
92
+ }),
93
+ new WatchExternalFilesPlugin.default({
94
+ verbose: false,
95
+ files: [
96
+ paths.getSourcePath('javascripts', entryList.name),
97
+ ],
98
+ }),
99
+ ].concat(webpackPlugins),
100
+
101
+ // Imports
102
+ resolve: merge({
103
+ // File extensions
104
+ extensions: map(entryConfig.extensions, (extension) => `.${ extension }`),
105
+
106
+ // Import folders
107
+ modules: [
108
+ // Allow imports from node_modules
109
+ paths.getProjectPath('node_modules'),
110
+
111
+ // Allow imports from source folder
112
+ paths.getSourcePath('javascripts'),
91
113
  ],
92
- }),
93
- ].concat(webpackPlugins),
94
-
95
- // Imports
96
- resolve: merge({
97
- // File extensions
98
- extensions: map(config.extensions, (extension) => `.${ extension }`),
99
-
100
- // Import folders
101
- modules: [
102
- // Allow imports from node_modules
103
- paths.getProjectPath('node_modules'),
104
-
105
- // Allow imports from source folder
106
- paths.getSourcePath('javascripts'),
107
- ],
108
- }, get(config, ['webpack', 'resolve'], null)),
109
-
110
- // Loader imports
111
- resolveLoader: {
112
- modules: [
113
- // Allow imports from node_modules
114
- paths.getBuilderPath('node_modules'),
115
- paths.getProjectPath('node_modules'),
116
- ]
117
- },
114
+ }, get(entryConfig, ['webpack', 'resolve'], null)),
115
+
116
+ // Loader imports
117
+ resolveLoader: {
118
+ modules: [
119
+ // Allow imports from node_modules
120
+ paths.getBuilderPath('node_modules'),
121
+ paths.getProjectPath('node_modules'),
122
+ ]
123
+ },
124
+ }
125
+ });
126
+
127
+ // Add webpack.optimization.runtimeChunk and webpack.optimization.splitChunks,
128
+ // if entryConfig.shared doesn't exist, then remove them
129
+ if (entryList.shared && entryList.shared !== 'shared') {
130
+ const optimization = buildConfig.webpack.optimization = cloneDeep(buildConfig.webpack.optimization || {});
131
+
132
+ if (get(optimization, ['runtimeChunk', 'name'], null) === 'shared') {
133
+ // Change shared runtimeChunk name
134
+ optimization.runtimeChunk.name = entryList.shared;
135
+ } else if (!optimization.runtimeChunk) {
136
+ // Add shared runtimeChunk
137
+ optimization.runtimeChunk = {
138
+ name: entryList.shared,
139
+ };
140
+ }
141
+
142
+ if ('shared' in get(optimization, ['splitChunks', 'cacheGroups'], {})) {
143
+ // Rename split chunks "shared" chunk
144
+ const cacheGroups = optimization.splitChunks.cacheGroups.shared;
145
+ delete(optimization.splitChunks.cacheGroups.shared);
146
+ optimization.splitChunks.cacheGroups[entryList.shared] = cacheGroups;
147
+ cacheGroups.name = entryList.shared;
148
+ } else if (!optimization.splitChunks) {
149
+ // Add splitChunks
150
+ optimization.splitChunks = optimization.splitChunks || {};
151
+ optimization.splitChunks.cacheGroups = optimization.splitChunks.cacheGroups || {};
152
+ optimization.splitChunks.cacheGroups[entryList.shared] = {
153
+ name: entryList.shared,
154
+ chunks: 'all',
155
+ minChunks: 3,
156
+ enforce: true,
157
+ };
158
+ }
159
+ } else if (!entryList.shared) {
160
+ // Remove optimization
161
+ delete(buildConfig.webpack.optimization);
118
162
  }
163
+
164
+ return buildConfig;
119
165
  });
166
+
120
167
  }
@@ -1,4 +1,5 @@
1
1
  const gulp = require('gulp');
2
+ const { parallel } = require('gulp');
2
3
  const webpack = require('webpack');
3
4
  const gulpWebpack = require('../../vendor/webpack-stream/index.js');
4
5
  const memoize = require('nano-memoize');
@@ -11,12 +12,12 @@ const getConfig = require('./../../lib/get-config');
11
12
  const taskStart = require('../../lib/gulp/task-start');
12
13
  const taskEnd = require('../../lib/gulp/task-end');
13
14
  const taskBeforeDest = require('../../lib/gulp/task-before-dest');
14
-
15
+ const dynamicTask = require('../../lib/gulp/dynamic-task');
15
16
 
16
17
  const getGlobPaths = memoize(function () {
17
18
  const sourcePaths = getPaths.getSourcePaths('javascripts');
18
- const extensions = getConfig.getTaskConfig('javascripts', 'webpack', 'resolve', 'extensions');
19
- const ignore = getConfig.getTaskConfig('javascripts', 'ignore');
19
+ const extensions = getConfig.getTaskConfig('javascripts', '0', 'webpack', 'resolve', 'extensions');
20
+ const ignore = getConfig.getTaskConfig('javascripts', '0', 'ignore');
20
21
 
21
22
  return globs.generate(
22
23
  globs.paths(sourcePaths).filesWithExtensions(extensions), // Files to watch
@@ -26,19 +27,42 @@ const getGlobPaths = memoize(function () {
26
27
 
27
28
 
28
29
  function javascripts (watch) {
29
- return gulp.src(getGlobPaths())
30
- .pipe(taskStart())
30
+ const configs = getConfig.getTaskConfig('javascripts');
31
+
32
+ // Configs is an array, for each of the entry files separate config is created
33
+ const tasks = configs.map(function (config, index) {
34
+ // Gulp task function
35
+ const fn = function () {
36
+ return gulp.src(getGlobPaths())
37
+ .pipe(taskStart())
38
+
39
+ .pipe(gulpWebpack(
40
+ merge(config.webpack, {'watch': watch === true}),
41
+ webpack
42
+ ))
43
+
44
+ .pipe(taskBeforeDest())
45
+ .pipe(gulp.dest(getPaths.getDestPath('javascripts')))
31
46
 
32
- .pipe(gulpWebpack(
33
- merge(getConfig.getTaskConfig('javascripts', 'webpack'), {'watch': watch === true}),
34
- webpack
35
- ))
47
+ // Reload on change
48
+ .pipe(taskEnd());
49
+ };
36
50
 
37
- .pipe(taskBeforeDest())
38
- .pipe(gulp.dest(getPaths.getDestPath('javascripts')))
51
+ // Set name of the gulp task function, currently it doesn't have a name yet
52
+ // This is needed so that name appears in terminal when running build
53
+ let name = 'javascripts' + (watch ? 'Watch' : '');
39
54
 
40
- // Reload on change
41
- .pipe(taskEnd());
55
+ if (configs.length > 1) {
56
+ let entryFileName = config.entryList.name.replace('.json', '').replace('.js', '');
57
+ name += entryFileName[0].toUpperCase() + entryFileName.slice(1);
58
+ }
59
+
60
+ Object.defineProperty(fn, 'name', { value: name });
61
+
62
+ return fn;
63
+ });
64
+
65
+ return parallel(...tasks);
42
66
  }
43
67
 
44
68
  function javascriptsWatch () {
@@ -46,6 +70,6 @@ function javascriptsWatch () {
46
70
  return javascripts(true);
47
71
  }
48
72
 
49
-
50
- exports.build = javascripts;
51
- exports.watch = javascriptsWatch;
73
+ // Dynamic task will be executed when config is ready and must return gulp tasks
74
+ exports.build = dynamicTask(javascripts);
75
+ exports.watch = dynamicTask(javascriptsWatch);
@@ -45,8 +45,9 @@ test('Preprocess returning non-object should result in same config config', () =
45
45
  const configString = {'task': {'a': 1}, 'preprocess': {'task': [() => 'string']}};
46
46
  expect(runPreprocess(configString).task).toEqual({'a': 1});
47
47
 
48
+ // Task config can be an array, this is used for javascripts
48
49
  const configArray = {'task': {'a': 1}, 'preprocess': {'task': [() => ['a', 'b']]}};
49
- expect(runPreprocess(configArray).task).toEqual({'a': 1});
50
+ expect(runPreprocess(configArray).task).toEqual(['a', 'b']);
50
51
  });
51
52
 
52
53
  test('Preprocess returning false shouldn\'t call other preprocesses', () => {