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