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