@oroinc/oro-webpack-config-builder 5.1.0-alpha9 → 5.1.0-dev0010
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/error-handler.js +95 -0
- package/loader/config-loader.js +1 -2
- package/loader/inject-loader/LICENSE.md +21 -0
- package/loader/inject-loader/README.md +54 -0
- package/loader/inject-loader/index.js +10 -0
- package/loader/inject-loader/injectify.js +66 -0
- package/loader/inject-loader/package.json +55 -0
- package/loader/inject-loader/wrapper_template.js +32 -0
- package/modules-config/layout-modules-config-loader.js +89 -2
- package/modules-config/modules-config-loader.js +83 -19
- package/oro-webpack-config.js +420 -299
- package/package.json +39 -38
- package/plugin/logs/after-webpack-logs-plugin.js +25 -0
- package/style/admin-style-loader.js +4 -3
- package/style/layout-style-loader.js +3 -3
- package/style/style-loader.js +52 -7
- package/svg-sprite/index.js +135 -0
- package/svg-sprite/svg-sprite-config.js +5 -0
- package/svg-sprite/svgo-config.js +32 -0
- package/theme-config-factory.js +45 -6
- package/utils.js +30 -0
- package/validation/assets-validator.js +104 -0
- package/validation/errors/assets-input-file-error.js +24 -0
- package/validation/errors/assets-schema-error.js +40 -0
- package/validation/errors/base-error.js +37 -0
- package/validation/errors/jsmodules-extra-modules-error.js +22 -0
- package/validation/errors/jsmodules-schema-error.js +40 -0
- package/validation/errors/styles-error.js +24 -0
- package/validation/errors/svg-icons-schema-error.js +36 -0
- package/validation/index.js +41 -0
- package/validation/jsmodules-validator.js +55 -0
- package/validation/schema-validator.js +62 -0
- package/validation/schemas/assets-schema-full.js +22 -0
- package/validation/schemas/assets-schema.js +32 -0
- package/validation/schemas/jsmodules-schema-full.js +11 -0
- package/validation/schemas/jsmodules-schema.js +76 -0
- package/validation/schemas/svg-icons-schema-full.js +18 -0
- package/validation/schemas/svg-icons-schema.js +17 -0
- package/validation/svg-icons-validator.js +53 -0
- package/writer/configs-file-writer.js +1 -1
- package/writer/dynamic-imports-file-writer.js +3 -3
- package/writer/scss-entry-point-file-writer.js +1 -1
package/oro-webpack-config.js
CHANGED
|
@@ -3,13 +3,13 @@ const printf = require('printf');
|
|
|
3
3
|
const AppConfigLoader = require('./app-config-loader');
|
|
4
4
|
const AppModulesFileWriter = require('./writer/app-modules-file-writer');
|
|
5
5
|
const CleanupStatsPlugin = require('./plugin/stats/cleanup-stats-plugin');
|
|
6
|
+
const AfterWebpackLogsPlugin = require('./plugin/logs/after-webpack-logs-plugin');
|
|
6
7
|
const ConfigsFileWriter = require('./writer/configs-file-writer');
|
|
7
8
|
const EntryPointFileWriter = require('./writer/scss-entry-point-file-writer');
|
|
8
9
|
const LayoutModulesConfigLoader = require('./modules-config/layout-modules-config-loader');
|
|
9
10
|
const LayoutStyleLoader = require('./style/layout-style-loader');
|
|
10
11
|
const MapModulesPlugin = require('./plugin/map/map-modules-plugin');
|
|
11
12
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
12
|
-
const HappyPack = require('happypack');
|
|
13
13
|
const ModulesConfigLoader = require('./modules-config/modules-config-loader');
|
|
14
14
|
const DynamicImportsFileWriter = require('./writer/dynamic-imports-file-writer');
|
|
15
15
|
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
@@ -17,21 +17,30 @@ const prepareModulesShim = require('./prepare-modules-shim');
|
|
|
17
17
|
const AdminStyleLoader = require('./style/admin-style-loader');
|
|
18
18
|
const ThemeConfigFactory = require('./theme-config-factory');
|
|
19
19
|
const path = require('path');
|
|
20
|
+
const fs = require('fs');
|
|
20
21
|
const prepareModulesMap = require('./plugin/map/prepare-modules-map');
|
|
21
22
|
const resolve = require('enhanced-resolve');
|
|
22
23
|
const {merge: webpackMerge} = require('webpack-merge');
|
|
23
24
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
24
25
|
const RtlCssWebpackPlugin = require('rtlcss-webpack-plugin');
|
|
26
|
+
const validation = require('./validation');
|
|
27
|
+
const EventEmitter = require('events');
|
|
28
|
+
const ErrorHandler = require('./error-handler');
|
|
29
|
+
const SVGSprite = require('./svg-sprite');
|
|
25
30
|
require('resolve-url-loader');
|
|
26
31
|
|
|
27
32
|
class ConfigBuilder {
|
|
28
33
|
constructor() {
|
|
29
|
-
this.
|
|
30
|
-
this._adminTheme = 'admin.oro';
|
|
34
|
+
this._projectPath = '';
|
|
31
35
|
this._enableLayoutThemes = false;
|
|
32
36
|
this._defaultLayoutThemes = null;
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
37
|
+
this.emitter = new EventEmitter();
|
|
38
|
+
this.errorHandler = new ErrorHandler();
|
|
39
|
+
this.addListeners();
|
|
40
|
+
this.setPublicPath('public/');
|
|
41
|
+
this.setAdminTheme('admin.oro');
|
|
42
|
+
this.setVersionFormat('%s?v=%s');
|
|
43
|
+
this.setBabelConfig({
|
|
35
44
|
sourceType: 'unambiguous',
|
|
36
45
|
presets: [
|
|
37
46
|
[
|
|
@@ -47,7 +56,12 @@ class ConfigBuilder {
|
|
|
47
56
|
plugins: [
|
|
48
57
|
'@babel/plugin-transform-runtime'
|
|
49
58
|
]
|
|
50
|
-
};
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
addListeners() {
|
|
63
|
+
this.emitter.on('publicPath:updated', path => validation.setPublicPath(path));
|
|
64
|
+
this.emitter.on('build:complete', stats => this.errorHandler.onBuildComplete(stats));
|
|
51
65
|
}
|
|
52
66
|
|
|
53
67
|
/**
|
|
@@ -57,6 +71,7 @@ class ConfigBuilder {
|
|
|
57
71
|
*/
|
|
58
72
|
setPublicPath(publicPath) {
|
|
59
73
|
this._publicPath = publicPath;
|
|
74
|
+
this.emitter.emit('publicPath:updated', publicPath);
|
|
60
75
|
return this;
|
|
61
76
|
}
|
|
62
77
|
|
|
@@ -72,12 +87,13 @@ class ConfigBuilder {
|
|
|
72
87
|
|
|
73
88
|
/**
|
|
74
89
|
* Specifies a sprintf pattern that will be used with the version option to construct an asset’s path.
|
|
75
|
-
* By default ts `%s?
|
|
90
|
+
* By default ts `%s?v=%s`
|
|
76
91
|
* @param {string} versionFormat
|
|
77
92
|
* @returns {ConfigBuilder}
|
|
78
93
|
*/
|
|
79
94
|
setVersionFormat(versionFormat) {
|
|
80
95
|
this._versionFormat = versionFormat;
|
|
96
|
+
this.emitter.emit('versionFormat:updated', versionFormat);
|
|
81
97
|
return this;
|
|
82
98
|
}
|
|
83
99
|
|
|
@@ -94,6 +110,7 @@ class ConfigBuilder {
|
|
|
94
110
|
}
|
|
95
111
|
|
|
96
112
|
this._adminTheme = adminTheme;
|
|
113
|
+
this.emitter.emit('adminTheme:updated', adminTheme);
|
|
97
114
|
return this;
|
|
98
115
|
}
|
|
99
116
|
|
|
@@ -103,8 +120,10 @@ class ConfigBuilder {
|
|
|
103
120
|
enableLayoutThemes(themes) {
|
|
104
121
|
if (themes) {
|
|
105
122
|
this._defaultLayoutThemes = themes;
|
|
123
|
+
this.emitter.emit('defaultLayoutThemes:updated', themes);
|
|
106
124
|
}
|
|
107
125
|
this._enableLayoutThemes = true;
|
|
126
|
+
this.emitter.emit('enableLayoutThemes:updated', true);
|
|
108
127
|
return this;
|
|
109
128
|
}
|
|
110
129
|
|
|
@@ -115,6 +134,7 @@ class ConfigBuilder {
|
|
|
115
134
|
*/
|
|
116
135
|
setBabelConfig(babelConfig) {
|
|
117
136
|
this._babelConfig = babelConfig;
|
|
137
|
+
this.emitter.emit('babelConfig:updated', babelConfig);
|
|
118
138
|
return this;
|
|
119
139
|
}
|
|
120
140
|
|
|
@@ -126,309 +146,403 @@ class ConfigBuilder {
|
|
|
126
146
|
return (env = {}, args = {}) => {
|
|
127
147
|
this._initialize(args, env);
|
|
128
148
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (selectedTheme === undefined) {
|
|
136
|
-
// themes.push(this._adminTheme.split(".")[1]);
|
|
137
|
-
themes.push(this._adminTheme);
|
|
138
|
-
} else if (this._adminThemes.indexOf(selectedTheme) !== -1) {
|
|
139
|
-
// themes.push(selectedTheme.split(".")[1]);
|
|
140
|
-
themes.push(selectedTheme);
|
|
149
|
+
let commonConfig = {};
|
|
150
|
+
try {
|
|
151
|
+
commonConfig = this._getCommonWebpackConfig(args, env);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
this.errorHandler.displayError(e);
|
|
154
|
+
process.exit(1);
|
|
141
155
|
}
|
|
142
156
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
const webpackConfigs = [];
|
|
158
|
+
const requestedBuildNames = env.theme ? env.theme.split(',') : [];
|
|
159
|
+
const buildNames = this._getBuildNames(requestedBuildNames);
|
|
160
|
+
|
|
161
|
+
const buildErrors = [];
|
|
162
|
+
validation.jsmodulesValidator.emitter.on('error', error => buildErrors.push(error));
|
|
163
|
+
validation.assetsValidation.emitter.on('error', error => buildErrors.push(error));
|
|
164
|
+
buildNames.forEach(buildName => {
|
|
165
|
+
let buildConfig;
|
|
166
|
+
// flush all collected errors from previews builds
|
|
167
|
+
buildErrors.splice(0, buildErrors.length);
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
buildConfig = this._getThemeWebpackConfig(buildName, args, env);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
buildErrors.push(error);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (buildErrors.length) {
|
|
176
|
+
this.errorHandler.displayError(buildErrors, buildName);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (buildConfig) {
|
|
181
|
+
webpackConfigs.push(webpackMerge(buildConfig, commonConfig));
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return webpackConfigs;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get resolvedProjectPath() {
|
|
190
|
+
if (this._resolvedProjectPath === undefined) {
|
|
191
|
+
this._resolvedProjectPath = path.resolve(this._projectPath);
|
|
192
|
+
}
|
|
193
|
+
return this._resolvedProjectPath;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
get resolvedPublicPath() {
|
|
197
|
+
if (this._resolvedPublicPath === undefined) {
|
|
198
|
+
this._resolvedPublicPath = path.resolve(this._publicPath);
|
|
199
|
+
}
|
|
200
|
+
return this._resolvedPublicPath;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
get resolvedNodeModulesPath() {
|
|
204
|
+
if (this._resolvedNodeModulesPath === undefined) {
|
|
205
|
+
this._resolvedNodeModulesPath = path.resolve('node_modules');
|
|
206
|
+
}
|
|
207
|
+
return this._resolvedNodeModulesPath;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
get assetVersion() {
|
|
211
|
+
if (this._assetVersion === undefined) {
|
|
212
|
+
const filePath = path.join(this.resolvedPublicPath, '/build/build_version.txt');
|
|
213
|
+
this._assetVersion = fs.existsSync(filePath) ? String(fs.readFileSync(filePath)) : null;
|
|
214
|
+
}
|
|
215
|
+
return this._assetVersion;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
_getBuildNames(requestedBuildNames = []) {
|
|
219
|
+
const buildNames = [];
|
|
220
|
+
requestedBuildNames.forEach(buildName => this._validateBuildName(buildName));
|
|
221
|
+
|
|
222
|
+
// Admin themes
|
|
223
|
+
if (!requestedBuildNames.length) {
|
|
224
|
+
buildNames.push(this._adminTheme);
|
|
225
|
+
} else {
|
|
226
|
+
requestedBuildNames.forEach(buildName => {
|
|
227
|
+
if (this._isAdminTheme(buildName)) {
|
|
228
|
+
buildNames.push(buildName);
|
|
155
229
|
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Layout Themes
|
|
234
|
+
if (this._enableLayoutThemes) {
|
|
235
|
+
if (!requestedBuildNames.length) {
|
|
236
|
+
// build all layout themes
|
|
237
|
+
const themes = this._defaultLayoutThemes || this._appConfig.themes;
|
|
238
|
+
buildNames.push(...themes);
|
|
239
|
+
themes.forEach(theme => {
|
|
240
|
+
buildNames.push(...this._layoutModulesConfigLoader.extraJSBuildNames(theme));
|
|
241
|
+
});
|
|
242
|
+
} else {
|
|
243
|
+
// build single layout theme
|
|
244
|
+
requestedBuildNames.forEach(buildName => {
|
|
245
|
+
if (this._layoutModulesConfigLoader.buildNames.includes(buildName)) {
|
|
246
|
+
buildNames.push(buildName);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
156
249
|
}
|
|
250
|
+
}
|
|
157
251
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
reuseExistingChunk: true
|
|
198
|
-
},
|
|
199
|
-
tinymce: {
|
|
200
|
-
test: /tinymce/,
|
|
201
|
-
name: 'tinymce.min',
|
|
202
|
-
minChunks: 1
|
|
203
|
-
},
|
|
204
|
-
fusioncharts: {
|
|
205
|
-
test: /fusioncharts/,
|
|
206
|
-
name: 'fusioncharts',
|
|
207
|
-
minChunks: 1
|
|
208
|
-
}
|
|
209
|
-
}
|
|
252
|
+
return buildNames;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
_getCommonWebpackConfig(args, env) {
|
|
256
|
+
const stats = env.stats || {
|
|
257
|
+
hash: false,
|
|
258
|
+
version: false,
|
|
259
|
+
// Do not write the information about files emitted from node_modules or public bundles,
|
|
260
|
+
// and hide css/*/*.js files from the output.
|
|
261
|
+
excludeAssets: [/^bundles\//, /^\.\.\/_static\//, /^css\/.+\.js/],
|
|
262
|
+
children: false,
|
|
263
|
+
entrypoints: false,
|
|
264
|
+
performance: this._isProduction,
|
|
265
|
+
chunks: false,
|
|
266
|
+
modules: false,
|
|
267
|
+
source: false,
|
|
268
|
+
publicPath: true,
|
|
269
|
+
builtAt: false,
|
|
270
|
+
warnings: false
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const webpackConfig = {
|
|
274
|
+
watchOptions: {
|
|
275
|
+
aggregateTimeout: 200,
|
|
276
|
+
ignored: /[\/\\]node_modules[\/\\].*\.js$/
|
|
277
|
+
},
|
|
278
|
+
stats,
|
|
279
|
+
output: {
|
|
280
|
+
filename: '[name].js',
|
|
281
|
+
// Because we use third party libraries 'chunkFilename' should include only [name]
|
|
282
|
+
chunkFilename: this._getVersionedPath('chunk/[name].js', this.assetVersion)
|
|
283
|
+
},
|
|
284
|
+
devtool: !env.skipSourcemap && 'inline-cheap-module-source-map',
|
|
285
|
+
mode: 'development',
|
|
286
|
+
optimization: {
|
|
287
|
+
moduleIds: 'named',
|
|
288
|
+
splitChunks: {
|
|
289
|
+
cacheGroups: {
|
|
290
|
+
defaultVendors: false
|
|
210
291
|
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
]
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
loader: 'sass-loader',
|
|
249
|
-
options: {
|
|
250
|
-
sassOptions: {
|
|
251
|
-
includePaths: [
|
|
252
|
-
resolvedPublicPath + '/bundles'
|
|
253
|
-
],
|
|
254
|
-
outputStyle: 'expanded'
|
|
255
|
-
},
|
|
256
|
-
sourceMap: true
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
resolveLoader: {
|
|
295
|
+
modules: [
|
|
296
|
+
this.resolvedPublicPath,
|
|
297
|
+
path.join(__dirname, './loader'),
|
|
298
|
+
path.join(this.resolvedPublicPath, '/bundles'),
|
|
299
|
+
this.resolvedNodeModulesPath
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
module: {
|
|
303
|
+
noParse: [
|
|
304
|
+
/[\/\\]bundles[\/\\]\.*[\/\\]lib[\/\\](?!chaplin|bootstrap|jquery\.dialog).*\.js$/
|
|
305
|
+
],
|
|
306
|
+
rules: [
|
|
307
|
+
{
|
|
308
|
+
test: /\.s?css$/,
|
|
309
|
+
use: [{
|
|
310
|
+
loader: args.hot ? 'style-loader' : MiniCssExtractPlugin.loader
|
|
311
|
+
}, {
|
|
312
|
+
loader: 'css-loader',
|
|
313
|
+
options: {
|
|
314
|
+
importLoaders: 1,
|
|
315
|
+
sourceMap: true,
|
|
316
|
+
// can't use esModule since resolve-url-loader needs file path to start with '~'
|
|
317
|
+
esModule: false
|
|
318
|
+
}
|
|
319
|
+
}, {
|
|
320
|
+
loader: 'resolve-url-loader'
|
|
321
|
+
}, {
|
|
322
|
+
loader: 'postcss-loader',
|
|
323
|
+
options: {
|
|
324
|
+
sourceMap: true,
|
|
325
|
+
postcssOptions: {
|
|
326
|
+
plugins: [
|
|
327
|
+
require('autoprefixer')
|
|
328
|
+
]
|
|
257
329
|
}
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
262
|
-
loader: 'url-loader',
|
|
330
|
+
}
|
|
331
|
+
}, {
|
|
332
|
+
loader: 'sass-loader',
|
|
263
333
|
options: {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
334
|
+
implementation: require('sass'),
|
|
335
|
+
sassOptions: {
|
|
336
|
+
includePaths: [
|
|
337
|
+
path.join(this.resolvedPublicPath, '/bundles')
|
|
338
|
+
],
|
|
339
|
+
outputStyle: 'expanded'
|
|
340
|
+
},
|
|
341
|
+
sourceMap: true
|
|
269
342
|
}
|
|
343
|
+
}]
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
347
|
+
loader: 'url-loader',
|
|
348
|
+
options: {
|
|
349
|
+
limit: 1,
|
|
350
|
+
emitFile: true,
|
|
351
|
+
outputPath: '../_static/',
|
|
352
|
+
publicPath: '../../_static/',
|
|
353
|
+
name: this._getVersionedPath('[path][name].[ext]', this.assetVersion)
|
|
270
354
|
}
|
|
271
|
-
|
|
272
|
-
},
|
|
273
|
-
performance: {hints: false},
|
|
274
|
-
plugins: [
|
|
275
|
-
new MiniCssExtractPlugin({
|
|
276
|
-
filename: '[name].css'
|
|
277
|
-
}),
|
|
278
|
-
new CleanupStatsPlugin(),
|
|
279
|
-
// Ignore all locale files of moment.js
|
|
280
|
-
new webpack.IgnorePlugin({
|
|
281
|
-
resourceRegExp: /^\.[\/\\]locale$/,
|
|
282
|
-
contextRegExp: /moment$/
|
|
283
|
-
}),
|
|
284
|
-
new webpack.optimize.MinChunkSizePlugin({
|
|
285
|
-
minChunkSize: 30000 // Minimum number of characters
|
|
286
|
-
})
|
|
355
|
+
}
|
|
287
356
|
]
|
|
288
|
-
}
|
|
357
|
+
},
|
|
358
|
+
performance: {hints: false},
|
|
359
|
+
plugins: [
|
|
360
|
+
new MiniCssExtractPlugin({
|
|
361
|
+
filename: '[name].css'
|
|
362
|
+
}),
|
|
363
|
+
new CleanupStatsPlugin(),
|
|
364
|
+
// Ignore all locale files of moment.js
|
|
365
|
+
new webpack.IgnorePlugin({
|
|
366
|
+
resourceRegExp: /^\.[\/\\]locale$/,
|
|
367
|
+
contextRegExp: /moment$/
|
|
368
|
+
}),
|
|
369
|
+
new webpack.optimize.MinChunkSizePlugin({
|
|
370
|
+
minChunkSize: 30000 // Minimum number of characters
|
|
371
|
+
}),
|
|
372
|
+
new AfterWebpackLogsPlugin(
|
|
373
|
+
stats => this.emitter.emit('build:complete', stats)
|
|
374
|
+
)
|
|
375
|
+
]
|
|
376
|
+
};
|
|
289
377
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
378
|
+
if (env.analyze) {
|
|
379
|
+
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
380
|
+
}
|
|
293
381
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
test: /\.js$/,
|
|
309
|
-
exclude: [
|
|
310
|
-
/[\/\\]platform[\/\\]build[\/\\]/,
|
|
311
|
-
/[\/\\]node_modules[\/\\]/,
|
|
312
|
-
/[\/\\]bundles[\/\\].+[\/\\]lib[\/\\]?/
|
|
313
|
-
],
|
|
314
|
-
use: 'happypack/loader?id=babel'
|
|
315
|
-
});
|
|
316
|
-
}
|
|
382
|
+
if (!env.skipJS && env.withBabel) {
|
|
383
|
+
webpackConfig.module.rules.push({
|
|
384
|
+
test: /\.js$/,
|
|
385
|
+
exclude: [
|
|
386
|
+
/[\/\\]platform[\/\\]build[\/\\]/,
|
|
387
|
+
/[\/\\]node_modules[\/\\]/,
|
|
388
|
+
/[\/\\]bundles[\/\\].+[\/\\]lib[\/\\]?/
|
|
389
|
+
],
|
|
390
|
+
use: {
|
|
391
|
+
loader: 'babel-loader',
|
|
392
|
+
options: this._babelConfig
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
317
396
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
397
|
+
if (args.hot) {
|
|
398
|
+
const https = this._appConfig.devServerOptions.https;
|
|
399
|
+
const schema = https ? 'https' : 'http';
|
|
400
|
+
const devServerHost = this._appConfig.devServerOptions.host;
|
|
401
|
+
const devServerPort = this._appConfig.devServerOptions.port;
|
|
402
|
+
webpackConfig.devServer = {
|
|
403
|
+
contentBase: this.resolvedPublicPath,
|
|
404
|
+
host: devServerHost,
|
|
405
|
+
port: devServerPort,
|
|
406
|
+
https: https,
|
|
407
|
+
compress: true,
|
|
408
|
+
stats: webpackConfig.stats,
|
|
409
|
+
disableHostCheck: true,
|
|
410
|
+
clientLogLevel: 'error',
|
|
411
|
+
headers: {
|
|
412
|
+
'Access-Control-Allow-Origin': '*'
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
webpackConfig.output.publicPath = `${schema}://${devServerHost}:${devServerPort}/`;
|
|
416
|
+
}
|
|
338
417
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
418
|
+
// Additional setting for production mode
|
|
419
|
+
if (this._isProduction) {
|
|
420
|
+
webpackConfig.devtool = false;
|
|
421
|
+
webpackConfig.plugins.push(new CssMinimizerPlugin());
|
|
422
|
+
}
|
|
343
423
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
]
|
|
347
|
-
});
|
|
348
|
-
}
|
|
424
|
+
return webpackConfig;
|
|
425
|
+
}
|
|
349
426
|
|
|
350
|
-
|
|
427
|
+
_getThemeWebpackConfig(buildName, args, env) {
|
|
428
|
+
let {skipCSS, skipJS, skipRTL, skipSVG} = env;
|
|
429
|
+
let themeDefinition;
|
|
430
|
+
let jsBuildConfig;
|
|
431
|
+
let buildPublicPath;
|
|
432
|
+
if (this._isAdminTheme(buildName)) {
|
|
433
|
+
themeDefinition = this._modulesConfigLoader.themes[buildName.split('.')[1]];
|
|
434
|
+
buildPublicPath = '/build/admin/';
|
|
435
|
+
const jsModulesConfig = this._themeConfigFactory.loadConfig(
|
|
436
|
+
buildName,
|
|
437
|
+
[
|
|
438
|
+
'Resources/config/oro/jsmodules.yml',
|
|
439
|
+
'Resources/config/jsmodules.yml',
|
|
440
|
+
'config/oro/jsmodules.yml'
|
|
441
|
+
]
|
|
442
|
+
);
|
|
443
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
444
|
+
jsModulesConfig,
|
|
445
|
+
this._themeConfigFactory?._configLoader.processedFiles,
|
|
446
|
+
buildName
|
|
447
|
+
);
|
|
448
|
+
jsBuildConfig = this._themeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
449
|
+
} else if (this._layoutModulesConfigLoader.isExtraJSBuild(buildName)) {
|
|
450
|
+
const [theme, suffix] = this._layoutModulesConfigLoader.splitBuildName(buildName);
|
|
451
|
+
skipCSS = true;
|
|
452
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
453
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
454
|
+
const baseConfig = this._layoutThemeConfigFactory.loadConfig(theme, 'config/jsmodules.yml');
|
|
455
|
+
const extraConfig = this._layoutThemeConfigFactory.loadConfig(theme, `config/jsmodules-${suffix}.yml`);
|
|
456
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.extendConfig(baseConfig, extraConfig);
|
|
457
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
458
|
+
jsModulesConfig,
|
|
459
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
460
|
+
buildName
|
|
461
|
+
);
|
|
462
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
463
|
+
} else {
|
|
464
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[buildName];
|
|
465
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
466
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.loadConfig(buildName, 'config/jsmodules.yml');
|
|
467
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
468
|
+
jsModulesConfig,
|
|
469
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
470
|
+
buildName
|
|
471
|
+
);
|
|
472
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
473
|
+
|
|
474
|
+
if (!skipSVG) {
|
|
475
|
+
new SVGSprite(
|
|
476
|
+
this._layoutModulesConfigLoader,
|
|
477
|
+
buildName,
|
|
478
|
+
this._publicPath,
|
|
479
|
+
buildPublicPath
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
484
|
+
const resolvedBuildPath = path.join(this.resolvedPublicPath, buildPublicPath);
|
|
485
|
+
|
|
486
|
+
const resolverConfig = {
|
|
487
|
+
modules: [
|
|
488
|
+
resolvedBuildPath,
|
|
489
|
+
this.resolvedPublicPath,
|
|
490
|
+
path.join(this.resolvedProjectPath, '/assets'),
|
|
491
|
+
path.join(this.resolvedPublicPath, '/bundles'),
|
|
492
|
+
path.join(this.resolvedPublicPath, '/js'),
|
|
493
|
+
this.resolvedNodeModulesPath
|
|
494
|
+
],
|
|
495
|
+
alias: jsBuildConfig.aliases,
|
|
496
|
+
cacheWithContext: true,
|
|
497
|
+
symlinks: false
|
|
498
|
+
};
|
|
499
|
+
const resolver = (resolver => {
|
|
500
|
+
return moduleName => resolver({}, '', moduleName, {});
|
|
501
|
+
})(resolve.create.sync({...resolverConfig}));
|
|
502
|
+
|
|
503
|
+
const plugins = [];
|
|
504
|
+
if (rtlSupport && !skipCSS && !skipRTL) {
|
|
505
|
+
plugins.push(new RtlCssWebpackPlugin({
|
|
506
|
+
filename: '[name].rtl.css'
|
|
507
|
+
}));
|
|
508
|
+
}
|
|
351
509
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
let themeConfig;
|
|
355
|
-
let buildPublicPath;
|
|
356
|
-
if (this._isAdminTheme(theme)) {
|
|
357
|
-
themeDefinition = this._modulesConfigLoader.themes[theme.split('.')[1]];
|
|
358
|
-
buildPublicPath = '/build/admin/';
|
|
359
|
-
themeConfig = this._themeConfigFactory
|
|
360
|
-
.create(theme, buildPublicPath,
|
|
361
|
-
['Resources/config/oro/jsmodules.yml', 'Resources/config/jsmodules.yml']);
|
|
362
|
-
} else {
|
|
363
|
-
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
364
|
-
buildPublicPath = `/build/${theme}/`;
|
|
365
|
-
themeConfig = this._layoutThemeConfigFactory
|
|
366
|
-
.create(theme, buildPublicPath, 'config/jsmodules.yml');
|
|
367
|
-
}
|
|
368
|
-
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
369
|
-
const resolvedBuildPath = path.join(resolvedPublicPath, buildPublicPath);
|
|
370
|
-
|
|
371
|
-
const resolverConfig = {
|
|
372
|
-
modules: [
|
|
373
|
-
resolvedBuildPath,
|
|
374
|
-
resolvedPublicPath,
|
|
375
|
-
resolvedPublicPath + '/bundles',
|
|
376
|
-
resolvedPublicPath + '/js',
|
|
377
|
-
resolvedNodeModulesPath
|
|
378
|
-
],
|
|
379
|
-
alias: themeConfig.aliases,
|
|
380
|
-
symlinks: false
|
|
381
|
-
};
|
|
382
|
-
const resolver = (resolver => {
|
|
383
|
-
return moduleName => resolver({}, '', moduleName, {});
|
|
384
|
-
})(resolve.create.sync({...resolverConfig}));
|
|
385
|
-
|
|
386
|
-
const plugins = [];
|
|
387
|
-
if (rtlSupport && !env.skipCSS && !env.skipRTL) {
|
|
388
|
-
plugins.push(new RtlCssWebpackPlugin({
|
|
389
|
-
filename: '[name].rtl.css'
|
|
390
|
-
}));
|
|
391
|
-
}
|
|
510
|
+
const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
|
|
511
|
+
const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
|
|
392
512
|
|
|
393
|
-
|
|
394
|
-
|
|
513
|
+
const entryPoints = {...cssEntryPoints, ...jsEntryPoints};
|
|
514
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
395
517
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
518
|
+
return {
|
|
519
|
+
entry: entryPoints,
|
|
520
|
+
name: buildName + ' theme',
|
|
521
|
+
output: {
|
|
522
|
+
publicPath: buildPublicPath,
|
|
523
|
+
path: resolvedBuildPath
|
|
524
|
+
},
|
|
525
|
+
context: this.resolvedPublicPath,
|
|
526
|
+
resolve: {
|
|
527
|
+
...resolverConfig,
|
|
528
|
+
plugins: [
|
|
529
|
+
new MapModulesPlugin(prepareModulesMap(resolver, jsBuildConfig.map))
|
|
530
|
+
]
|
|
531
|
+
},
|
|
532
|
+
plugins,
|
|
533
|
+
module: {
|
|
534
|
+
rules: [
|
|
535
|
+
{
|
|
536
|
+
test: /[\/\\]configs\.json$/,
|
|
537
|
+
loader: 'config-loader',
|
|
538
|
+
options: {
|
|
539
|
+
resolver,
|
|
540
|
+
relativeTo: this.resolvedPublicPath
|
|
541
|
+
}
|
|
413
542
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
{
|
|
418
|
-
test: /[\/\\]configs\.json$/,
|
|
419
|
-
loader: 'config-loader',
|
|
420
|
-
options: {
|
|
421
|
-
resolver,
|
|
422
|
-
relativeTo: resolvedPublicPath
|
|
423
|
-
}
|
|
424
|
-
},
|
|
425
|
-
...prepareModulesShim(resolver, themeConfig.shim)
|
|
426
|
-
]
|
|
427
|
-
}
|
|
428
|
-
}, webpackConfig));
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
return webpackConfigs;
|
|
543
|
+
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
544
|
+
]
|
|
545
|
+
}
|
|
432
546
|
};
|
|
433
547
|
}
|
|
434
548
|
|
|
@@ -438,10 +552,11 @@ class ConfigBuilder {
|
|
|
438
552
|
this._isProduction = args.mode === 'production';
|
|
439
553
|
this._symfonyEnv = env.symfony;
|
|
440
554
|
this._appConfig = AppConfigLoader.getConfig(this._cachePath, this._symfonyEnv);
|
|
555
|
+
this._appConfig.paths.push(this.resolvedProjectPath);
|
|
441
556
|
|
|
442
557
|
this._modulesConfigLoader = new ModulesConfigLoader(
|
|
443
558
|
this._appConfig.paths,
|
|
444
|
-
'/Resources/public/themes/',
|
|
559
|
+
['/Resources/public/themes/', '/public/themes/admin/'],
|
|
445
560
|
'settings.yml'
|
|
446
561
|
);
|
|
447
562
|
this._adminThemes = this._modulesConfigLoader.themeNames.map(themeName => 'admin.' + themeName);
|
|
@@ -455,10 +570,9 @@ class ConfigBuilder {
|
|
|
455
570
|
|
|
456
571
|
this._layoutModulesConfigLoader = new LayoutModulesConfigLoader(
|
|
457
572
|
this._appConfig.paths,
|
|
458
|
-
'/Resources/views/layouts/',
|
|
573
|
+
['/Resources/views/layouts/', '/templates/layouts/'],
|
|
459
574
|
'theme.yml'
|
|
460
575
|
);
|
|
461
|
-
this._layoutThemes = this._layoutModulesConfigLoader.themeNames;
|
|
462
576
|
this._layoutStyleLoader = new LayoutStyleLoader(this._layoutModulesConfigLoader, entryPointFileWriter);
|
|
463
577
|
this._layoutThemeConfigFactory = new ThemeConfigFactory(
|
|
464
578
|
this._layoutModulesConfigLoader,
|
|
@@ -468,6 +582,13 @@ class ConfigBuilder {
|
|
|
468
582
|
);
|
|
469
583
|
}
|
|
470
584
|
|
|
585
|
+
_getVersionedPath(name, assetVersion) {
|
|
586
|
+
if (!assetVersion) {
|
|
587
|
+
return name;
|
|
588
|
+
}
|
|
589
|
+
return printf(this._versionFormat, name, assetVersion);
|
|
590
|
+
}
|
|
591
|
+
|
|
471
592
|
_getCssEntryPoints(theme, buildPath) {
|
|
472
593
|
if (this._isAdminTheme(theme)) {
|
|
473
594
|
return this._adminStyleLoader.getThemeEntryPoints(theme.split('.')[1], buildPath);
|
|
@@ -476,25 +597,25 @@ class ConfigBuilder {
|
|
|
476
597
|
return this._layoutStyleLoader.getThemeEntryPoints(theme, buildPath);
|
|
477
598
|
}
|
|
478
599
|
|
|
479
|
-
|
|
480
|
-
|
|
600
|
+
_validateBuildName(buildName) {
|
|
601
|
+
const buildNames = [...this._adminThemes];
|
|
481
602
|
if (this._enableLayoutThemes) {
|
|
482
|
-
|
|
603
|
+
buildNames.push(...this._layoutModulesConfigLoader.buildNames);
|
|
483
604
|
}
|
|
484
|
-
if (
|
|
605
|
+
if (buildName === 'admin') {
|
|
485
606
|
throw new Error(
|
|
486
607
|
'The "admin" is a reserved word and cannot be used as a theme name.'
|
|
487
608
|
);
|
|
488
609
|
}
|
|
489
|
-
if (
|
|
610
|
+
if (buildName !== undefined && !buildNames.includes(buildName)) {
|
|
490
611
|
throw new Error(
|
|
491
|
-
'Theme "' +
|
|
612
|
+
'Theme "' + buildName + '" doesn\'t exists. Existing themes:' + buildNames.join(', ')
|
|
492
613
|
);
|
|
493
614
|
}
|
|
494
615
|
}
|
|
495
616
|
|
|
496
617
|
_isAdminTheme(theme) {
|
|
497
|
-
return this._adminThemes.
|
|
618
|
+
return this._adminThemes.includes(theme);
|
|
498
619
|
}
|
|
499
620
|
}
|
|
500
621
|
|