@oroinc/oro-webpack-config-builder 4.2.1-dev8 → 5.1.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +57 -15
- package/oro-webpack-config.js +416 -310
- package/package.json +36 -34
- package/plugin/logs/after-webpack-logs-plugin.js +25 -0
- package/prepare-modules-shim.js +15 -3
- package/style/admin-style-loader.js +23 -0
- package/style/layout-style-loader.js +12 -109
- package/style/style-loader.js +156 -46
- 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,34 +3,44 @@ 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
|
-
const
|
|
15
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
16
16
|
const prepareModulesShim = require('./prepare-modules-shim');
|
|
17
|
-
const
|
|
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
|
-
const
|
|
25
|
+
const RtlCssWebpackPlugin = require('rtlcss-webpack-plugin');
|
|
26
|
+
const validation = require('./validation');
|
|
27
|
+
const EventEmitter = require('events');
|
|
28
|
+
const ErrorHandler = require('./error-handler');
|
|
29
|
+
|
|
30
|
+
require('resolve-url-loader');
|
|
25
31
|
|
|
26
32
|
class ConfigBuilder {
|
|
27
33
|
constructor() {
|
|
28
|
-
this.
|
|
29
|
-
this._adminTheme = 'admin.oro';
|
|
34
|
+
this._projectPath = '';
|
|
30
35
|
this._enableLayoutThemes = false;
|
|
31
36
|
this._defaultLayoutThemes = null;
|
|
32
|
-
this.
|
|
33
|
-
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({
|
|
34
44
|
sourceType: 'unambiguous',
|
|
35
45
|
presets: [
|
|
36
46
|
[
|
|
@@ -46,7 +56,12 @@ class ConfigBuilder {
|
|
|
46
56
|
plugins: [
|
|
47
57
|
'@babel/plugin-transform-runtime'
|
|
48
58
|
]
|
|
49
|
-
};
|
|
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));
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
/**
|
|
@@ -56,6 +71,7 @@ class ConfigBuilder {
|
|
|
56
71
|
*/
|
|
57
72
|
setPublicPath(publicPath) {
|
|
58
73
|
this._publicPath = publicPath;
|
|
74
|
+
this.emitter.emit('publicPath:updated', publicPath);
|
|
59
75
|
return this;
|
|
60
76
|
}
|
|
61
77
|
|
|
@@ -71,12 +87,13 @@ class ConfigBuilder {
|
|
|
71
87
|
|
|
72
88
|
/**
|
|
73
89
|
* Specifies a sprintf pattern that will be used with the version option to construct an asset’s path.
|
|
74
|
-
* By default ts `%s?
|
|
90
|
+
* By default ts `%s?v=%s`
|
|
75
91
|
* @param {string} versionFormat
|
|
76
92
|
* @returns {ConfigBuilder}
|
|
77
93
|
*/
|
|
78
94
|
setVersionFormat(versionFormat) {
|
|
79
95
|
this._versionFormat = versionFormat;
|
|
96
|
+
this.emitter.emit('versionFormat:updated', versionFormat);
|
|
80
97
|
return this;
|
|
81
98
|
}
|
|
82
99
|
|
|
@@ -93,6 +110,7 @@ class ConfigBuilder {
|
|
|
93
110
|
}
|
|
94
111
|
|
|
95
112
|
this._adminTheme = adminTheme;
|
|
113
|
+
this.emitter.emit('adminTheme:updated', adminTheme);
|
|
96
114
|
return this;
|
|
97
115
|
}
|
|
98
116
|
|
|
@@ -102,8 +120,10 @@ class ConfigBuilder {
|
|
|
102
120
|
enableLayoutThemes(themes) {
|
|
103
121
|
if (themes) {
|
|
104
122
|
this._defaultLayoutThemes = themes;
|
|
123
|
+
this.emitter.emit('defaultLayoutThemes:updated', themes);
|
|
105
124
|
}
|
|
106
125
|
this._enableLayoutThemes = true;
|
|
126
|
+
this.emitter.emit('enableLayoutThemes:updated', true);
|
|
107
127
|
return this;
|
|
108
128
|
}
|
|
109
129
|
|
|
@@ -114,6 +134,7 @@ class ConfigBuilder {
|
|
|
114
134
|
*/
|
|
115
135
|
setBabelConfig(babelConfig) {
|
|
116
136
|
this._babelConfig = babelConfig;
|
|
137
|
+
this.emitter.emit('babelConfig:updated', babelConfig);
|
|
117
138
|
return this;
|
|
118
139
|
}
|
|
119
140
|
|
|
@@ -125,331 +146,411 @@ class ConfigBuilder {
|
|
|
125
146
|
return (env = {}, args = {}) => {
|
|
126
147
|
this._initialize(args, env);
|
|
127
148
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (selectedTheme === undefined) {
|
|
135
|
-
// themes.push(this._adminTheme.split(".")[1]);
|
|
136
|
-
themes.push(this._adminTheme);
|
|
137
|
-
} else if (this._adminThemes.indexOf(selectedTheme) !== -1) {
|
|
138
|
-
// themes.push(selectedTheme.split(".")[1]);
|
|
139
|
-
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);
|
|
140
155
|
}
|
|
141
156
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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);
|
|
154
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
|
+
});
|
|
155
249
|
}
|
|
250
|
+
}
|
|
156
251
|
|
|
157
|
-
|
|
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
|
-
minSize: 30,
|
|
197
|
-
minChunks: 2,
|
|
198
|
-
priority: 10,
|
|
199
|
-
reuseExistingChunk: true
|
|
200
|
-
},
|
|
201
|
-
tinymce: {
|
|
202
|
-
test: /tinymce/,
|
|
203
|
-
name: 'tinymce.min',
|
|
204
|
-
minChunks: 1
|
|
205
|
-
},
|
|
206
|
-
fusioncharts: {
|
|
207
|
-
test: /fusioncharts/,
|
|
208
|
-
name: 'fusioncharts',
|
|
209
|
-
minChunks: 1
|
|
210
|
-
}
|
|
211
|
-
}
|
|
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
|
|
212
291
|
}
|
|
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
|
-
|
|
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: {
|
|
241
326
|
plugins: [
|
|
242
327
|
require('autoprefixer')
|
|
243
328
|
]
|
|
244
329
|
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
sassOptions: {
|
|
249
|
-
includePaths: [
|
|
250
|
-
path.join(resolvedPublicPath, '/bundles')
|
|
251
|
-
],
|
|
252
|
-
outputStyle: 'expanded'
|
|
253
|
-
},
|
|
254
|
-
sourceMap: true
|
|
255
|
-
}
|
|
256
|
-
}]
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
260
|
-
loader: 'url-loader',
|
|
330
|
+
}
|
|
331
|
+
}, {
|
|
332
|
+
loader: 'sass-loader',
|
|
261
333
|
options: {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
334
|
+
implementation: require("sass"),
|
|
335
|
+
sassOptions: {
|
|
336
|
+
includePaths: [
|
|
337
|
+
path.join(this.resolvedPublicPath, '/bundles')
|
|
338
|
+
],
|
|
339
|
+
outputStyle: 'expanded'
|
|
340
|
+
},
|
|
341
|
+
sourceMap: true
|
|
267
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)
|
|
268
354
|
}
|
|
269
|
-
|
|
270
|
-
},
|
|
271
|
-
performance: {hints: false},
|
|
272
|
-
plugins: [
|
|
273
|
-
new MiniCssExtractPlugin({
|
|
274
|
-
filename: '[name].css'
|
|
275
|
-
}),
|
|
276
|
-
new CleanupStatsPlugin(),
|
|
277
|
-
// Ignore all locale files of moment.js
|
|
278
|
-
new webpack.IgnorePlugin({
|
|
279
|
-
resourceRegExp: /^\.[\/\\]locale$/,
|
|
280
|
-
contextRegExp: /moment$/
|
|
281
|
-
}),
|
|
282
|
-
new webpack.optimize.MinChunkSizePlugin({
|
|
283
|
-
minChunkSize: 30000 // Minimum number of characters
|
|
284
|
-
})
|
|
355
|
+
}
|
|
285
356
|
]
|
|
286
|
-
}
|
|
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
|
+
};
|
|
287
377
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
378
|
+
if (env.analyze) {
|
|
379
|
+
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
380
|
+
}
|
|
291
381
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
test: /\.js$/,
|
|
307
|
-
exclude: [
|
|
308
|
-
/[\/\\]platform[\/\\]build[\/\\]/,
|
|
309
|
-
/[\/\\]node_modules[\/\\]/,
|
|
310
|
-
/[\/\\]bundles[\/\\].+[\/\\]lib[\/\\]?/
|
|
311
|
-
],
|
|
312
|
-
use: 'happypack/loader?id=babel'
|
|
313
|
-
});
|
|
314
|
-
}
|
|
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
|
+
}
|
|
315
396
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
+
}
|
|
336
417
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
plugins: [
|
|
343
|
-
new OptimizeCssAssetsPlugin({
|
|
344
|
-
cssProcessorPluginOptions: {
|
|
345
|
-
preset: ['default', {
|
|
346
|
-
// preserve comments for WebpackRTLPlugin, comments will be removed anyway later
|
|
347
|
-
discardComments: false,
|
|
348
|
-
}],
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
]
|
|
352
|
-
});
|
|
353
|
-
}
|
|
418
|
+
// Additional setting for production mode
|
|
419
|
+
if (this._isProduction) {
|
|
420
|
+
webpackConfig.devtool = false;
|
|
421
|
+
webpackConfig.plugins.push(new CssMinimizerPlugin());
|
|
422
|
+
}
|
|
354
423
|
|
|
355
|
-
|
|
424
|
+
return webpackConfig;
|
|
425
|
+
}
|
|
356
426
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
+
}
|
|
398
499
|
|
|
399
|
-
|
|
400
|
-
|
|
500
|
+
const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
|
|
501
|
+
const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
|
|
401
502
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
webpackConfigs.push(webpackMerge({
|
|
407
|
-
entry: entryPoints,
|
|
408
|
-
name: theme + ' theme',
|
|
409
|
-
output: {
|
|
410
|
-
publicPath: buildPublicPath,
|
|
411
|
-
path: resolvedBuildPath
|
|
412
|
-
},
|
|
413
|
-
context: resolvedPublicPath,
|
|
414
|
-
resolve: {
|
|
415
|
-
...resolverConfig,
|
|
416
|
-
plugins: [
|
|
417
|
-
new MapModulesPlugin(prepareModulesMap(resolver, themeConfig.map))
|
|
418
|
-
]
|
|
419
|
-
},
|
|
420
|
-
plugins,
|
|
421
|
-
module: {
|
|
422
|
-
rules: [
|
|
423
|
-
{
|
|
424
|
-
test: /[\/\\]configs\.json$/,
|
|
425
|
-
loader: 'config-loader',
|
|
426
|
-
options: {
|
|
427
|
-
resolver,
|
|
428
|
-
relativeTo: resolvedPublicPath
|
|
429
|
-
}
|
|
430
|
-
},
|
|
431
|
-
...prepareModulesShim(resolver, themeConfig.shim)
|
|
432
|
-
]
|
|
433
|
-
}
|
|
434
|
-
}, webpackConfig));
|
|
435
|
-
});
|
|
503
|
+
const entryPoints = {...cssEntryPoints, ...jsEntryPoints};
|
|
504
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
436
507
|
|
|
437
|
-
|
|
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
|
+
}
|
|
532
|
+
},
|
|
533
|
+
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
534
|
+
]
|
|
535
|
+
}
|
|
438
536
|
};
|
|
439
537
|
}
|
|
440
538
|
|
|
441
539
|
_initialize(args, env) {
|
|
540
|
+
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
541
|
+
|
|
442
542
|
this._isProduction = args.mode === 'production';
|
|
443
543
|
this._symfonyEnv = env.symfony;
|
|
444
544
|
this._appConfig = AppConfigLoader.getConfig(this._cachePath, this._symfonyEnv);
|
|
545
|
+
this._appConfig.paths.push(this.resolvedProjectPath);
|
|
445
546
|
|
|
446
547
|
this._modulesConfigLoader = new ModulesConfigLoader(
|
|
447
548
|
this._appConfig.paths,
|
|
448
|
-
'/Resources/public/themes/',
|
|
549
|
+
['/Resources/public/themes/', '/public/themes/admin/'],
|
|
449
550
|
'settings.yml'
|
|
450
551
|
);
|
|
451
552
|
this._adminThemes = this._modulesConfigLoader.themeNames.map(themeName => 'admin.' + themeName);
|
|
452
|
-
this.
|
|
553
|
+
this._adminStyleLoader = new AdminStyleLoader(this._modulesConfigLoader, entryPointFileWriter);
|
|
453
554
|
this._themeConfigFactory = new ThemeConfigFactory(
|
|
454
555
|
this._modulesConfigLoader,
|
|
455
556
|
new DynamicImportsFileWriter(this._publicPath),
|
|
@@ -459,11 +560,9 @@ class ConfigBuilder {
|
|
|
459
560
|
|
|
460
561
|
this._layoutModulesConfigLoader = new LayoutModulesConfigLoader(
|
|
461
562
|
this._appConfig.paths,
|
|
462
|
-
'/Resources/views/layouts/',
|
|
563
|
+
['/Resources/views/layouts/', '/templates/layouts/'],
|
|
463
564
|
'theme.yml'
|
|
464
565
|
);
|
|
465
|
-
this._layoutThemes = this._layoutModulesConfigLoader.themeNames;
|
|
466
|
-
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
467
566
|
this._layoutStyleLoader = new LayoutStyleLoader(this._layoutModulesConfigLoader, entryPointFileWriter);
|
|
468
567
|
this._layoutThemeConfigFactory = new ThemeConfigFactory(
|
|
469
568
|
this._layoutModulesConfigLoader,
|
|
@@ -473,33 +572,40 @@ class ConfigBuilder {
|
|
|
473
572
|
);
|
|
474
573
|
}
|
|
475
574
|
|
|
575
|
+
_getVersionedPath(name, assetVersion) {
|
|
576
|
+
if (!assetVersion) {
|
|
577
|
+
return name;
|
|
578
|
+
}
|
|
579
|
+
return printf(this._versionFormat, name, assetVersion);
|
|
580
|
+
}
|
|
581
|
+
|
|
476
582
|
_getCssEntryPoints(theme, buildPath) {
|
|
477
583
|
if (this._isAdminTheme(theme)) {
|
|
478
|
-
return this.
|
|
584
|
+
return this._adminStyleLoader.getThemeEntryPoints(theme.split('.')[1], buildPath);
|
|
479
585
|
}
|
|
480
586
|
|
|
481
587
|
return this._layoutStyleLoader.getThemeEntryPoints(theme, buildPath);
|
|
482
588
|
}
|
|
483
589
|
|
|
484
|
-
|
|
485
|
-
|
|
590
|
+
_validateBuildName(buildName) {
|
|
591
|
+
const buildNames = [...this._adminThemes];
|
|
486
592
|
if (this._enableLayoutThemes) {
|
|
487
|
-
|
|
593
|
+
buildNames.push(...this._layoutModulesConfigLoader.buildNames);
|
|
488
594
|
}
|
|
489
|
-
if (
|
|
595
|
+
if (buildName === 'admin') {
|
|
490
596
|
throw new Error(
|
|
491
597
|
'The "admin" is a reserved word and cannot be used as a theme name.'
|
|
492
598
|
);
|
|
493
599
|
}
|
|
494
|
-
if (
|
|
600
|
+
if (buildName !== undefined && !buildNames.includes(buildName)) {
|
|
495
601
|
throw new Error(
|
|
496
|
-
'Theme "' +
|
|
602
|
+
'Theme "' + buildName + '" doesn\'t exists. Existing themes:' + buildNames.join(', ')
|
|
497
603
|
);
|
|
498
604
|
}
|
|
499
605
|
}
|
|
500
606
|
|
|
501
607
|
_isAdminTheme(theme) {
|
|
502
|
-
return this._adminThemes.
|
|
608
|
+
return this._adminThemes.includes(theme);
|
|
503
609
|
}
|
|
504
610
|
}
|
|
505
611
|
|