@oroinc/oro-webpack-config-builder 5.1.0-alpha8 → 5.1.0-lts001
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 +416 -301
- package/package.json +37 -37
- package/plugin/logs/after-webpack-logs-plugin.js +25 -0
- 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
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
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,322 +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));
|
|
154
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
|
+
});
|
|
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
|
-
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
|
-
}
|
|
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
|
|
209
291
|
}
|
|
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
|
|
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
|
+
]
|
|
254
329
|
}
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
259
|
-
loader: 'url-loader',
|
|
330
|
+
}
|
|
331
|
+
}, {
|
|
332
|
+
loader: 'sass-loader',
|
|
260
333
|
options: {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
334
|
+
implementation: require("sass"),
|
|
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
|
-
performance: {hints: false},
|
|
271
|
-
plugins: [
|
|
272
|
-
new MiniCssExtractPlugin({
|
|
273
|
-
filename: '[name].css'
|
|
274
|
-
}),
|
|
275
|
-
new CleanupStatsPlugin(),
|
|
276
|
-
// Ignore all locale files of moment.js
|
|
277
|
-
new webpack.IgnorePlugin({
|
|
278
|
-
resourceRegExp: /^\.[\/\\]locale$/,
|
|
279
|
-
contextRegExp: /moment$/
|
|
280
|
-
}),
|
|
281
|
-
new webpack.optimize.MinChunkSizePlugin({
|
|
282
|
-
minChunkSize: 30000 // Minimum number of characters
|
|
283
|
-
})
|
|
355
|
+
}
|
|
284
356
|
]
|
|
285
|
-
}
|
|
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
|
+
};
|
|
286
377
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
378
|
+
if (env.analyze) {
|
|
379
|
+
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
380
|
+
}
|
|
290
381
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
test: /\.js$/,
|
|
306
|
-
exclude: [
|
|
307
|
-
/[\/\\]platform[\/\\]build[\/\\]/,
|
|
308
|
-
/[\/\\]node_modules[\/\\]/,
|
|
309
|
-
/[\/\\]bundles[\/\\].+[\/\\]lib[\/\\]?/
|
|
310
|
-
],
|
|
311
|
-
use: 'happypack/loader?id=babel'
|
|
312
|
-
});
|
|
313
|
-
}
|
|
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
|
+
}
|
|
314
396
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
+
}
|
|
335
417
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
418
|
+
// Additional setting for production mode
|
|
419
|
+
if (this._isProduction) {
|
|
420
|
+
webpackConfig.devtool = false;
|
|
421
|
+
webpackConfig.plugins.push(new CssMinimizerPlugin());
|
|
422
|
+
}
|
|
340
423
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
]
|
|
344
|
-
});
|
|
345
|
-
}
|
|
424
|
+
return webpackConfig;
|
|
425
|
+
}
|
|
346
426
|
|
|
347
|
-
|
|
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
|
+
}
|
|
348
499
|
|
|
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,
|
|
358
|
-
['Resources/config/oro/jsmodules.yml', 'Resources/config/jsmodules.yml']);
|
|
359
|
-
} else {
|
|
360
|
-
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
361
|
-
buildPublicPath = `/build/${theme}/`;
|
|
362
|
-
themeConfig = this._layoutThemeConfigFactory
|
|
363
|
-
.create(theme, buildPublicPath, 'config/jsmodules.yml');
|
|
364
|
-
}
|
|
365
|
-
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
366
|
-
const resolvedBuildPath = path.join(resolvedPublicPath, buildPublicPath);
|
|
367
|
-
|
|
368
|
-
const resolverConfig = {
|
|
369
|
-
modules: [
|
|
370
|
-
resolvedBuildPath,
|
|
371
|
-
resolvedPublicPath,
|
|
372
|
-
resolvedPublicPath + '/bundles',
|
|
373
|
-
resolvedPublicPath + '/js',
|
|
374
|
-
resolvedNodeModulesPath
|
|
375
|
-
],
|
|
376
|
-
alias: themeConfig.aliases,
|
|
377
|
-
symlinks: false
|
|
378
|
-
};
|
|
379
|
-
const resolver = (resolver => {
|
|
380
|
-
return moduleName => resolver({}, '', moduleName, {});
|
|
381
|
-
})(resolve.create.sync({...resolverConfig}));
|
|
382
|
-
|
|
383
|
-
const plugins = [];
|
|
384
|
-
if (rtlSupport && !env.skipCSS && !env.skipRTL) {
|
|
385
|
-
plugins.push(new RtlCssWebpackPlugin({
|
|
386
|
-
filename: '[name].rtl.css'
|
|
387
|
-
}));
|
|
388
|
-
}
|
|
500
|
+
const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
|
|
501
|
+
const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
|
|
389
502
|
|
|
390
|
-
|
|
391
|
-
|
|
503
|
+
const entryPoints = {...cssEntryPoints, ...jsEntryPoints};
|
|
504
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
392
507
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
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
|
+
}
|
|
410
532
|
},
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
{
|
|
415
|
-
test: /[\/\\]configs\.json$/,
|
|
416
|
-
loader: 'config-loader',
|
|
417
|
-
options: {
|
|
418
|
-
resolver,
|
|
419
|
-
relativeTo: resolvedPublicPath
|
|
420
|
-
}
|
|
421
|
-
},
|
|
422
|
-
...prepareModulesShim(resolver, themeConfig.shim)
|
|
423
|
-
]
|
|
424
|
-
}
|
|
425
|
-
}, webpackConfig));
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
return webpackConfigs;
|
|
533
|
+
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
534
|
+
]
|
|
535
|
+
}
|
|
429
536
|
};
|
|
430
537
|
}
|
|
431
538
|
|
|
432
539
|
_initialize(args, env) {
|
|
540
|
+
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
541
|
+
|
|
433
542
|
this._isProduction = args.mode === 'production';
|
|
434
543
|
this._symfonyEnv = env.symfony;
|
|
435
544
|
this._appConfig = AppConfigLoader.getConfig(this._cachePath, this._symfonyEnv);
|
|
545
|
+
this._appConfig.paths.push(this.resolvedProjectPath);
|
|
436
546
|
|
|
437
547
|
this._modulesConfigLoader = new ModulesConfigLoader(
|
|
438
548
|
this._appConfig.paths,
|
|
439
|
-
'/Resources/public/themes/',
|
|
549
|
+
['/Resources/public/themes/', '/public/themes/admin/'],
|
|
440
550
|
'settings.yml'
|
|
441
551
|
);
|
|
442
552
|
this._adminThemes = this._modulesConfigLoader.themeNames.map(themeName => 'admin.' + themeName);
|
|
443
|
-
this.
|
|
553
|
+
this._adminStyleLoader = new AdminStyleLoader(this._modulesConfigLoader, entryPointFileWriter);
|
|
444
554
|
this._themeConfigFactory = new ThemeConfigFactory(
|
|
445
555
|
this._modulesConfigLoader,
|
|
446
556
|
new DynamicImportsFileWriter(this._publicPath),
|
|
@@ -450,11 +560,9 @@ class ConfigBuilder {
|
|
|
450
560
|
|
|
451
561
|
this._layoutModulesConfigLoader = new LayoutModulesConfigLoader(
|
|
452
562
|
this._appConfig.paths,
|
|
453
|
-
'/Resources/views/layouts/',
|
|
563
|
+
['/Resources/views/layouts/', '/templates/layouts/'],
|
|
454
564
|
'theme.yml'
|
|
455
565
|
);
|
|
456
|
-
this._layoutThemes = this._layoutModulesConfigLoader.themeNames;
|
|
457
|
-
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
458
566
|
this._layoutStyleLoader = new LayoutStyleLoader(this._layoutModulesConfigLoader, entryPointFileWriter);
|
|
459
567
|
this._layoutThemeConfigFactory = new ThemeConfigFactory(
|
|
460
568
|
this._layoutModulesConfigLoader,
|
|
@@ -464,33 +572,40 @@ class ConfigBuilder {
|
|
|
464
572
|
);
|
|
465
573
|
}
|
|
466
574
|
|
|
575
|
+
_getVersionedPath(name, assetVersion) {
|
|
576
|
+
if (!assetVersion) {
|
|
577
|
+
return name;
|
|
578
|
+
}
|
|
579
|
+
return printf(this._versionFormat, name, assetVersion);
|
|
580
|
+
}
|
|
581
|
+
|
|
467
582
|
_getCssEntryPoints(theme, buildPath) {
|
|
468
583
|
if (this._isAdminTheme(theme)) {
|
|
469
|
-
return this.
|
|
584
|
+
return this._adminStyleLoader.getThemeEntryPoints(theme.split('.')[1], buildPath);
|
|
470
585
|
}
|
|
471
586
|
|
|
472
587
|
return this._layoutStyleLoader.getThemeEntryPoints(theme, buildPath);
|
|
473
588
|
}
|
|
474
589
|
|
|
475
|
-
|
|
476
|
-
|
|
590
|
+
_validateBuildName(buildName) {
|
|
591
|
+
const buildNames = [...this._adminThemes];
|
|
477
592
|
if (this._enableLayoutThemes) {
|
|
478
|
-
|
|
593
|
+
buildNames.push(...this._layoutModulesConfigLoader.buildNames);
|
|
479
594
|
}
|
|
480
|
-
if (
|
|
595
|
+
if (buildName === 'admin') {
|
|
481
596
|
throw new Error(
|
|
482
597
|
'The "admin" is a reserved word and cannot be used as a theme name.'
|
|
483
598
|
);
|
|
484
599
|
}
|
|
485
|
-
if (
|
|
600
|
+
if (buildName !== undefined && !buildNames.includes(buildName)) {
|
|
486
601
|
throw new Error(
|
|
487
|
-
'Theme "' +
|
|
602
|
+
'Theme "' + buildName + '" doesn\'t exists. Existing themes:' + buildNames.join(', ')
|
|
488
603
|
);
|
|
489
604
|
}
|
|
490
605
|
}
|
|
491
606
|
|
|
492
607
|
_isAdminTheme(theme) {
|
|
493
|
-
return this._adminThemes.
|
|
608
|
+
return this._adminThemes.includes(theme);
|
|
494
609
|
}
|
|
495
610
|
}
|
|
496
611
|
|