@oroinc/oro-webpack-config-builder 5.1.0-alpha3 → 5.1.0-alpha30
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/README.md +1 -1
- package/messages.js +29 -0
- package/modules-config/layout-modules-config-loader.js +62 -2
- package/modules-config/modules-config-loader.js +32 -14
- package/oro-webpack-config.js +361 -298
- package/package.json +29 -26
- package/prepare-modules-shim.js +13 -1
- package/style/admin-style-loader.js +22 -0
- package/style/layout-style-loader.js +12 -109
- package/style/style-loader.js +130 -46
- package/theme-config-factory.js +48 -5
- package/writer/configs-file-writer.js +1 -1
- package/writer/dynamic-imports-file-writer.js +3 -3
package/package.json
CHANGED
|
@@ -1,46 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oroinc/oro-webpack-config-builder",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-alpha30",
|
|
4
4
|
"author": "Oro, Inc (https://www.oroinc.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "An integration of OroPlatform based applications with the Webpack.",
|
|
7
7
|
"main": "oro-webpack-config.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@babel/core": "^7.
|
|
10
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
11
|
-
"@babel/preset-env": "^7.
|
|
12
|
-
"autoprefixer": "^
|
|
13
|
-
"babel-loader": "^8.
|
|
14
|
-
"
|
|
15
|
-
"css-
|
|
9
|
+
"@babel/core": "^7.16.0",
|
|
10
|
+
"@babel/plugin-transform-runtime": "^7.16.0",
|
|
11
|
+
"@babel/preset-env": "^7.16.0",
|
|
12
|
+
"autoprefixer": "^10.4.0",
|
|
13
|
+
"babel-loader": "^8.2.3",
|
|
14
|
+
"bindings": "^1.5.0",
|
|
15
|
+
"css-loader": "^6.5.1",
|
|
16
|
+
"css-minimizer-webpack-plugin": "^3.1.3",
|
|
16
17
|
"deepmerge": "^4.2.2",
|
|
17
|
-
"exports-loader": "^
|
|
18
|
-
"expose-loader": "^
|
|
18
|
+
"exports-loader": "^3.1.0",
|
|
19
|
+
"expose-loader": "^3.1.0",
|
|
19
20
|
"extract-loader": "^5.1.0",
|
|
20
21
|
"file-loader": "^6.2.0",
|
|
21
22
|
"happypack": "^5.0.1",
|
|
22
|
-
"html-webpack-plugin": "^5.
|
|
23
|
-
"imports-loader": "^
|
|
24
|
-
"js-yaml": "^4.
|
|
25
|
-
"mini-css-extract-plugin": "^
|
|
23
|
+
"html-webpack-plugin": "^5.5.0",
|
|
24
|
+
"imports-loader": "^3.1.1",
|
|
25
|
+
"js-yaml": "^4.1.0",
|
|
26
|
+
"mini-css-extract-plugin": "^2.4.4",
|
|
26
27
|
"minimist": "^1.2.3",
|
|
28
|
+
"nan": "^2.15.0",
|
|
27
29
|
"path": "0.12.7",
|
|
28
|
-
"postcss": "^8.
|
|
29
|
-
"postcss-loader": "^
|
|
30
|
+
"postcss": "^8.3.11",
|
|
31
|
+
"postcss-loader": "^6.2.0",
|
|
30
32
|
"printf": "^0.6.0",
|
|
33
|
+
"resolve-url-loader": "^4.0.0",
|
|
31
34
|
"rtlcss-webpack-plugin": "^4.0.6",
|
|
32
|
-
"sass": "^1.
|
|
33
|
-
"sass-loader": "^
|
|
34
|
-
"style-loader": "^
|
|
35
|
-
"terser": "^5.
|
|
35
|
+
"sass": "^1.43.4",
|
|
36
|
+
"sass-loader": "^12.3.0",
|
|
37
|
+
"style-loader": "^3.3.1",
|
|
38
|
+
"terser": "^5.9.0",
|
|
36
39
|
"text-loader": "0.0.1",
|
|
37
|
-
"underscore": "^1.
|
|
40
|
+
"underscore": "^1.13.1",
|
|
38
41
|
"url-loader": "^4.1.1",
|
|
39
|
-
"webpack": "^5.
|
|
40
|
-
"webpack-bundle-analyzer": "^4.
|
|
41
|
-
"webpack-cli": "^4.
|
|
42
|
-
"webpack-dev-server": "^
|
|
43
|
-
"webpack-merge": "^5.
|
|
42
|
+
"webpack": "^5.63.0",
|
|
43
|
+
"webpack-bundle-analyzer": "^4.5.0",
|
|
44
|
+
"webpack-cli": "^4.9.1",
|
|
45
|
+
"webpack-dev-server": "^4.4.0",
|
|
46
|
+
"webpack-merge": "^5.8.0",
|
|
44
47
|
"wildcard": "^2.0.0"
|
|
45
48
|
}
|
|
46
49
|
}
|
package/prepare-modules-shim.js
CHANGED
|
@@ -12,7 +12,19 @@ module.exports = (resolver, config) => {
|
|
|
12
12
|
|
|
13
13
|
// convert to imports-loader? syntax
|
|
14
14
|
if (imports && imports.length) {
|
|
15
|
-
|
|
15
|
+
let importParams = Object.assign(
|
|
16
|
+
{
|
|
17
|
+
type: 'commonjs',
|
|
18
|
+
imports: imports.filter(item => typeof item === 'string').join(',')
|
|
19
|
+
},
|
|
20
|
+
...imports.filter(item => typeof item === 'object')
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
importParams = Object.entries(importParams)
|
|
24
|
+
.filter(([, value]) => Boolean(value))
|
|
25
|
+
.map(([key, value]) => `${key}=${value.replace(/ /g, '%20')}`);
|
|
26
|
+
|
|
27
|
+
uses.push(`imports-loader?${importParams.join('&')}`);
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
// convert to exports-loader? syntax
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const merge = require('deepmerge');
|
|
2
|
+
const StyleLoader = require('./style-loader');
|
|
3
|
+
|
|
4
|
+
class AdminStyleLoader extends StyleLoader {
|
|
5
|
+
/**
|
|
6
|
+
* @inheritdoc
|
|
7
|
+
*/
|
|
8
|
+
_fetchThemeConfig(themeName) {
|
|
9
|
+
const {rtl_support: rtlSupport = false, styles: extraThemeConfig} =
|
|
10
|
+
this._configLoader.loadConfig(themeName, 'Resources/public/themes/' + themeName + '/settings.yml');
|
|
11
|
+
const baseThemeConfig = this._configLoader.loadConfig(themeName, 'Resources/config/oro/assets.yml');
|
|
12
|
+
/** @type {Object.<string, ThemeGroupConfig>} */
|
|
13
|
+
const themeConfig = merge(baseThemeConfig, extraThemeConfig);
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
themeConfig,
|
|
17
|
+
settings: {rtlSupport}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = AdminStyleLoader;
|
|
@@ -1,115 +1,18 @@
|
|
|
1
|
-
const
|
|
2
|
-
const wildcard = require('wildcard');
|
|
3
|
-
const _ = require('underscore')
|
|
1
|
+
const StyleLoader = require('./style-loader');
|
|
4
2
|
|
|
5
|
-
class LayoutStyleLoader {
|
|
3
|
+
class LayoutStyleLoader extends StyleLoader {
|
|
6
4
|
/**
|
|
7
|
-
* @
|
|
8
|
-
* @param {SCSSEntryPointFileWriter} entryPointFileWriter
|
|
5
|
+
* @inheritdoc
|
|
9
6
|
*/
|
|
10
|
-
|
|
11
|
-
this._configLoader
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
20
|
-
getThemeEntryPoints(theme, buildPath) {
|
|
21
|
-
const entryPoints = {};
|
|
22
|
-
const {rtl_support: rtlSupport = false} = this._configLoader.themes[theme];
|
|
23
|
-
const themeConfig = this._configLoader.loadConfig(theme, '/config/assets.yml');
|
|
24
|
-
const writingOptions = {};
|
|
25
|
-
|
|
26
|
-
for (const [key, config] of Object.entries(themeConfig)) {
|
|
27
|
-
let {inputs, output, auto_rtl_inputs: rtlMasks = []} = config;
|
|
28
|
-
if (config.output === undefined) {
|
|
29
|
-
throw new Error('"output" for "' + key + '" group in theme "' + theme + '" is not defined');
|
|
30
|
-
}
|
|
31
|
-
inputs = this._overrideInputs(inputs);
|
|
32
|
-
inputs = this._sortInputs(inputs);
|
|
33
|
-
if (rtlSupport) {
|
|
34
|
-
writingOptions.ignoreRTLInputs = _.difference(inputs, this._matchInputs(rtlMasks, inputs));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const entryPointName = output.replace(/\.[^/.]+$/, '');
|
|
38
|
-
const filePath = path.join(buildPath, output);
|
|
39
|
-
entryPoints[entryPointName] =
|
|
40
|
-
this._entryPointFileWriter.write('./../../../', inputs, filePath, writingOptions);
|
|
41
|
-
}
|
|
42
|
-
return entryPoints;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {Object} inputs
|
|
47
|
-
* @returns {string[]} List of inputs
|
|
48
|
-
* @private
|
|
49
|
-
*/
|
|
50
|
-
_overrideInputs(inputs) {
|
|
51
|
-
const newInputs = [];
|
|
52
|
-
|
|
53
|
-
inputs.forEach((input, index) => {
|
|
54
|
-
if (typeof input !== 'string') {
|
|
55
|
-
const oldInput = Object.keys(input)[0];
|
|
56
|
-
const newInput = input[oldInput];
|
|
57
|
-
const oldInputIndex = newInputs.findIndex(element => element === oldInput);
|
|
58
|
-
|
|
59
|
-
if (newInput) { // replace input
|
|
60
|
-
newInputs[oldInputIndex] = newInput;
|
|
61
|
-
} else { // delete input
|
|
62
|
-
newInputs.splice(oldInputIndex, 1);
|
|
63
|
-
}
|
|
64
|
-
newInputs.splice(index);
|
|
65
|
-
} else {
|
|
66
|
-
newInputs[index] = input;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return newInputs;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Sort inputs, so first will be settings, then variables, then other files
|
|
75
|
-
* @param {Object} inputs
|
|
76
|
-
* @returns {string[]} List of ordered inputs
|
|
77
|
-
* @private
|
|
78
|
-
*/
|
|
79
|
-
_sortInputs(inputs) {
|
|
80
|
-
const settingsInputs = [];
|
|
81
|
-
const variablesInputs = [];
|
|
82
|
-
const restInputs = [];
|
|
83
|
-
|
|
84
|
-
inputs.forEach(input => {
|
|
85
|
-
if (input.indexOf('/settings/') > 0) {
|
|
86
|
-
settingsInputs.push(input);
|
|
87
|
-
} else if (input.indexOf('/variables/') > 0) {
|
|
88
|
-
variablesInputs.push(input);
|
|
89
|
-
} else {
|
|
90
|
-
restInputs.push(input);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
return [...settingsInputs, ...variablesInputs, ...restInputs];
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Filter inputs that matches any mask from the list
|
|
98
|
-
*
|
|
99
|
-
* @param {[string]} masks list of wildcard masks
|
|
100
|
-
* @param {[string]} inputs
|
|
101
|
-
* @return {[string]} matched inputs
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
_matchInputs(masks, inputs) {
|
|
105
|
-
masks = masks.map(mask => wildcard(mask));
|
|
106
|
-
|
|
107
|
-
const whiteListedInputs = masks.reduce((include, mask) => {
|
|
108
|
-
include.push(...mask.match(inputs));
|
|
109
|
-
return include;
|
|
110
|
-
}, []);
|
|
111
|
-
|
|
112
|
-
return _.unique(whiteListedInputs);
|
|
7
|
+
_fetchThemeConfig(themeName) {
|
|
8
|
+
const {rtl_support: rtlSupport = false} = this._configLoader.themes[themeName];
|
|
9
|
+
/** @type {Object.<string, ThemeGroupConfig>} */
|
|
10
|
+
const themeConfig = this._configLoader.loadConfig(themeName, 'config/assets.yml');
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
themeConfig,
|
|
14
|
+
settings: {rtlSupport}
|
|
15
|
+
};
|
|
113
16
|
}
|
|
114
17
|
}
|
|
115
18
|
|
package/style/style-loader.js
CHANGED
|
@@ -1,78 +1,162 @@
|
|
|
1
|
-
const
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const wildcard = require('wildcard');
|
|
3
|
+
const _ = require('underscore');
|
|
4
|
+
const messages = require('../messages')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef ThemeGroupConfig
|
|
8
|
+
* @type {Object}
|
|
9
|
+
* @property {Array.<string|Object>} inputs - list of input resources for import into root SCSS file
|
|
10
|
+
* @property {Array.<string>} entries - list of direct entry resources
|
|
11
|
+
* @property {string} output - name or out put resource
|
|
12
|
+
* @property {[boolean]} auto_rtl_inputs - whether theme support RTL
|
|
13
|
+
*/
|
|
2
14
|
|
|
3
15
|
class StyleLoader {
|
|
4
16
|
/**
|
|
5
17
|
* @param {YamlConfigLoader} configLoader
|
|
18
|
+
* @param {SCSSEntryPointFileWriter} entryPointFileWriter
|
|
6
19
|
*/
|
|
7
|
-
constructor(configLoader) {
|
|
20
|
+
constructor(configLoader, entryPointFileWriter) {
|
|
8
21
|
this._configLoader = configLoader;
|
|
22
|
+
this._entryPointFileWriter = entryPointFileWriter;
|
|
9
23
|
}
|
|
10
24
|
|
|
11
25
|
/**
|
|
12
26
|
* @param {string} theme Theme name
|
|
27
|
+
* @param {string} buildPath Build path
|
|
13
28
|
* @return {Object} List of Webpack entry-points
|
|
14
29
|
*/
|
|
15
|
-
getThemeEntryPoints(theme) {
|
|
30
|
+
getThemeEntryPoints(theme, buildPath) {
|
|
31
|
+
const {themeConfig, settings = {}} = this._fetchThemeConfig(theme);
|
|
32
|
+
|
|
16
33
|
const entryPoints = {};
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const config = themeConfig[key];
|
|
24
|
-
if (commonConfig[key]) {
|
|
25
|
-
commonConfig[key] = merge(commonConfig[key], config);
|
|
26
|
-
}
|
|
34
|
+
const writingOptions = {};
|
|
35
|
+
for (const [group, config] of Object.entries(themeConfig)) {
|
|
36
|
+
let {inputs, entries = [], output, auto_rtl_inputs: rtlMasks = []} = config;
|
|
37
|
+
|
|
38
|
+
if (output === void 0) {
|
|
39
|
+
throw new Error(messages.assetsMissedOutput(group, theme));
|
|
27
40
|
}
|
|
28
|
-
}
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const config = commonConfig[key];
|
|
33
|
-
const inputs = this._overrideInputs(config.inputs);
|
|
34
|
-
if (config.output === undefined) {
|
|
35
|
-
throw new Error('"output" for "' + key + '" group in theme "' + theme + '" is not defined');
|
|
36
|
-
}
|
|
37
|
-
entryPoints[config.output.replace(/\.[^/.]+$/, '')] = inputs;
|
|
42
|
+
if (inputs === void 0) {
|
|
43
|
+
throw new Error(messages.assetsMissedInput(group, theme));
|
|
38
44
|
}
|
|
45
|
+
|
|
46
|
+
inputs = this._overrideInputs(inputs);
|
|
47
|
+
inputs = this._sortInputs(inputs);
|
|
48
|
+
|
|
49
|
+
if (settings.rtlSupport) {
|
|
50
|
+
writingOptions.ignoreRTLInputs = _.difference(inputs, this._matchInputs(rtlMasks, inputs));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const entryPointName = output.replace(/\.[^/.]+$/, '');
|
|
54
|
+
const filePath = path.join(buildPath, output);
|
|
55
|
+
entryPoints[entryPointName] = [
|
|
56
|
+
...entries,
|
|
57
|
+
this._entryPointFileWriter.write('./../../../', inputs, filePath, writingOptions)
|
|
58
|
+
];
|
|
39
59
|
}
|
|
40
60
|
return entryPoints;
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
/**
|
|
44
|
-
*
|
|
64
|
+
* Extracts theme configuration with its settings
|
|
65
|
+
*
|
|
66
|
+
* @param {string} themeName
|
|
67
|
+
* @return {{themeConfig: Object.<string, ThemeGroupConfig>, settings: {rtlSupport: boolean}}}
|
|
68
|
+
* @abstract
|
|
69
|
+
* @protected
|
|
70
|
+
*/
|
|
71
|
+
_fetchThemeConfig(themeName) {
|
|
72
|
+
throw new Error('Method `_fetchThemeConfig` has to be implemented in extends');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Override inputs
|
|
77
|
+
*
|
|
78
|
+
* @param {(string|Object)[]} inputs
|
|
45
79
|
* @returns {string[]} List of inputs
|
|
46
|
-
* @
|
|
80
|
+
* @protected
|
|
47
81
|
*/
|
|
48
82
|
_overrideInputs(inputs) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const oldInput = Object.keys(input)[0];
|
|
54
|
-
const newInput = input[oldInput];
|
|
55
|
-
const oldInputIndex = newInputs.findIndex(element => element === oldInput);
|
|
56
|
-
|
|
57
|
-
if (newInput) { // replace input
|
|
58
|
-
newInputs[oldInputIndex] = newInput;
|
|
59
|
-
} else { // delete input
|
|
60
|
-
newInputs.splice(oldInputIndex, 1);
|
|
61
|
-
}
|
|
62
|
-
newInputs.splice(index);
|
|
83
|
+
const mappedInputs = [];
|
|
84
|
+
inputs.forEach(input => {
|
|
85
|
+
if (typeof input === 'string') {
|
|
86
|
+
mappedInputs.push(input);
|
|
63
87
|
} else {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
const [oldInput, newInput] = Object.entries(input)[0];
|
|
89
|
+
const oldInputIndex = mappedInputs.findIndex(item => item === oldInput);
|
|
90
|
+
|
|
91
|
+
if (oldInputIndex === -1) {
|
|
92
|
+
// old input does not exists any more
|
|
93
|
+
mappedInputs.push(newInput);
|
|
94
|
+
} else if (newInput) {
|
|
95
|
+
// replace input
|
|
96
|
+
mappedInputs[oldInputIndex] = newInput;
|
|
97
|
+
} else {
|
|
98
|
+
// delete input
|
|
99
|
+
mappedInputs.splice(oldInputIndex, 1);
|
|
70
100
|
}
|
|
71
|
-
newInputs.push(input);
|
|
72
101
|
}
|
|
73
102
|
});
|
|
103
|
+
return mappedInputs;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Sort inputs, so first will be settings, then variables, then other files
|
|
108
|
+
*
|
|
109
|
+
* @param {string[]} inputs
|
|
110
|
+
* @returns {string[]} List of ordered inputs
|
|
111
|
+
* @protected
|
|
112
|
+
*/
|
|
113
|
+
_sortInputs(inputs) {
|
|
114
|
+
const primarySettingsInputs = [];
|
|
115
|
+
const settingsInputs = [];
|
|
116
|
+
const primaryVariablesInputs = [];
|
|
117
|
+
const variablesInputs = [];
|
|
118
|
+
const restInputs = [];
|
|
119
|
+
|
|
120
|
+
inputs.forEach(input => {
|
|
121
|
+
if (input.indexOf('/settings/primary-settings') > 0) {
|
|
122
|
+
primarySettingsInputs.push(input);
|
|
123
|
+
} else if (input.indexOf('/settings/') > 0) {
|
|
124
|
+
settingsInputs.push(input);
|
|
125
|
+
} else if (input.indexOf('/variables/primary-variables') > 0) {
|
|
126
|
+
primaryVariablesInputs.push(input);
|
|
127
|
+
} else if (input.indexOf('/variables/') > 0) {
|
|
128
|
+
variablesInputs.push(input);
|
|
129
|
+
} else {
|
|
130
|
+
restInputs.push(input);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return [
|
|
135
|
+
...primarySettingsInputs,
|
|
136
|
+
...settingsInputs,
|
|
137
|
+
...primaryVariablesInputs,
|
|
138
|
+
...variablesInputs,
|
|
139
|
+
...restInputs
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Filter inputs that matches any mask from the list
|
|
145
|
+
*
|
|
146
|
+
* @param {string[]} masks list of wildcard masks
|
|
147
|
+
* @param {string[]} inputs
|
|
148
|
+
* @return {string[]} matched inputs
|
|
149
|
+
* @protected
|
|
150
|
+
*/
|
|
151
|
+
_matchInputs(masks, inputs) {
|
|
152
|
+
masks = masks.map(mask => wildcard(mask));
|
|
153
|
+
|
|
154
|
+
const whiteListedInputs = masks.reduce((include, mask) => {
|
|
155
|
+
include.push(...mask.match(inputs));
|
|
156
|
+
return include;
|
|
157
|
+
}, []);
|
|
74
158
|
|
|
75
|
-
return
|
|
159
|
+
return _.unique(whiteListedInputs);
|
|
76
160
|
}
|
|
77
161
|
}
|
|
78
162
|
|
package/theme-config-factory.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const messages = require('./messages');
|
|
2
|
+
|
|
1
3
|
class ThemeConfigFactory {
|
|
2
4
|
/**
|
|
3
5
|
* @param {ModulesConfigLoader} configLoader
|
|
@@ -11,15 +13,56 @@ class ThemeConfigFactory {
|
|
|
11
13
|
this._appModulesFileWriter = appModulesFileWriter;
|
|
12
14
|
this._configsFileWriter = configsFileWriter;
|
|
13
15
|
}
|
|
14
|
-
|
|
15
16
|
/**
|
|
16
17
|
* @param {string} theme Theme name
|
|
18
|
+
* @param {string|string[]} configFilepath Path (or paths with fallback) to yaml config file in a bundle
|
|
19
|
+
* @return {Object} Merged Configs loaded from all the bundles Yaml files matched by filePath
|
|
20
|
+
*/
|
|
21
|
+
loadConfig(theme, configFilepath) {
|
|
22
|
+
try {
|
|
23
|
+
return this._configLoader.loadConfig(theme, configFilepath)
|
|
24
|
+
} catch (e) {
|
|
25
|
+
throw new Error(messages.jsModulesError(theme));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
extendConfig(baseConfig, extraConfig) {
|
|
30
|
+
const {
|
|
31
|
+
aliases = {},
|
|
32
|
+
configs,
|
|
33
|
+
map = {},
|
|
34
|
+
shim = {},
|
|
35
|
+
} = baseConfig;
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
['app-modules']: appModules,
|
|
39
|
+
['dynamic-imports']: dynamicImports,
|
|
40
|
+
entry,
|
|
41
|
+
...rest
|
|
42
|
+
} = extraConfig;
|
|
43
|
+
|
|
44
|
+
const beyondKeys = Object.keys(rest);
|
|
45
|
+
if (beyondKeys.length) {
|
|
46
|
+
throw new Error( messages.jsExtraModulesError(beyondKeys));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
aliases,
|
|
51
|
+
'app-modules': appModules,
|
|
52
|
+
configs,
|
|
53
|
+
'dynamic-imports': dynamicImports,
|
|
54
|
+
entry,
|
|
55
|
+
map,
|
|
56
|
+
shim
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
17
61
|
* @param {string} buildPath Path to theme build folder
|
|
18
|
-
* @param {
|
|
19
|
-
* @return {Object}
|
|
62
|
+
* @param {Object} jsModulesConfig configuration loaded from jsmodules files and merged together
|
|
63
|
+
* @return {Object} webpack configuration fragment
|
|
20
64
|
*/
|
|
21
|
-
create(
|
|
22
|
-
const jsModulesConfig = this._configLoader.loadConfig(theme, configFilepath);
|
|
65
|
+
create(buildPath, jsModulesConfig) {
|
|
23
66
|
const {
|
|
24
67
|
entry,
|
|
25
68
|
map = {},
|
|
@@ -12,7 +12,7 @@ class ConfigsFileWriter {
|
|
|
12
12
|
/**
|
|
13
13
|
* Write app-modules.js file and return file path
|
|
14
14
|
*
|
|
15
|
-
* @param {
|
|
15
|
+
* @param {Object} configs List of configurable modules
|
|
16
16
|
* @param {string} output Output file path
|
|
17
17
|
* @returns {string} JS file path of an output file
|
|
18
18
|
*/
|
|
@@ -19,9 +19,9 @@ class DynamicImportsFileWriter {
|
|
|
19
19
|
write(dynamicImports, output) {
|
|
20
20
|
const buildPath = path.join(output, 'dynamic-imports.js');
|
|
21
21
|
let content = Object.entries(dynamicImports).map(([chunkName, moduleNames]) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
);
|
|
22
|
+
const notation = chunkName === 'commons' ?
|
|
23
|
+
'/* webpackMode: "eager" */' : `/* webpackChunkName: "${chunkName}" */`;
|
|
24
|
+
return moduleNames.map(moduleName =>`'${moduleName}': () => import(${notation}'${moduleName}')`);
|
|
25
25
|
});
|
|
26
26
|
content = `module.exports = {\n ${content.flat().join(',\n ')}\n};\n`;
|
|
27
27
|
const filepath = path.resolve(this._publicPath + buildPath);
|