@oroinc/oro-webpack-config-builder 5.1.0-alpha5 → 5.1.0-alpha50
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 +67 -3
- package/modules-config/modules-config-loader.js +49 -14
- package/oro-webpack-config.js +406 -296
- package/package.json +37 -36
- package/plugin/logs/after-webpack-logs-plugin.js +25 -0
- package/prepare-modules-shim.js +13 -1
- 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,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,32 @@ 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._publicPath = 'public/';
|
|
29
|
-
this._adminTheme = 'admin.oro';
|
|
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,310 +146,394 @@ 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 resolvedPublicPath() {
|
|
190
|
+
if (this._resolvedPublicPath === undefined) {
|
|
191
|
+
this._resolvedPublicPath = path.resolve(this._publicPath);
|
|
192
|
+
}
|
|
193
|
+
return this._resolvedPublicPath;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
get resolvedNodeModulesPath() {
|
|
197
|
+
if (this._resolvedNodeModulesPath === undefined) {
|
|
198
|
+
this._resolvedNodeModulesPath = path.resolve('node_modules');
|
|
199
|
+
}
|
|
200
|
+
return this._resolvedNodeModulesPath;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
get assetVersion() {
|
|
204
|
+
if (this._assetVersion === undefined) {
|
|
205
|
+
const filePath = path.join(this.resolvedPublicPath, '/build/build_version.txt');
|
|
206
|
+
this._assetVersion = fs.existsSync(filePath) ? String(fs.readFileSync(filePath)) : null;
|
|
207
|
+
}
|
|
208
|
+
return this._assetVersion;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
_getBuildNames(requestedBuildNames = []) {
|
|
212
|
+
const buildNames = [];
|
|
213
|
+
requestedBuildNames.forEach(buildName => this._validateBuildName(buildName));
|
|
214
|
+
|
|
215
|
+
// Admin themes
|
|
216
|
+
if (!requestedBuildNames.length) {
|
|
217
|
+
buildNames.push(this._adminTheme);
|
|
218
|
+
} else {
|
|
219
|
+
requestedBuildNames.forEach(buildName => {
|
|
220
|
+
if (this._isAdminTheme(buildName)) {
|
|
221
|
+
buildNames.push(buildName);
|
|
154
222
|
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Layout Themes
|
|
227
|
+
if (this._enableLayoutThemes) {
|
|
228
|
+
if (!requestedBuildNames.length) {
|
|
229
|
+
// build all layout themes
|
|
230
|
+
const themes = this._defaultLayoutThemes || this._appConfig.themes;
|
|
231
|
+
buildNames.push(...themes);
|
|
232
|
+
themes.forEach(theme => {
|
|
233
|
+
buildNames.push(...this._layoutModulesConfigLoader.extraJSBuildNames(theme));
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
// build single layout theme
|
|
237
|
+
requestedBuildNames.forEach(buildName => {
|
|
238
|
+
if (this._layoutModulesConfigLoader.buildNames.includes(buildName)) {
|
|
239
|
+
buildNames.push(buildName);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
155
242
|
}
|
|
243
|
+
}
|
|
156
244
|
|
|
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
|
-
}
|
|
245
|
+
return buildNames;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
_getCommonWebpackConfig(args, env) {
|
|
249
|
+
const stats = env.stats || {
|
|
250
|
+
hash: false,
|
|
251
|
+
version: false,
|
|
252
|
+
// Do not write the information about files emitted from node_modules or public bundles,
|
|
253
|
+
// and hide css/*/*.js files from the output.
|
|
254
|
+
excludeAssets: [/^bundles\//, /^\.\.\/_static\//, /^css\/.+\.js/],
|
|
255
|
+
children: false,
|
|
256
|
+
entrypoints: false,
|
|
257
|
+
performance: this._isProduction,
|
|
258
|
+
chunks: false,
|
|
259
|
+
modules: false,
|
|
260
|
+
source: false,
|
|
261
|
+
publicPath: true,
|
|
262
|
+
builtAt: false,
|
|
263
|
+
warnings: false
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const webpackConfig = {
|
|
267
|
+
watchOptions: {
|
|
268
|
+
aggregateTimeout: 200,
|
|
269
|
+
ignored: /[\/\\]node_modules[\/\\].*\.js$/
|
|
270
|
+
},
|
|
271
|
+
stats,
|
|
272
|
+
output: {
|
|
273
|
+
filename: '[name].js',
|
|
274
|
+
// Because we use third party libraries 'chunkFilename' should include only [name]
|
|
275
|
+
chunkFilename: this._getVersionedPath('chunk/[name].js', this.assetVersion)
|
|
276
|
+
},
|
|
277
|
+
devtool: !env.skipSourcemap && 'inline-cheap-module-source-map',
|
|
278
|
+
mode: 'development',
|
|
279
|
+
optimization: {
|
|
280
|
+
moduleIds: 'named',
|
|
281
|
+
splitChunks: {
|
|
282
|
+
cacheGroups: {
|
|
283
|
+
defaultVendors: false
|
|
209
284
|
}
|
|
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
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
resolveLoader: {
|
|
288
|
+
modules: [
|
|
289
|
+
this.resolvedPublicPath,
|
|
290
|
+
path.join(__dirname, './loader'),
|
|
291
|
+
path.join(this.resolvedPublicPath, '/bundles'),
|
|
292
|
+
this.resolvedNodeModulesPath
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
module: {
|
|
296
|
+
noParse: [
|
|
297
|
+
/[\/\\]bundles[\/\\]\.*[\/\\]lib[\/\\](?!chaplin|bootstrap|jquery\.dialog).*\.js$/
|
|
298
|
+
],
|
|
299
|
+
rules: [
|
|
300
|
+
{
|
|
301
|
+
test: /\.s?css$/,
|
|
302
|
+
use: [{
|
|
303
|
+
loader: args.hot ? 'style-loader' : MiniCssExtractPlugin.loader
|
|
304
|
+
}, {
|
|
305
|
+
loader: 'css-loader',
|
|
306
|
+
options: {
|
|
307
|
+
importLoaders: 1,
|
|
308
|
+
sourceMap: true,
|
|
309
|
+
// can't use esModule since resolve-url-loader needs file path to start with '~'
|
|
310
|
+
esModule: false
|
|
311
|
+
}
|
|
312
|
+
}, {
|
|
313
|
+
loader: 'resolve-url-loader'
|
|
314
|
+
}, {
|
|
315
|
+
loader: 'postcss-loader',
|
|
316
|
+
options: {
|
|
317
|
+
sourceMap: true,
|
|
318
|
+
postcssOptions: {
|
|
319
|
+
plugins: [
|
|
320
|
+
require('autoprefixer')
|
|
321
|
+
]
|
|
254
322
|
}
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
|
|
258
|
-
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
259
|
-
loader: 'url-loader',
|
|
323
|
+
}
|
|
324
|
+
}, {
|
|
325
|
+
loader: 'sass-loader',
|
|
260
326
|
options: {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
327
|
+
sassOptions: {
|
|
328
|
+
includePaths: [
|
|
329
|
+
path.join(this.resolvedPublicPath, '/bundles')
|
|
330
|
+
],
|
|
331
|
+
outputStyle: 'expanded'
|
|
332
|
+
},
|
|
333
|
+
sourceMap: true
|
|
266
334
|
}
|
|
335
|
+
}]
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
test: /\.(eot|ttf|woff|woff2|cur|ico|svg|png|jpg|gif)$/,
|
|
339
|
+
loader: 'url-loader',
|
|
340
|
+
options: {
|
|
341
|
+
limit: 1,
|
|
342
|
+
emitFile: true,
|
|
343
|
+
outputPath: '../_static/',
|
|
344
|
+
publicPath: '../../_static/',
|
|
345
|
+
name: this._getVersionedPath('[path][name].[ext]', this.assetVersion)
|
|
267
346
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
},
|
|
350
|
+
performance: {hints: false},
|
|
351
|
+
plugins: [
|
|
352
|
+
new MiniCssExtractPlugin({
|
|
353
|
+
filename: '[name].css'
|
|
354
|
+
}),
|
|
355
|
+
new CleanupStatsPlugin(),
|
|
356
|
+
// Ignore all locale files of moment.js
|
|
357
|
+
new webpack.IgnorePlugin({
|
|
358
|
+
resourceRegExp: /^\.[\/\\]locale$/,
|
|
359
|
+
contextRegExp: /moment$/
|
|
360
|
+
}),
|
|
361
|
+
new webpack.optimize.MinChunkSizePlugin({
|
|
362
|
+
minChunkSize: 30000 // Minimum number of characters
|
|
363
|
+
}),
|
|
364
|
+
new AfterWebpackLogsPlugin(
|
|
365
|
+
stats => this.emitter.emit('build:complete', stats)
|
|
366
|
+
)
|
|
367
|
+
]
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
if (env.analyze) {
|
|
371
|
+
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (!env.skipJS && !env.skipBabel) {
|
|
375
|
+
const happyPackOptions = {
|
|
376
|
+
id: 'babel',
|
|
377
|
+
loaders: [
|
|
378
|
+
{
|
|
379
|
+
loader: 'babel-loader',
|
|
380
|
+
options: this._babelConfig
|
|
381
|
+
}
|
|
284
382
|
]
|
|
285
383
|
};
|
|
286
384
|
|
|
287
|
-
|
|
288
|
-
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
|
289
|
-
}
|
|
385
|
+
webpackConfig.plugins.push(new HappyPack(happyPackOptions));
|
|
290
386
|
|
|
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
|
-
}
|
|
387
|
+
webpackConfig.module.rules.push({
|
|
388
|
+
test: /\.js$/,
|
|
389
|
+
exclude: [
|
|
390
|
+
/[\/\\]platform[\/\\]build[\/\\]/,
|
|
391
|
+
/[\/\\]node_modules[\/\\]/,
|
|
392
|
+
/[\/\\]bundles[\/\\].+[\/\\]lib[\/\\]?/
|
|
393
|
+
],
|
|
394
|
+
use: 'happypack/loader?id=babel'
|
|
395
|
+
});
|
|
396
|
+
}
|
|
314
397
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
398
|
+
if (args.hot) {
|
|
399
|
+
const https = this._appConfig.devServerOptions.https;
|
|
400
|
+
const schema = https ? 'https' : 'http';
|
|
401
|
+
const devServerHost = this._appConfig.devServerOptions.host;
|
|
402
|
+
const devServerPort = this._appConfig.devServerOptions.port;
|
|
403
|
+
webpackConfig.devServer = {
|
|
404
|
+
contentBase: this.resolvedPublicPath,
|
|
405
|
+
host: devServerHost,
|
|
406
|
+
port: devServerPort,
|
|
407
|
+
https: https,
|
|
408
|
+
compress: true,
|
|
409
|
+
stats: webpackConfig.stats,
|
|
410
|
+
disableHostCheck: true,
|
|
411
|
+
clientLogLevel: 'error',
|
|
412
|
+
headers: {
|
|
413
|
+
'Access-Control-Allow-Origin': '*'
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
webpackConfig.output.publicPath = `${schema}://${devServerHost}:${devServerPort}/`;
|
|
417
|
+
}
|
|
335
418
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
419
|
+
// Additional setting for production mode
|
|
420
|
+
if (this._isProduction) {
|
|
421
|
+
webpackConfig.devtool = false;
|
|
422
|
+
webpackConfig.plugins.push(new CssMinimizerPlugin());
|
|
423
|
+
}
|
|
340
424
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
]
|
|
344
|
-
});
|
|
345
|
-
}
|
|
425
|
+
return webpackConfig;
|
|
426
|
+
}
|
|
346
427
|
|
|
347
|
-
|
|
428
|
+
_getThemeWebpackConfig(buildName, args, env) {
|
|
429
|
+
let {skipCSS, skipJS, skipRTL} = env;
|
|
430
|
+
let themeDefinition;
|
|
431
|
+
let jsBuildConfig;
|
|
432
|
+
let buildPublicPath;
|
|
433
|
+
if (this._isAdminTheme(buildName)) {
|
|
434
|
+
themeDefinition = this._modulesConfigLoader.themes[buildName.split('.')[1]];
|
|
435
|
+
buildPublicPath = '/build/admin/';
|
|
436
|
+
const jsModulesConfig = this._themeConfigFactory.loadConfig(buildName,
|
|
437
|
+
['Resources/config/oro/jsmodules.yml', 'Resources/config/jsmodules.yml']);
|
|
438
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
439
|
+
jsModulesConfig,
|
|
440
|
+
this._themeConfigFactory?._configLoader.processedFiles,
|
|
441
|
+
buildName
|
|
442
|
+
);
|
|
443
|
+
jsBuildConfig = this._themeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
444
|
+
} else if (this._layoutModulesConfigLoader.isExtraJSBuild(buildName)) {
|
|
445
|
+
const [theme, suffix] = this._layoutModulesConfigLoader.splitBuildName(buildName);
|
|
446
|
+
skipCSS = true;
|
|
447
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[theme];
|
|
448
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
449
|
+
const baseConfig = this._layoutThemeConfigFactory.loadConfig(theme, 'config/jsmodules.yml');
|
|
450
|
+
const extraConfig = this._layoutThemeConfigFactory.loadConfig(theme, `config/jsmodules-${suffix}.yml`);
|
|
451
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.extendConfig(baseConfig, extraConfig);
|
|
452
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
453
|
+
jsModulesConfig,
|
|
454
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
455
|
+
buildName
|
|
456
|
+
);
|
|
457
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
458
|
+
} else {
|
|
459
|
+
themeDefinition = this._layoutModulesConfigLoader.themes[buildName];
|
|
460
|
+
buildPublicPath = `/build/${buildName}/`;
|
|
461
|
+
const jsModulesConfig = this._layoutThemeConfigFactory.loadConfig(buildName, 'config/jsmodules.yml');
|
|
462
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
463
|
+
jsModulesConfig,
|
|
464
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
465
|
+
buildName
|
|
466
|
+
);
|
|
467
|
+
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
468
|
+
}
|
|
469
|
+
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
470
|
+
const resolvedBuildPath = path.join(this.resolvedPublicPath, buildPublicPath);
|
|
471
|
+
|
|
472
|
+
const resolverConfig = {
|
|
473
|
+
modules: [
|
|
474
|
+
resolvedBuildPath,
|
|
475
|
+
this.resolvedPublicPath,
|
|
476
|
+
path.join(this.resolvedPublicPath, '/bundles'),
|
|
477
|
+
path.join(this.resolvedPublicPath, '/js'),
|
|
478
|
+
this.resolvedNodeModulesPath
|
|
479
|
+
],
|
|
480
|
+
alias: jsBuildConfig.aliases,
|
|
481
|
+
cacheWithContext: true,
|
|
482
|
+
symlinks: false
|
|
483
|
+
};
|
|
484
|
+
const resolver = (resolver => {
|
|
485
|
+
return moduleName => resolver({}, '', moduleName, {});
|
|
486
|
+
})(resolve.create.sync({...resolverConfig}));
|
|
487
|
+
|
|
488
|
+
const plugins = [];
|
|
489
|
+
if (rtlSupport && !skipCSS && !skipRTL) {
|
|
490
|
+
plugins.push(new RtlCssWebpackPlugin({
|
|
491
|
+
filename: '[name].rtl.css'
|
|
492
|
+
}));
|
|
493
|
+
}
|
|
348
494
|
|
|
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
|
-
}
|
|
495
|
+
const cssEntryPoints = !skipCSS ? this._getCssEntryPoints(buildName, buildPublicPath) : {};
|
|
496
|
+
const jsEntryPoints = !skipJS ? jsBuildConfig.entry : {};
|
|
388
497
|
|
|
389
|
-
|
|
390
|
-
|
|
498
|
+
const entryPoints = {...cssEntryPoints, ...jsEntryPoints};
|
|
499
|
+
if (Object.keys(entryPoints).length === 0) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
391
502
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
503
|
+
return {
|
|
504
|
+
entry: entryPoints,
|
|
505
|
+
name: buildName + ' theme',
|
|
506
|
+
output: {
|
|
507
|
+
publicPath: buildPublicPath,
|
|
508
|
+
path: resolvedBuildPath
|
|
509
|
+
},
|
|
510
|
+
context: this.resolvedPublicPath,
|
|
511
|
+
resolve: {
|
|
512
|
+
...resolverConfig,
|
|
513
|
+
plugins: [
|
|
514
|
+
new MapModulesPlugin(prepareModulesMap(resolver, jsBuildConfig.map))
|
|
515
|
+
]
|
|
516
|
+
},
|
|
517
|
+
plugins,
|
|
518
|
+
module: {
|
|
519
|
+
rules: [
|
|
520
|
+
{
|
|
521
|
+
test: /[\/\\]configs\.json$/,
|
|
522
|
+
loader: 'config-loader',
|
|
523
|
+
options: {
|
|
524
|
+
resolver,
|
|
525
|
+
relativeTo: this.resolvedPublicPath
|
|
526
|
+
}
|
|
409
527
|
},
|
|
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;
|
|
528
|
+
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
529
|
+
]
|
|
530
|
+
}
|
|
428
531
|
};
|
|
429
532
|
}
|
|
430
533
|
|
|
431
534
|
_initialize(args, env) {
|
|
535
|
+
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
536
|
+
|
|
432
537
|
this._isProduction = args.mode === 'production';
|
|
433
538
|
this._symfonyEnv = env.symfony;
|
|
434
539
|
this._appConfig = AppConfigLoader.getConfig(this._cachePath, this._symfonyEnv);
|
|
@@ -439,7 +544,7 @@ class ConfigBuilder {
|
|
|
439
544
|
'settings.yml'
|
|
440
545
|
);
|
|
441
546
|
this._adminThemes = this._modulesConfigLoader.themeNames.map(themeName => 'admin.' + themeName);
|
|
442
|
-
this.
|
|
547
|
+
this._adminStyleLoader = new AdminStyleLoader(this._modulesConfigLoader, entryPointFileWriter);
|
|
443
548
|
this._themeConfigFactory = new ThemeConfigFactory(
|
|
444
549
|
this._modulesConfigLoader,
|
|
445
550
|
new DynamicImportsFileWriter(this._publicPath),
|
|
@@ -452,8 +557,6 @@ class ConfigBuilder {
|
|
|
452
557
|
'/Resources/views/layouts/',
|
|
453
558
|
'theme.yml'
|
|
454
559
|
);
|
|
455
|
-
this._layoutThemes = this._layoutModulesConfigLoader.themeNames;
|
|
456
|
-
const entryPointFileWriter = new EntryPointFileWriter(this._publicPath);
|
|
457
560
|
this._layoutStyleLoader = new LayoutStyleLoader(this._layoutModulesConfigLoader, entryPointFileWriter);
|
|
458
561
|
this._layoutThemeConfigFactory = new ThemeConfigFactory(
|
|
459
562
|
this._layoutModulesConfigLoader,
|
|
@@ -463,33 +566,40 @@ class ConfigBuilder {
|
|
|
463
566
|
);
|
|
464
567
|
}
|
|
465
568
|
|
|
569
|
+
_getVersionedPath(name, assetVersion) {
|
|
570
|
+
if (!assetVersion) {
|
|
571
|
+
return name;
|
|
572
|
+
}
|
|
573
|
+
return printf(this._versionFormat, name, assetVersion);
|
|
574
|
+
}
|
|
575
|
+
|
|
466
576
|
_getCssEntryPoints(theme, buildPath) {
|
|
467
577
|
if (this._isAdminTheme(theme)) {
|
|
468
|
-
return this.
|
|
578
|
+
return this._adminStyleLoader.getThemeEntryPoints(theme.split('.')[1], buildPath);
|
|
469
579
|
}
|
|
470
580
|
|
|
471
581
|
return this._layoutStyleLoader.getThemeEntryPoints(theme, buildPath);
|
|
472
582
|
}
|
|
473
583
|
|
|
474
|
-
|
|
475
|
-
|
|
584
|
+
_validateBuildName(buildName) {
|
|
585
|
+
const buildNames = [...this._adminThemes];
|
|
476
586
|
if (this._enableLayoutThemes) {
|
|
477
|
-
|
|
587
|
+
buildNames.push(...this._layoutModulesConfigLoader.buildNames);
|
|
478
588
|
}
|
|
479
|
-
if (
|
|
589
|
+
if (buildName === 'admin') {
|
|
480
590
|
throw new Error(
|
|
481
591
|
'The "admin" is a reserved word and cannot be used as a theme name.'
|
|
482
592
|
);
|
|
483
593
|
}
|
|
484
|
-
if (
|
|
594
|
+
if (buildName !== undefined && !buildNames.includes(buildName)) {
|
|
485
595
|
throw new Error(
|
|
486
|
-
'Theme "' +
|
|
596
|
+
'Theme "' + buildName + '" doesn\'t exists. Existing themes:' + buildNames.join(', ')
|
|
487
597
|
);
|
|
488
598
|
}
|
|
489
599
|
}
|
|
490
600
|
|
|
491
601
|
_isAdminTheme(theme) {
|
|
492
|
-
return this._adminThemes.
|
|
602
|
+
return this._adminThemes.includes(theme);
|
|
493
603
|
}
|
|
494
604
|
}
|
|
495
605
|
|