@oroinc/oro-webpack-config-builder 5.1.0-alpha9 → 5.1.0-dev002
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 +66 -2
- package/modules-config/modules-config-loader.js +52 -19
- package/oro-webpack-config.js +410 -299
- package/package.json +37 -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/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/index.js +36 -0
- package/validation/jsmodules-validator.js +53 -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/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
|
+
|
|
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,393 @@ 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));
|
|
155
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);
|
|
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} = 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
|
+
); validation.jsmodulesValidator.checkFullSchema(
|
|
443
|
+
jsModulesConfig,
|
|
444
|
+
this._themeConfigFactory?._configLoader.processedFiles,
|
|
445
|
+
buildName
|
|
446
|
+
);
|
|
447
|
+
jsBuildConfig = this._themeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
448
|
+
} else if (this._layoutModulesConfigLoader.isExtraJSBuild(buildName)) {
|
|
449
|
+
const [theme, suffix] = this._layoutModulesConfigLoader.splitBuildName(buildName);
|
|
450
|
+
skipCSS = true;
|
|
451
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
452
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
453
|
+
const baseConfig = this._layoutThemeConfigFactory.loadConfig(theme, 'config/jsmodules.yml');
|
|
454
|
+
const extraConfig = this._layoutThemeConfigFactory.loadConfig(theme, `config/jsmodules-${suffix}.yml`);
|
|
455
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.extendConfig(baseConfig, extraConfig);
|
|
456
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
457
|
+
jsModulesConfig,
|
|
458
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
459
|
+
buildName
|
|
460
|
+
);
|
|
461
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
462
|
+
} else {
|
|
463
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[buildName];
|
|
464
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
465
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.loadConfig(buildName, 'config/jsmodules.yml');
|
|
466
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
467
|
+
jsModulesConfig,
|
|
468
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
469
|
+
buildName
|
|
470
|
+
);
|
|
471
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
472
|
+
}
|
|
473
|
+
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
474
|
+
const resolvedBuildPath = path.join(this.resolvedPublicPath, buildPublicPath);
|
|
475
|
+
|
|
476
|
+
const resolverConfig = {
|
|
477
|
+
modules: [
|
|
478
|
+
resolvedBuildPath,
|
|
479
|
+
this.resolvedPublicPath,
|
|
480
|
+
path.join(this.resolvedProjectPath, '/assets'),
|
|
481
|
+
path.join(this.resolvedPublicPath, '/bundles'),
|
|
482
|
+
path.join(this.resolvedPublicPath, '/js'),
|
|
483
|
+
this.resolvedNodeModulesPath
|
|
484
|
+
],
|
|
485
|
+
alias: jsBuildConfig.aliases,
|
|
486
|
+
cacheWithContext: true,
|
|
487
|
+
symlinks: false
|
|
488
|
+
};
|
|
489
|
+
const resolver = (resolver => {
|
|
490
|
+
return moduleName => resolver({}, '', moduleName, {});
|
|
491
|
+
})(resolve.create.sync({...resolverConfig}));
|
|
492
|
+
|
|
493
|
+
const plugins = [];
|
|
494
|
+
if (rtlSupport && !skipCSS && !skipRTL) {
|
|
495
|
+
plugins.push(new RtlCssWebpackPlugin({
|
|
496
|
+
filename: '[name].rtl.css'
|
|
497
|
+
}));
|
|
498
|
+
}
|
|
351
499
|
|
|
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
|
-
}
|
|
500
|
+
const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
|
|
501
|
+
const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
|
|
392
502
|
|
|
393
|
-
|
|
394
|
-
|
|
503
|
+
const entryPoints = {...cssEntryPoints, ...jsEntryPoints};
|
|
504
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
395
507
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
508
|
+
return {
|
|
509
|
+
entry: entryPoints,
|
|
510
|
+
name: buildName + ' theme',
|
|
511
|
+
output: {
|
|
512
|
+
publicPath: buildPublicPath,
|
|
513
|
+
path: resolvedBuildPath
|
|
514
|
+
},
|
|
515
|
+
context: this.resolvedPublicPath,
|
|
516
|
+
resolve: {
|
|
517
|
+
...resolverConfig,
|
|
518
|
+
plugins: [
|
|
519
|
+
new MapModulesPlugin(prepareModulesMap(resolver, jsBuildConfig.map))
|
|
520
|
+
]
|
|
521
|
+
},
|
|
522
|
+
plugins,
|
|
523
|
+
module: {
|
|
524
|
+
rules: [
|
|
525
|
+
{
|
|
526
|
+
test: /[\/\\]configs\.json$/,
|
|
527
|
+
loader: 'config-loader',
|
|
528
|
+
options: {
|
|
529
|
+
resolver,
|
|
530
|
+
relativeTo: this.resolvedPublicPath
|
|
531
|
+
}
|
|
413
532
|
},
|
|
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;
|
|
533
|
+
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
534
|
+
]
|
|
535
|
+
}
|
|
432
536
|
};
|
|
433
537
|
}
|
|
434
538
|
|
|
@@ -438,10 +542,11 @@ class ConfigBuilder {
|
|
|
438
542
|
this._isProduction = args.mode === 'production';
|
|
439
543
|
this._symfonyEnv = env.symfony;
|
|
440
544
|
this._appConfig = AppConfigLoader.getConfig(this._cachePath, this._symfonyEnv);
|
|
545
|
+
this._appConfig.paths.push(this.resolvedProjectPath);
|
|
441
546
|
|
|
442
547
|
this._modulesConfigLoader = new ModulesConfigLoader(
|
|
443
548
|
this._appConfig.paths,
|
|
444
|
-
'/Resources/public/themes/',
|
|
549
|
+
['/Resources/public/themes/', '/public/themes/admin/'],
|
|
445
550
|
'settings.yml'
|
|
446
551
|
);
|
|
447
552
|
this._adminThemes = this._modulesConfigLoader.themeNames.map(themeName => 'admin.' + themeName);
|
|
@@ -455,10 +560,9 @@ class ConfigBuilder {
|
|
|
455
560
|
|
|
456
561
|
this._layoutModulesConfigLoader = new LayoutModulesConfigLoader(
|
|
457
562
|
this._appConfig.paths,
|
|
458
|
-
'/Resources/views/layouts/',
|
|
563
|
+
['/Resources/views/layouts/', '/templates/layouts/'],
|
|
459
564
|
'theme.yml'
|
|
460
565
|
);
|
|
461
|
-
this._layoutThemes = this._layoutModulesConfigLoader.themeNames;
|
|
462
566
|
this._layoutStyleLoader = new LayoutStyleLoader(this._layoutModulesConfigLoader, entryPointFileWriter);
|
|
463
567
|
this._layoutThemeConfigFactory = new ThemeConfigFactory(
|
|
464
568
|
this._layoutModulesConfigLoader,
|
|
@@ -468,6 +572,13 @@ class ConfigBuilder {
|
|
|
468
572
|
);
|
|
469
573
|
}
|
|
470
574
|
|
|
575
|
+
_getVersionedPath(name, assetVersion) {
|
|
576
|
+
if (!assetVersion) {
|
|
577
|
+
return name;
|
|
578
|
+
}
|
|
579
|
+
return printf(this._versionFormat, name, assetVersion);
|
|
580
|
+
}
|
|
581
|
+
|
|
471
582
|
_getCssEntryPoints(theme, buildPath) {
|
|
472
583
|
if (this._isAdminTheme(theme)) {
|
|
473
584
|
return this._adminStyleLoader.getThemeEntryPoints(theme.split('.')[1], buildPath);
|
|
@@ -476,25 +587,25 @@ class ConfigBuilder {
|
|
|
476
587
|
return this._layoutStyleLoader.getThemeEntryPoints(theme, buildPath);
|
|
477
588
|
}
|
|
478
589
|
|
|
479
|
-
|
|
480
|
-
|
|
590
|
+
_validateBuildName(buildName) {
|
|
591
|
+
const buildNames = [...this._adminThemes];
|
|
481
592
|
if (this._enableLayoutThemes) {
|
|
482
|
-
|
|
593
|
+
buildNames.push(...this._layoutModulesConfigLoader.buildNames);
|
|
483
594
|
}
|
|
484
|
-
if (
|
|
595
|
+
if (buildName === 'admin') {
|
|
485
596
|
throw new Error(
|
|
486
597
|
'The "admin" is a reserved word and cannot be used as a theme name.'
|
|
487
598
|
);
|
|
488
599
|
}
|
|
489
|
-
if (
|
|
600
|
+
if (buildName !== undefined && !buildNames.includes(buildName)) {
|
|
490
601
|
throw new Error(
|
|
491
|
-
'Theme "' +
|
|
602
|
+
'Theme "' + buildName + '" doesn\'t exists. Existing themes:' + buildNames.join(', ')
|
|
492
603
|
);
|
|
493
604
|
}
|
|
494
605
|
}
|
|
495
606
|
|
|
496
607
|
_isAdminTheme(theme) {
|
|
497
|
-
return this._adminThemes.
|
|
608
|
+
return this._adminThemes.includes(theme);
|
|
498
609
|
}
|
|
499
610
|
}
|
|
500
611
|
|