@eclipse-scout/cli 22.0.41 → 23.1.0-beta.4
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/bin/scout-scripts.js +92 -18
- package/package.json +29 -27
- package/scripts/AfterEmitWebpackPlugin.js +5 -3
- package/scripts/StatsExtractWebpackPlugin.js +23 -0
- package/scripts/constants.js +38 -21
- package/scripts/files.js +66 -0
- package/scripts/karma-defaults.js +45 -11
- package/scripts/post-build.js +23 -14
- package/scripts/webpack-defaults.js +276 -81
- package/scripts/list-files.js +0 -26
package/bin/scout-scripts.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/*
|
|
3
2
|
* Copyright (c) 2010-2022 BSI Business Systems Integration AG.
|
|
4
3
|
* All rights reserved. This program and the accompanying materials
|
|
5
4
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
6
5
|
* which accompanies this distribution, and is available at
|
|
7
|
-
*
|
|
6
|
+
* https://www.eclipse.org/legal/epl-v10.html
|
|
8
7
|
*
|
|
9
8
|
* Contributors:
|
|
10
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
@@ -26,14 +25,26 @@ const argv = process.argv.slice(3);
|
|
|
26
25
|
const parser = require('yargs-parser');
|
|
27
26
|
const fs = require('fs');
|
|
28
27
|
const path = require('path');
|
|
28
|
+
const scoutBuildConstants = require('./../scripts/constants');
|
|
29
29
|
const webpackConfigFileName = './webpack.config.js';
|
|
30
30
|
const webpackCustomConfigFileName = './webpack.config.custom.js';
|
|
31
|
+
const StatsExtractWebpackPlugin = require('../scripts/StatsExtractWebpackPlugin');
|
|
31
32
|
const webpackYargsOptions = {
|
|
32
33
|
boolean: ['progress', 'profile', 'clean'],
|
|
33
34
|
array: ['resDirArray', 'themes']
|
|
34
35
|
};
|
|
36
|
+
const buildYargsOptions = {
|
|
37
|
+
array: ['run'],
|
|
38
|
+
default: {run: []}
|
|
39
|
+
};
|
|
35
40
|
const karmaYargsOptions = prepareWebpackYargsOptionsForKarma();
|
|
36
41
|
|
|
42
|
+
let buildArgs = parser(argv, buildYargsOptions);
|
|
43
|
+
if (buildArgs.run.length > 1) {
|
|
44
|
+
runBuilds(buildArgs);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
37
48
|
switch (script) {
|
|
38
49
|
case 'test-server:start': {
|
|
39
50
|
runKarma(null, false, parser(argv, karmaYargsOptions));
|
|
@@ -56,25 +67,30 @@ switch (script) {
|
|
|
56
67
|
if (args.webpackArgs.progress === undefined) {
|
|
57
68
|
args.webpackArgs.progress = false;
|
|
58
69
|
}
|
|
70
|
+
if (args.webpackArgs.watch === undefined) {
|
|
71
|
+
args.webpackArgs.watch = false;
|
|
72
|
+
}
|
|
59
73
|
runKarma(null, true, args);
|
|
60
74
|
break;
|
|
61
75
|
}
|
|
62
76
|
case 'build:dev': {
|
|
63
77
|
const args = parser(argv, webpackYargsOptions);
|
|
64
|
-
args.mode =
|
|
78
|
+
args.mode = scoutBuildConstants.mode.development;
|
|
65
79
|
runWebpack(args);
|
|
66
80
|
break;
|
|
67
81
|
}
|
|
68
82
|
case 'build:prod': {
|
|
69
83
|
const args = parser(argv, webpackYargsOptions);
|
|
70
|
-
args.mode =
|
|
84
|
+
args.mode = scoutBuildConstants.mode.production;
|
|
71
85
|
runWebpack(args);
|
|
72
86
|
break;
|
|
73
87
|
}
|
|
74
88
|
case 'build:dev:watch': {
|
|
75
89
|
const args = parser(argv, webpackYargsOptions);
|
|
76
|
-
args.mode =
|
|
77
|
-
|
|
90
|
+
args.mode = scoutBuildConstants.mode.development;
|
|
91
|
+
args.watch = true;
|
|
92
|
+
args.clean = true; // prevents errors because of old output folders in the development environment
|
|
93
|
+
runWebpack(args);
|
|
78
94
|
break;
|
|
79
95
|
}
|
|
80
96
|
default:
|
|
@@ -82,6 +98,20 @@ switch (script) {
|
|
|
82
98
|
break;
|
|
83
99
|
}
|
|
84
100
|
|
|
101
|
+
function runBuilds(args) {
|
|
102
|
+
const execSync = require('child_process').execSync;
|
|
103
|
+
let argStr = '';
|
|
104
|
+
for (let [key, value] of Object.entries(args)) {
|
|
105
|
+
if (key !== 'run' && key !== '_') {
|
|
106
|
+
argStr += `--${key} ${value} `;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (let type of args.run) {
|
|
110
|
+
console.log(`Starting ${type} build` + (argStr ? ` with args ${argStr}` : ''));
|
|
111
|
+
execSync(`scout-scripts ${script} --run ${type} ${argStr}`, {stdio: 'inherit'});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
85
115
|
function runKarma(configFileName, headless, args) {
|
|
86
116
|
const cfg = require('karma').config;
|
|
87
117
|
const cfgFile = configFileName || './karma.conf.js';
|
|
@@ -116,27 +146,77 @@ function runKarma(configFileName, headless, args) {
|
|
|
116
146
|
});
|
|
117
147
|
}
|
|
118
148
|
|
|
149
|
+
let exitCode = 100;
|
|
119
150
|
const Server = require('karma').Server;
|
|
120
|
-
const serverInstance = new Server(karmaConfig,
|
|
151
|
+
const serverInstance = new Server(karmaConfig, karmaExitCode => {
|
|
121
152
|
if (exitCode === 0) {
|
|
122
|
-
console.log('Karma has exited with 0');
|
|
153
|
+
console.log('Karma has exited with 0.');
|
|
154
|
+
process.exitCode = exitCode; // all fine: tests could be executed and no failures
|
|
155
|
+
} else if (exitCode === 10) {
|
|
156
|
+
console.log('Webpack build failed. See webpack output for details.');
|
|
157
|
+
process.exitCode = exitCode; // webpack error
|
|
158
|
+
} else if (exitCode === 4) {
|
|
159
|
+
console.log('There are test failures.');
|
|
160
|
+
process.exitCode = 0; // test could be executed but there are test failures: do not set exitCode to something other than 0 here because the build should continue even on failing tests.
|
|
123
161
|
} else {
|
|
124
|
-
console.log(`
|
|
162
|
+
console.log(`Error in test execution. Exit code: ${exitCode}.`);
|
|
163
|
+
process.exitCode = exitCode; // tests could not be executed because of an error. Let the process fail.
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
serverInstance.on('run_complete', (browsers, results) => {
|
|
168
|
+
// compute exit code based on webpack stats and karma result.
|
|
169
|
+
// Karma exitCode alone is not detailed enough (all problems have exitCode=1).
|
|
170
|
+
let webpackStats = null;
|
|
171
|
+
let statsExtractPlugins = karmaConfig.webpack.plugins.filter(p => p instanceof StatsExtractWebpackPlugin);
|
|
172
|
+
if (statsExtractPlugins && statsExtractPlugins.length) {
|
|
173
|
+
webpackStats = statsExtractPlugins[0].stats;
|
|
125
174
|
}
|
|
126
|
-
|
|
175
|
+
exitCode = computeExitCode(results, webpackStats);
|
|
127
176
|
});
|
|
177
|
+
|
|
128
178
|
console.log(`Starting Karma server using config file ${configFilePath}`);
|
|
129
179
|
serverInstance.start();
|
|
130
180
|
}
|
|
131
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Inspired by Karma.BrowserCollection.calculateExitCode().
|
|
184
|
+
*
|
|
185
|
+
* @param karmaResults The Karma results object
|
|
186
|
+
* @param webpackStats The Webpack build stats object
|
|
187
|
+
* @returns {number} The custom exit code
|
|
188
|
+
*/
|
|
189
|
+
function computeExitCode(karmaResults, webpackStats) {
|
|
190
|
+
if (webpackStats && webpackStats.hasErrors()) {
|
|
191
|
+
return 10; // webpack build failed
|
|
192
|
+
}
|
|
193
|
+
if (karmaResults.disconnected) {
|
|
194
|
+
return 2; // browser disconnected
|
|
195
|
+
}
|
|
196
|
+
if (karmaResults.error) {
|
|
197
|
+
return 3; // karma error
|
|
198
|
+
}
|
|
199
|
+
if (karmaResults.failed > 0) {
|
|
200
|
+
return 4; // tests could be executed but there are test failures (Karma uses exitCode=1 here which is not what we want)
|
|
201
|
+
}
|
|
202
|
+
return karmaResults.exitCode;
|
|
203
|
+
}
|
|
204
|
+
|
|
132
205
|
function runWebpack(args) {
|
|
133
206
|
const configFilePath = readWebpackConfig();
|
|
207
|
+
if (!configFilePath) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
134
210
|
const {compiler, statsConfig} = createWebpackCompiler(configFilePath, args);
|
|
135
|
-
|
|
211
|
+
if (args.watch) {
|
|
212
|
+
compiler.watch({}, (err, stats) => logWebpack(err, stats, statsConfig));
|
|
213
|
+
} else {
|
|
214
|
+
compiler.run((err, stats) => logWebpack(err, stats, statsConfig));
|
|
215
|
+
}
|
|
136
216
|
}
|
|
137
217
|
|
|
138
218
|
function readWebpackConfig() {
|
|
139
|
-
let configFilePath
|
|
219
|
+
let configFilePath;
|
|
140
220
|
const devConfigFilePath = path.resolve(webpackCustomConfigFileName);
|
|
141
221
|
if (fs.existsSync(devConfigFilePath)) {
|
|
142
222
|
console.log(`Reading config from ${webpackCustomConfigFileName}`);
|
|
@@ -152,12 +232,6 @@ function readWebpackConfig() {
|
|
|
152
232
|
return configFilePath;
|
|
153
233
|
}
|
|
154
234
|
|
|
155
|
-
function runWebpackWatch(args) {
|
|
156
|
-
const configFilePath = readWebpackConfig();
|
|
157
|
-
const {compiler, statsConfig} = createWebpackCompiler(configFilePath, args);
|
|
158
|
-
compiler.watch({}, (err, stats) => logWebpack(err, stats, statsConfig));
|
|
159
|
-
}
|
|
160
|
-
|
|
161
235
|
function createWebpackCompiler(configFilePath, args) {
|
|
162
236
|
const webpack = require('webpack');
|
|
163
237
|
const conf = require(configFilePath);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eclipse-scout/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "23.1.0-beta.4",
|
|
4
4
|
"description": "CLI for Eclipse Scout",
|
|
5
5
|
"author": "BSI Business Systems Integration AG",
|
|
6
6
|
"homepage": "https://www.eclipse.org/scout",
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
"license": "EPL-1.0",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
14
|
-
"npm": ">=
|
|
15
|
-
"pnpm": ">=
|
|
13
|
+
"node": ">=18.12.1",
|
|
14
|
+
"npm": ">=9.1.1",
|
|
15
|
+
"pnpm": ">=7.16.0"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"scout",
|
|
@@ -28,35 +28,37 @@
|
|
|
28
28
|
"scripts"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"
|
|
32
|
-
"@babel/core": "7.
|
|
33
|
-
"@babel/
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"copy-webpack-plugin": "
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"jasmine-core": "3.10.1",
|
|
31
|
+
"esbuild": "0.15.16",
|
|
32
|
+
"@babel/core": "7.20.5",
|
|
33
|
+
"@babel/preset-env": "7.20.2",
|
|
34
|
+
"babel-loader": "9.1.0",
|
|
35
|
+
"typescript": "4.9.3",
|
|
36
|
+
"ts-loader": "9.4.1",
|
|
37
|
+
"source-map-loader": "4.0.1",
|
|
38
|
+
"copy-webpack-plugin": "11.0.0",
|
|
39
|
+
"css-loader": "6.7.2",
|
|
40
|
+
"jasmine-core": "4.5.0",
|
|
42
41
|
"jasmine-jquery": "2.1.1",
|
|
43
42
|
"jquery": "3.6.0",
|
|
44
|
-
"karma": "6.
|
|
45
|
-
"karma-chrome-launcher": "3.1.
|
|
46
|
-
"karma-jasmine": "
|
|
43
|
+
"karma": "6.4.1",
|
|
44
|
+
"karma-chrome-launcher": "3.1.1",
|
|
45
|
+
"karma-jasmine": "5.1.0",
|
|
47
46
|
"karma-jasmine-ajax": "0.1.13",
|
|
48
47
|
"@metahub/karma-jasmine-jquery": "4.0.1",
|
|
49
|
-
"@eclipse-scout/karma-jasmine-scout": "
|
|
50
|
-
"
|
|
48
|
+
"@eclipse-scout/karma-jasmine-scout": "23.1.0-beta.4",
|
|
49
|
+
"@eclipse-scout/tsconfig": "23.1.0-beta.4",
|
|
50
|
+
"karma-jasmine-html-reporter": "2.0.0",
|
|
51
51
|
"karma-junit-reporter": "2.0.1",
|
|
52
52
|
"karma-webpack": "5.0.0",
|
|
53
|
-
"less": "4.1.
|
|
54
|
-
"less-loader": "
|
|
55
|
-
"mini-css-extract-plugin": "2.
|
|
56
|
-
"css-minimizer-webpack-plugin": "
|
|
57
|
-
"terser-webpack-plugin": "5.3.
|
|
58
|
-
"webpack": "5.
|
|
59
|
-
"yargs-parser": "21.
|
|
53
|
+
"less": "4.1.3",
|
|
54
|
+
"less-loader": "11.1.0",
|
|
55
|
+
"mini-css-extract-plugin": "2.7.1",
|
|
56
|
+
"css-minimizer-webpack-plugin": "4.2.2",
|
|
57
|
+
"terser-webpack-plugin": "5.3.6",
|
|
58
|
+
"webpack": "5.75.0",
|
|
59
|
+
"yargs-parser": "21.1.1",
|
|
60
|
+
"fork-ts-checker-webpack-plugin": "7.2.13",
|
|
61
|
+
"fork-ts-checker-notifier-webpack-plugin": "6.0.0"
|
|
60
62
|
},
|
|
61
63
|
"devDependencies": {
|
|
62
64
|
"@eclipse-scout/releng": "^22.0.0"
|
|
@@ -13,15 +13,17 @@ const scoutPostBuild = require('./post-build');
|
|
|
13
13
|
|
|
14
14
|
module.exports = class AfterEmitWebpackPlugin {
|
|
15
15
|
constructor(options = {}) {
|
|
16
|
-
const {outDir} = options;
|
|
17
|
-
this.options = {outDir};
|
|
16
|
+
const {outDir, createFileList} = options;
|
|
17
|
+
this.options = {outDir, createFileList};
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// noinspection JSUnusedGlobalSymbols
|
|
21
21
|
apply(compiler) {
|
|
22
22
|
compiler.hooks.afterEmit.tap(pluginName, compilation => {
|
|
23
23
|
scoutPostBuild.cleanOutDir(this.options.outDir);
|
|
24
|
-
|
|
24
|
+
if (this.options.createFileList ?? true) {
|
|
25
|
+
scoutPostBuild.createFileList(this.options.outDir);
|
|
26
|
+
}
|
|
25
27
|
});
|
|
26
28
|
}
|
|
27
29
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010-2022 BSI Business Systems Integration AG.
|
|
3
|
+
* All rights reserved. This program and the accompanying materials
|
|
4
|
+
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
|
+
* which accompanies this distribution, and is available at
|
|
6
|
+
* https://www.eclipse.org/legal/epl-v10.html
|
|
7
|
+
*
|
|
8
|
+
* Contributors:
|
|
9
|
+
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const pluginName = 'StatsExtractWebpackPlugin';
|
|
13
|
+
/**
|
|
14
|
+
* Webpack plugin used to store the build stats (results) on build completion.
|
|
15
|
+
* Result may be obtained using 'statsExtractWebpackPlugin.stats'.
|
|
16
|
+
*/
|
|
17
|
+
module.exports = class StatsExtractWebpackPlugin {
|
|
18
|
+
apply(compiler) {
|
|
19
|
+
compiler.hooks.done.tap(pluginName, stats => {
|
|
20
|
+
this.stats = stats;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
};
|
package/scripts/constants.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* All rights reserved. This program and the accompanying materials
|
|
4
4
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
5
|
* which accompanies this distribution, and is available at
|
|
6
|
-
*
|
|
6
|
+
* https://www.eclipse.org/legal/epl-v10.html
|
|
7
7
|
*
|
|
8
8
|
* Contributors:
|
|
9
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
|
+
const contentHashSuffix = '-[contenthash]';
|
|
15
|
+
|
|
14
16
|
const mode = {
|
|
15
17
|
production: 'production',
|
|
16
18
|
development: 'development'
|
|
@@ -37,31 +39,46 @@ const cssFilename = {
|
|
|
37
39
|
development: '[name].css'
|
|
38
40
|
};
|
|
39
41
|
|
|
42
|
+
function isMavenModule() {
|
|
43
|
+
const workingDir = process.cwd();
|
|
44
|
+
return fs.existsSync(path.resolve(workingDir, 'src', 'main')) || fs.existsSync(path.resolve(workingDir, 'src', 'test'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getConstantsForMode(buildMode) {
|
|
48
|
+
if (buildMode !== mode.production) {
|
|
49
|
+
return {
|
|
50
|
+
devMode: true,
|
|
51
|
+
jsFilename: jsFilename.development,
|
|
52
|
+
cssFilename: cssFilename.development,
|
|
53
|
+
outSubDir: outSubDir.development
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
devMode: false,
|
|
58
|
+
jsFilename: jsFilename.production,
|
|
59
|
+
cssFilename: cssFilename.production,
|
|
60
|
+
outSubDir: outSubDir.production
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getOutputDir(mode) {
|
|
65
|
+
const outSubDir = getConstantsForMode(mode).outSubDir;
|
|
66
|
+
const isMavenModule = this.isMavenModule();
|
|
67
|
+
if (isMavenModule) {
|
|
68
|
+
return path.resolve(this.outDir.target, this.outDir.dist, outSubDir);
|
|
69
|
+
}
|
|
70
|
+
return path.resolve(this.outDir.dist);
|
|
71
|
+
}
|
|
72
|
+
|
|
40
73
|
module.exports = {
|
|
74
|
+
contentHashSuffix: contentHashSuffix,
|
|
41
75
|
mode: mode,
|
|
42
76
|
outDir: outDir,
|
|
43
77
|
outSubDir: outSubDir,
|
|
44
78
|
fileListName: 'file-list',
|
|
45
79
|
jsFilename: jsFilename,
|
|
46
80
|
cssFilename: cssFilename,
|
|
47
|
-
isMavenModule:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
getConstantsForMode: buildMode => {
|
|
52
|
-
if (buildMode !== mode.production) {
|
|
53
|
-
return {
|
|
54
|
-
devMode: true,
|
|
55
|
-
jsFilename: jsFilename.development,
|
|
56
|
-
cssFilename: cssFilename.development,
|
|
57
|
-
outSubDir: outSubDir.development
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
return {
|
|
61
|
-
devMode: false,
|
|
62
|
-
jsFilename: jsFilename.production,
|
|
63
|
-
cssFilename: cssFilename.production,
|
|
64
|
-
outSubDir: outSubDir.production
|
|
65
|
-
};
|
|
66
|
-
}
|
|
81
|
+
isMavenModule: isMavenModule,
|
|
82
|
+
getConstantsForMode: getConstantsForMode,
|
|
83
|
+
getOutputDir: getOutputDir
|
|
67
84
|
};
|
package/scripts/files.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010-2021 BSI Business Systems Integration AG.
|
|
3
|
+
* All rights reserved. This program and the accompanying materials
|
|
4
|
+
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
|
+
* which accompanies this distribution, and is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-v10.html
|
|
7
|
+
*
|
|
8
|
+
* Contributors:
|
|
9
|
+
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
|
+
*/
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const getAllFiles = dir => {
|
|
15
|
+
if (!fs.existsSync(dir)) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return fs.readdirSync(dir).reduce((files, file) => {
|
|
20
|
+
const filePath = path.join(dir, file);
|
|
21
|
+
if (!fs.existsSync(filePath)) {
|
|
22
|
+
return files;
|
|
23
|
+
}
|
|
24
|
+
return isDirectory(filePath) ? [...files, ...getAllFiles(filePath)] : [...files, filePath];
|
|
25
|
+
}, []);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function isDirectory(filePath) {
|
|
29
|
+
return fs.statSync(filePath).isDirectory();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const cleanFolder = dir => {
|
|
33
|
+
if (!fs.existsSync(dir)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const files = fs.readdirSync(dir);
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
try {
|
|
40
|
+
let filePath = path.join(dir, file);
|
|
41
|
+
if (isDirectory(filePath)) {
|
|
42
|
+
fs.rmdirSync(filePath, {recursive: true});
|
|
43
|
+
} else {
|
|
44
|
+
file.unlink(path.resolve(dir, file));
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.log(`${dir}/${file} could not be removed`, err);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const deleteFolder = dir => {
|
|
53
|
+
if (!fs.existsSync(dir)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
fs.rmdirSync(dir, {recursive: true});
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.log(`${dir} could not be deleted`, err);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
module.exports.listFiles = getAllFiles;
|
|
65
|
+
module.exports.cleanFolder = cleanFolder;
|
|
66
|
+
module.exports.deleteFolder = deleteFolder;
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
* All rights reserved. This program and the accompanying materials
|
|
4
4
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
5
|
* which accompanies this distribution, and is available at
|
|
6
|
-
*
|
|
6
|
+
* https://www.eclipse.org/legal/epl-v10.html
|
|
7
7
|
*
|
|
8
8
|
* Contributors:
|
|
9
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
10
|
*/
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
|
-
|
|
14
13
|
const jquery = require.resolve('jquery');
|
|
15
|
-
const webpack = require('webpack');
|
|
16
|
-
|
|
17
14
|
const scoutBuildConstants = require('./constants');
|
|
15
|
+
const {SourceMapDevToolPlugin} = require('webpack');
|
|
16
|
+
const StatsExtractWebpackPlugin = require('./StatsExtractWebpackPlugin');
|
|
18
17
|
|
|
19
18
|
module.exports = (config, specEntryPoint) => {
|
|
20
19
|
const webpackConfigFilePath = path.resolve('webpack.config.js');
|
|
@@ -25,32 +24,56 @@ module.exports = (config, specEntryPoint) => {
|
|
|
25
24
|
}
|
|
26
25
|
let webpackConfigProvider = require(webpackConfigFilePath);
|
|
27
26
|
|
|
28
|
-
const webpackArgs = Object.assign({
|
|
29
|
-
|
|
27
|
+
const webpackArgs = Object.assign({
|
|
28
|
+
mode: scoutBuildConstants.mode.development,
|
|
29
|
+
watch: true, // by default tests are running in watch mode
|
|
30
|
+
tsOptions: {
|
|
31
|
+
compilerOptions: {
|
|
32
|
+
// No need to create declarations for tests
|
|
33
|
+
declaration: false,
|
|
34
|
+
declarationMap: false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}, config.webpackArgs);
|
|
38
|
+
let webpackConfig = webpackConfigProvider(null, webpackArgs);
|
|
39
|
+
if (Array.isArray(webpackConfig)) {
|
|
40
|
+
webpackConfig = webpackConfig[0];
|
|
41
|
+
}
|
|
30
42
|
delete webpackConfig.entry;
|
|
31
43
|
if (webpackConfig.optimization) {
|
|
32
44
|
delete webpackConfig.optimization.splitChunks; // disable splitting for tests
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
if (webpackConfig.output) {
|
|
36
|
-
//
|
|
48
|
+
// Remove output file as Karma uses an in-memory middleware and complains if an output file is present
|
|
37
49
|
delete webpackConfig.output.filename;
|
|
50
|
+
// Don't create a library, it would create an error during test run (module not found)
|
|
51
|
+
delete webpackConfig.output.library;
|
|
38
52
|
}
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
if (webpackConfig.externals) {
|
|
55
|
+
// Remove externals, so they don't have to be provided
|
|
56
|
+
// Add jquery as the only external, so it won't be loaded twice because it is provided by @metahub/karma-jasmine-jquery
|
|
57
|
+
webpackConfig.externals = {
|
|
58
|
+
'jquery': 'global jQuery'
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// specify output directory for webpack (use different from normal output dir so that they are not polluted with test artifacts)
|
|
41
63
|
webpackConfig.output = webpackConfig.output || {};
|
|
42
64
|
webpackConfig.output.path = path.resolve(scoutBuildConstants.outDir.target, scoutBuildConstants.outDir.distKarma, scoutBuildConstants.outSubDir.development);
|
|
43
65
|
fs.mkdirSync(webpackConfig.output.path, {recursive: true});
|
|
44
66
|
|
|
45
|
-
webpackConfig.watch =
|
|
67
|
+
webpackConfig.watch = !!webpackArgs.watch;
|
|
46
68
|
|
|
47
|
-
const sourceMapPlugin = webpackConfig.plugins.find(plugin => plugin instanceof
|
|
69
|
+
const sourceMapPlugin = webpackConfig.plugins.find(plugin => plugin instanceof SourceMapDevToolPlugin);
|
|
48
70
|
if (sourceMapPlugin) {
|
|
49
71
|
// Use inline source maps because external source maps are not supported by karma (https://github.com/webpack-contrib/karma-webpack/issues/224)
|
|
50
72
|
delete sourceMapPlugin.sourceMapFilename;
|
|
51
73
|
}
|
|
74
|
+
webpackConfig.plugins.push(new StatsExtractWebpackPlugin()); // used by scout-scripts to access the webpack build result.
|
|
52
75
|
|
|
53
|
-
const specIndex =
|
|
76
|
+
const specIndex = searchSpecEntryPoint(specEntryPoint);
|
|
54
77
|
const preprocessorObj = {};
|
|
55
78
|
preprocessorObj[specIndex] = ['webpack'];
|
|
56
79
|
|
|
@@ -96,3 +119,14 @@ module.exports = (config, specEntryPoint) => {
|
|
|
96
119
|
}
|
|
97
120
|
});
|
|
98
121
|
};
|
|
122
|
+
|
|
123
|
+
function searchSpecEntryPoint(specEntryPoint) {
|
|
124
|
+
if (specEntryPoint) {
|
|
125
|
+
return path.resolve(specEntryPoint);
|
|
126
|
+
}
|
|
127
|
+
let defaultTypescriptIndex = path.resolve('test', 'test-index.ts');
|
|
128
|
+
if (fs.existsSync(defaultTypescriptIndex)) {
|
|
129
|
+
return defaultTypescriptIndex;
|
|
130
|
+
}
|
|
131
|
+
return path.resolve('test', 'test-index.js');
|
|
132
|
+
}
|
package/scripts/post-build.js
CHANGED
|
@@ -12,30 +12,40 @@
|
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const themeJsOutFilter = f => /.*theme.*\.js/.test(f);
|
|
15
|
-
const listFiles = require('./
|
|
15
|
+
const {listFiles} = require('./files');
|
|
16
|
+
const scoutBuild = require('./constants');
|
|
16
17
|
|
|
17
18
|
function deleteFile(filename) {
|
|
18
|
-
fs.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
if (!fs.existsSync(filename)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
fs.accessSync(filename, fs.constants.W_OK);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(`No right to delete ${filename}.`, err);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
fs.unlink(filename, unlinkErr => {
|
|
29
|
+
if (unlinkErr) {
|
|
30
|
+
throw unlinkErr;
|
|
27
31
|
}
|
|
28
32
|
});
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
function fileListFilter(fileName) {
|
|
36
|
+
return fileName !== scoutBuild.fileListName
|
|
37
|
+
&& !fileName.endsWith('.LICENSE')
|
|
38
|
+
&& !themeJsOutFilter(fileName)
|
|
39
|
+
&& !fileName.endsWith('d.ts')
|
|
40
|
+
&& !fileName.endsWith('d.ts.map');
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
module.exports = {
|
|
32
44
|
createFileList: dir => {
|
|
33
45
|
const scoutBuild = require('./constants');
|
|
34
46
|
let content = '';
|
|
35
47
|
listFiles(dir)
|
|
36
|
-
.filter(fileName => fileName
|
|
37
|
-
.filter(fileName => !fileName.endsWith('.LICENSE'))
|
|
38
|
-
.filter(fileName => !themeJsOutFilter(fileName))
|
|
48
|
+
.filter(fileName => fileListFilter(fileName))
|
|
39
49
|
.map(file => file.substring(dir.length + 1))
|
|
40
50
|
.map(path => path.replace(/\\/g, '/'))
|
|
41
51
|
.map(fileName => `${fileName}\n`)
|
|
@@ -55,6 +65,5 @@ module.exports = {
|
|
|
55
65
|
listFiles(dir)
|
|
56
66
|
.filter(themeJsOutFilter)
|
|
57
67
|
.forEach(f => deleteFile(f));
|
|
58
|
-
|
|
59
68
|
}
|
|
60
69
|
};
|
|
@@ -8,27 +8,31 @@
|
|
|
8
8
|
* Contributors:
|
|
9
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
10
|
*/
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const scoutBuildConstants = require('./constants');
|
|
11
14
|
const CopyPlugin = require('copy-webpack-plugin');
|
|
12
15
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
13
16
|
const AfterEmitWebpackPlugin = require('./AfterEmitWebpackPlugin');
|
|
14
|
-
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const scoutBuildConstants = require('./constants');
|
|
17
|
-
const webpack = require('webpack');
|
|
17
|
+
const {SourceMapDevToolPlugin, WatchIgnorePlugin, ProgressPlugin} = require('webpack');
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {string} args.mode development or production
|
|
21
|
-
* @param {boolean} args.clean true, to clean the dist folder before each build. Default is
|
|
21
|
+
* @param {boolean} args.clean true, to clean the dist folder before each build. Default is false.
|
|
22
22
|
* @param {boolean} args.progress true, to show build progress in percentage. Default is true.
|
|
23
23
|
* @param {boolean} args.profile true, to show timing information for each build step. Default is false.
|
|
24
|
+
* @param {boolean} args.watch true, if webpack runs in watch mode. Default is false.
|
|
24
25
|
* @param {[]} args.resDirArray an array containing directories which should be copied to dist/res
|
|
26
|
+
* @param {object} args.tsOptions a config object to be passed to the ts-loader
|
|
25
27
|
*/
|
|
26
28
|
module.exports = (env, args) => {
|
|
27
|
-
const
|
|
29
|
+
const buildMode = args.mode;
|
|
30
|
+
const {devMode, cssFilename, jsFilename} = scoutBuildConstants.getConstantsForMode(buildMode);
|
|
28
31
|
const isMavenModule = scoutBuildConstants.isMavenModule();
|
|
29
|
-
const
|
|
32
|
+
const isWatchMode = nvl(args.watch, false);
|
|
33
|
+
const outDir = scoutBuildConstants.getOutputDir(buildMode);
|
|
30
34
|
const resDirArray = args.resDirArray || ['res'];
|
|
31
|
-
console.log(`Webpack mode: ${
|
|
35
|
+
console.log(`Webpack mode: ${buildMode}`);
|
|
32
36
|
|
|
33
37
|
// # Copy static web-resources delivered by the modules
|
|
34
38
|
const copyPluginConfig = [];
|
|
@@ -41,17 +45,39 @@ module.exports = (env, args) => {
|
|
|
41
45
|
});
|
|
42
46
|
}
|
|
43
47
|
|
|
48
|
+
const minimizerTarget = ['firefox69', 'chrome71', 'safari12.1'];
|
|
49
|
+
const babelOptions = {
|
|
50
|
+
compact: false,
|
|
51
|
+
cacheDirectory: true,
|
|
52
|
+
cacheCompression: false,
|
|
53
|
+
presets: [
|
|
54
|
+
[require.resolve('@babel/preset-env'), {
|
|
55
|
+
debug: false,
|
|
56
|
+
targets: {
|
|
57
|
+
firefox: '69',
|
|
58
|
+
chrome: '71',
|
|
59
|
+
safari: '12.1'
|
|
60
|
+
}
|
|
61
|
+
}]
|
|
62
|
+
]
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// in prod mode always only transpile (no type-checks). In dev mode type checking is skipped in watch mode. Instead, ForkTsCheckerWebpackPlugin is used then (see below).
|
|
66
|
+
const transpileOnly = !devMode || isWatchMode;
|
|
67
|
+
const tsOptions = {
|
|
68
|
+
...args.tsOptions,
|
|
69
|
+
transpileOnly: transpileOnly,
|
|
70
|
+
compilerOptions: {
|
|
71
|
+
noEmit: false,
|
|
72
|
+
...args.tsOptions?.compilerOptions
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
44
76
|
const config = {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Other source map types may increase build performance but decrease debugging experience
|
|
49
|
-
// (e.g. wrong this in arrow functions with inline-cheap-module-source-map or not having original source code at all (code after babel transpilation instead of before) with eval types).
|
|
50
|
-
// In production mode create external source maps without source code to map stack traces.
|
|
51
|
-
// Otherwise stack traces would point to the minified source code which makes it quite impossible to analyze productive issues.
|
|
52
|
-
devtool: devMode ? false : 'nosources-source-map',
|
|
77
|
+
mode: buildMode,
|
|
78
|
+
devtool: false, // disabled because SourceMapDevToolPlugin is used (see below)
|
|
79
|
+
ignoreWarnings: [(webpackError, compilation) => isWarningIgnored(devMode, webpackError, compilation)],
|
|
53
80
|
resolve: {
|
|
54
|
-
|
|
55
81
|
// no automatic polyfills. clients must add the desired polyfills themselves.
|
|
56
82
|
fallback: {
|
|
57
83
|
assert: false,
|
|
@@ -77,7 +103,8 @@ module.exports = (env, args) => {
|
|
|
77
103
|
util: false,
|
|
78
104
|
vm: false,
|
|
79
105
|
zlib: false
|
|
80
|
-
}
|
|
106
|
+
},
|
|
107
|
+
extensions: ['.ts', '.js', '.json', '.wasm', '.tsx', '.jsx']
|
|
81
108
|
},
|
|
82
109
|
// expect these apis in the browser
|
|
83
110
|
externals: {
|
|
@@ -92,16 +119,15 @@ module.exports = (env, args) => {
|
|
|
92
119
|
output: {
|
|
93
120
|
filename: jsFilename,
|
|
94
121
|
path: outDir,
|
|
95
|
-
|
|
96
|
-
clean: nvl(args.clean, true)
|
|
122
|
+
clean: nvl(args.clean, false)
|
|
97
123
|
},
|
|
98
124
|
performance: {
|
|
99
125
|
hints: false
|
|
100
126
|
},
|
|
101
127
|
profile: args.profile,
|
|
102
128
|
module: {
|
|
103
|
-
// LESS
|
|
104
129
|
rules: [{
|
|
130
|
+
// LESS
|
|
105
131
|
test: /\.less$/,
|
|
106
132
|
use: [{
|
|
107
133
|
// Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS.
|
|
@@ -136,50 +162,48 @@ module.exports = (env, args) => {
|
|
|
136
162
|
}
|
|
137
163
|
}]
|
|
138
164
|
}, {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
use: {
|
|
165
|
+
test: /\.tsx?$/,
|
|
166
|
+
exclude: /node_modules/,
|
|
167
|
+
use: [{
|
|
143
168
|
loader: require.resolve('babel-loader'),
|
|
144
|
-
options:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
require.resolve('@babel/plugin-transform-object-assign'),
|
|
150
|
-
require.resolve('@babel/plugin-proposal-class-properties')],
|
|
151
|
-
presets: [
|
|
152
|
-
[require.resolve('@babel/preset-env'), {
|
|
153
|
-
debug: false,
|
|
154
|
-
targets: {
|
|
155
|
-
firefox: '69',
|
|
156
|
-
chrome: '71',
|
|
157
|
-
safari: '12.1'
|
|
158
|
-
}
|
|
159
|
-
}]
|
|
160
|
-
]
|
|
161
|
-
}
|
|
162
|
-
}
|
|
169
|
+
options: babelOptions
|
|
170
|
+
}, {
|
|
171
|
+
loader: require.resolve('ts-loader'),
|
|
172
|
+
options: tsOptions
|
|
173
|
+
}]
|
|
163
174
|
}, {
|
|
164
|
-
|
|
165
|
-
test: /\.css$/i,
|
|
175
|
+
test: /\.jsx?$/,
|
|
166
176
|
use: [{
|
|
167
|
-
loader: require.resolve('
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
177
|
+
loader: require.resolve('babel-loader'),
|
|
178
|
+
options: babelOptions
|
|
179
|
+
}]
|
|
180
|
+
}, {
|
|
181
|
+
test: /\.jsx?$/,
|
|
182
|
+
enforce: 'pre',
|
|
183
|
+
use: [{
|
|
184
|
+
loader: require.resolve('source-map-loader')
|
|
175
185
|
}]
|
|
176
186
|
}]
|
|
177
187
|
},
|
|
178
188
|
plugins: [
|
|
189
|
+
new WatchIgnorePlugin({paths: [/\.d\.ts$/]}),
|
|
179
190
|
// see: extracts css into separate files
|
|
180
191
|
new MiniCssExtractPlugin({filename: cssFilename}),
|
|
181
192
|
// run post-build script hook
|
|
182
|
-
new AfterEmitWebpackPlugin({outDir: outDir})
|
|
193
|
+
new AfterEmitWebpackPlugin({outDir: outDir}),
|
|
194
|
+
new SourceMapDevToolPlugin({
|
|
195
|
+
// Use external source maps in all modes because the browser is very slow in displaying a file containing large lines which is the case if source maps are inlined
|
|
196
|
+
filename: '[file].map',
|
|
197
|
+
|
|
198
|
+
// Don't create maps for static resources.
|
|
199
|
+
// They may already have maps which could lead to "multiple assets emit different content to the same file" exception.
|
|
200
|
+
exclude: /\/res\/.*/,
|
|
201
|
+
|
|
202
|
+
// In production mode create external source maps without source code to map stack traces.
|
|
203
|
+
// Otherwise, stack traces would point to the minified source code which makes it quite impossible to analyze productive issues.
|
|
204
|
+
noSources: !devMode,
|
|
205
|
+
moduleFilenameTemplate: devMode ? undefined : prodDevtoolModuleFilenameTemplate
|
|
206
|
+
})
|
|
183
207
|
],
|
|
184
208
|
optimization: {
|
|
185
209
|
splitChunks: {
|
|
@@ -189,49 +213,181 @@ module.exports = (env, args) => {
|
|
|
189
213
|
}
|
|
190
214
|
};
|
|
191
215
|
|
|
192
|
-
//
|
|
216
|
+
// Copy resources only add the plugin if there are resources to copy. Otherwise, the plugin fails.
|
|
193
217
|
if (copyPluginConfig.length > 0) {
|
|
194
|
-
// only add the plugin if there are resources to copy. Otherwise the plugin fails.
|
|
195
218
|
config.plugins.push(new CopyPlugin({patterns: copyPluginConfig}));
|
|
196
219
|
}
|
|
197
220
|
|
|
221
|
+
// Shows progress information in the console in dev mode
|
|
198
222
|
if (nvl(args.progress, true)) {
|
|
199
|
-
|
|
200
|
-
const webpack = require('webpack');
|
|
201
|
-
config.plugins.push(new webpack.ProgressPlugin({profile: args.profile}));
|
|
223
|
+
config.plugins.push(new ProgressPlugin({profile: args.profile}));
|
|
202
224
|
}
|
|
203
225
|
|
|
204
|
-
if (
|
|
226
|
+
if (devMode) {
|
|
227
|
+
if (transpileOnly) { // devMode and no type-checks: perform checks asynchronously (watch mode).
|
|
228
|
+
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
|
229
|
+
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');
|
|
230
|
+
|
|
231
|
+
let forkTsCheckerConfig = undefined;
|
|
232
|
+
if (!fs.existsSync('./tsconfig.json')) {
|
|
233
|
+
// if the module has no tsconfig: use default from Scout.
|
|
234
|
+
// Otherwise, each module would need to provide a tsconfig even if there is no typescript code in the module.
|
|
235
|
+
forkTsCheckerConfig = {
|
|
236
|
+
typescript: {
|
|
237
|
+
configFile: require.resolve('@eclipse-scout/tsconfig'),
|
|
238
|
+
context: process.cwd(),
|
|
239
|
+
configOverwrite: {
|
|
240
|
+
compilerOptions: {skipLibCheck: true, sourceMap: false, inlineSourceMap: false, declarationMap: false, allowJs: true},
|
|
241
|
+
include: isMavenModule ? ['./src/main/js/**/*.ts', './src/main/js/**/*.js', './src/test/js/**/*.ts', './src/test/js/**/*.js']
|
|
242
|
+
: ['./src/**/*.ts', './src/**/*.js', './test/**/*.ts', './test/**/*.js']
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
config.plugins.push(new ForkTsCheckerWebpackPlugin(forkTsCheckerConfig));
|
|
248
|
+
config.plugins.push(new ForkTsCheckerNotifierWebpackPlugin({
|
|
249
|
+
title: getModuleName(),
|
|
250
|
+
skipSuccessful: true, // no notification for successful builds
|
|
251
|
+
excludeWarnings: true // no notification for warnings
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
205
255
|
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
206
256
|
const TerserPlugin = require('terser-webpack-plugin');
|
|
207
257
|
config.optimization.minimizer = [
|
|
208
258
|
// minify css
|
|
209
259
|
new CssMinimizerPlugin({
|
|
210
|
-
test: /\.min\.css$/
|
|
260
|
+
test: /\.min\.css$/i, // only minimize required files
|
|
261
|
+
exclude: /res[\\/]/i, // exclude resources output directory from minimizing as these files are copied
|
|
262
|
+
parallel: 4, // best ratio between memory consumption and performance on most systems
|
|
263
|
+
minify: CssMinimizerPlugin.esbuildMinify,
|
|
211
264
|
minimizerOptions: {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
265
|
+
logLevel: 'error', // show messages directly to see the details. The message passed to webpack is only an object which is ignored in isWarningIgnored
|
|
266
|
+
sourcemap: false, // no sourcemaps for css in prod build (needs more heap memory instead)
|
|
267
|
+
charset: 'utf8', // default is ASCII which requires more escaping. UTF-8 allows for more compact code.
|
|
268
|
+
target: minimizerTarget
|
|
215
269
|
}
|
|
216
270
|
}),
|
|
217
271
|
// minify js
|
|
218
272
|
new TerserPlugin({
|
|
219
|
-
test: /\.js
|
|
220
|
-
|
|
273
|
+
test: /\.min\.js$/i, // only minimize required files
|
|
274
|
+
exclude: [/log4javascript-1\.4\.9[\\/]/i, /res[\\/]/i], // exclude resources output directory from minimizing as these files are copied
|
|
275
|
+
parallel: 4, // best ratio between memory consumption and performance on most systems
|
|
276
|
+
minify: TerserPlugin.esbuildMinify,
|
|
277
|
+
terserOptions: {
|
|
278
|
+
legalComments: 'none',
|
|
279
|
+
logLevel: 'error', // show messages directly to see the details. The message passed to webpack is only an object which is ignored in isWarningIgnored
|
|
280
|
+
charset: 'utf8', // default is ASCII which requires more escaping. UTF-8 allows for more compact code.
|
|
281
|
+
target: minimizerTarget
|
|
282
|
+
}
|
|
221
283
|
})
|
|
222
284
|
];
|
|
223
285
|
}
|
|
224
286
|
|
|
225
|
-
if (devMode) {
|
|
226
|
-
// Use external source maps also in dev mode because the browser is very slow in displaying a file containing large lines which is the case if source maps are inlined
|
|
227
|
-
config.plugins.push(new webpack.SourceMapDevToolPlugin({
|
|
228
|
-
filename: '[file].map'
|
|
229
|
-
}));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
287
|
return config;
|
|
233
288
|
};
|
|
234
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Creates a new object that contains the same keys as the given object. The values are replaced with the keys.
|
|
292
|
+
* So the resulting object looks like: {key1: key1, key2: key2}.
|
|
293
|
+
*/
|
|
294
|
+
function toExternals(src, dest) {
|
|
295
|
+
if (!src) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
return Object.keys(src).reduce((obj, current) => {
|
|
299
|
+
obj[current] = current;
|
|
300
|
+
return obj;
|
|
301
|
+
}, dest);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Converts the given base config to a library config meaning that all dependencies declared in the package.json are externalized by default.
|
|
306
|
+
*
|
|
307
|
+
* @param {object} config base config to convert to a library config
|
|
308
|
+
* @param {object} [options]
|
|
309
|
+
* @param {object} [options.externals] object holding custom externals for the module. See https://webpack.js.org/configuration/externals/ for details about supported formats and types.
|
|
310
|
+
* @param {boolean} [options.externalizeDevDeps] Add devDependencies as externals. Default is true.
|
|
311
|
+
* @param {boolean} [options.externalizePeerDeps] Add peerDependencies as externals. Default is true.
|
|
312
|
+
* @param {boolean} [options.externalizeBundledDeps] Add bundledDependencies as externals. Default is true.
|
|
313
|
+
* @param {boolean} [options.externalizeOptionalDeps] Add optionalDependencies as externals. Default is true.
|
|
314
|
+
*/
|
|
315
|
+
function libraryConfig(config, options = {}) {
|
|
316
|
+
const packageJson = require(path.resolve('./package.json'));
|
|
317
|
+
const packageJsonExternals = {};
|
|
318
|
+
toExternals(packageJson.dependencies, packageJsonExternals);
|
|
319
|
+
if (options.externalizeDevDeps ?? true) {
|
|
320
|
+
toExternals(packageJson.devDependencies, packageJsonExternals);
|
|
321
|
+
}
|
|
322
|
+
if (options.externalizePeerDeps ?? true) {
|
|
323
|
+
toExternals(packageJson.peerDependencies, packageJsonExternals);
|
|
324
|
+
}
|
|
325
|
+
if (options.externalizeBundledDeps ?? true) {
|
|
326
|
+
toExternals(packageJson.bundledDependencies, packageJsonExternals);
|
|
327
|
+
}
|
|
328
|
+
if (options.externalizeOptionalDeps ?? true) {
|
|
329
|
+
toExternals(packageJson.optionalDependencies, packageJsonExternals);
|
|
330
|
+
}
|
|
331
|
+
packageJsonExternals.jquery = 'commonjs jquery'; // Make synthetic default import work (import $ from 'jquery') by importing jquery as commonjs module
|
|
332
|
+
const customExternals = options.externals || {};
|
|
333
|
+
const allExternals = {...packageJsonExternals, ...config.externals, ...customExternals};
|
|
334
|
+
|
|
335
|
+
// FileList is not necessary in library mode
|
|
336
|
+
let plugins = config.plugins.map(plugin => {
|
|
337
|
+
if (plugin instanceof AfterEmitWebpackPlugin) {
|
|
338
|
+
return new AfterEmitWebpackPlugin({outDir: plugin.options.outDir, createFileList: false});
|
|
339
|
+
}
|
|
340
|
+
return plugin;
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
...config,
|
|
345
|
+
optimization: {
|
|
346
|
+
...config.optimization,
|
|
347
|
+
splitChunks: undefined // disable splitting
|
|
348
|
+
},
|
|
349
|
+
output: {
|
|
350
|
+
...config.output,
|
|
351
|
+
library: {
|
|
352
|
+
type: 'module'
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
experiments: {
|
|
356
|
+
// required for library.type = 'module'
|
|
357
|
+
outputModule: true
|
|
358
|
+
},
|
|
359
|
+
plugins,
|
|
360
|
+
externals: (context, callback) => markExternals(allExternals, context, callback)
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function markExternals(allExternals, context, callback) {
|
|
365
|
+
const request = context.request;
|
|
366
|
+
if (request.startsWith('.')) {
|
|
367
|
+
// fast check: continue without externalizing the import for relative paths
|
|
368
|
+
return callback();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (allExternals[request]) {
|
|
372
|
+
// import matches exactly a declared dependency
|
|
373
|
+
return callback(null, allExternals[request]);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// check for files in sub-folders of an external
|
|
377
|
+
for (const [key, value] of Object.entries(allExternals)) {
|
|
378
|
+
if (request.startsWith(key + '/')) {
|
|
379
|
+
let result = request;
|
|
380
|
+
let spacePos = value.indexOf(' ');
|
|
381
|
+
if (spacePos > 0) {
|
|
382
|
+
result = value.substring(0, spacePos + 1) + result;
|
|
383
|
+
}
|
|
384
|
+
return callback(null, result);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
callback(); // Continue without externalizing the import
|
|
389
|
+
}
|
|
390
|
+
|
|
235
391
|
/**
|
|
236
392
|
* @param {object} entry the webpack entry object
|
|
237
393
|
* @param {object} options the options object to configure which themes should be built and how
|
|
@@ -264,13 +420,6 @@ function addThemes(entry, options = {}) {
|
|
|
264
420
|
});
|
|
265
421
|
}
|
|
266
422
|
|
|
267
|
-
function getOutputDir(isMavenModule, outSubDir) {
|
|
268
|
-
if (isMavenModule) {
|
|
269
|
-
return path.resolve(scoutBuildConstants.outDir.target, scoutBuildConstants.outDir.dist, outSubDir);
|
|
270
|
-
}
|
|
271
|
-
return path.resolve(scoutBuildConstants.outDir.dist);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
423
|
function computeChunkName(module, chunks, cacheGroupKey) {
|
|
275
424
|
const entryPointDelim = '~';
|
|
276
425
|
const allChunksNames = chunks
|
|
@@ -296,6 +445,7 @@ function computeChunkName(module, chunks, cacheGroupKey) {
|
|
|
296
445
|
|
|
297
446
|
function computeModuleId(module) {
|
|
298
447
|
const nodeModules = 'node_modules';
|
|
448
|
+
// noinspection JSUnresolvedVariable
|
|
299
449
|
let id = module.userRequest;
|
|
300
450
|
const nodeModulesPos = id.lastIndexOf(nodeModules);
|
|
301
451
|
if (nodeModulesPos < 0) {
|
|
@@ -340,6 +490,17 @@ function nvl(arg, defaultValue) {
|
|
|
340
490
|
return arg;
|
|
341
491
|
}
|
|
342
492
|
|
|
493
|
+
function isWarningIgnored(devMode, webpackError) {
|
|
494
|
+
if (webpackError && webpackError.message === '[object Object]') {
|
|
495
|
+
return true; // esbuild warnings are not correctly passed to webpack. ignore them. The actual message is printed with the esbuild flag 'logLevel' (see below)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (devMode || !webpackError || !webpackError.warning || !webpackError.warning.message) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
return webpackError.warning.message.startsWith('Failed to parse source map');
|
|
502
|
+
}
|
|
503
|
+
|
|
343
504
|
/**
|
|
344
505
|
* Don't reveal absolute file paths in production mode -> only return the file name relative to its module.
|
|
345
506
|
* @param info.resourcePath
|
|
@@ -363,4 +524,38 @@ function prodDevtoolModuleFilenameTemplate(info) {
|
|
|
363
524
|
}
|
|
364
525
|
}
|
|
365
526
|
|
|
527
|
+
function getModuleName() {
|
|
528
|
+
let packageJsonFile = path.resolve('./package.json');
|
|
529
|
+
if (fs.existsSync(packageJsonFile)) {
|
|
530
|
+
let name = require(packageJsonFile).name;
|
|
531
|
+
if (name) {
|
|
532
|
+
return name;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return path.basename(process.cwd());
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Externalize every import to the main index and replace it with newImport
|
|
540
|
+
* Keep imports to the excludedFolder.
|
|
541
|
+
* @param {string} newImport new name of the replaced import, typically the module name
|
|
542
|
+
* @param {string} excludedFolder imports to that folder won't be replaced
|
|
543
|
+
* @return a function that should be added to the webpack externals
|
|
544
|
+
*/
|
|
545
|
+
function rewriteIndexImports(newImport, excludedFolder) {
|
|
546
|
+
return ({context, request, contextInfo}, callback) => {
|
|
547
|
+
// Externalize every import to the main index and replace it with @bsi-scout/datamodel
|
|
548
|
+
// Keep imports to the testing index
|
|
549
|
+
if (/\/index$/.test(request) && !path.resolve(context, request).includes(excludedFolder)) {
|
|
550
|
+
return callback(null, newImport);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Continue without externalizing the import
|
|
554
|
+
callback();
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
|
|
366
558
|
module.exports.addThemes = addThemes;
|
|
559
|
+
module.exports.libraryConfig = libraryConfig;
|
|
560
|
+
module.exports.markExternals = markExternals;
|
|
561
|
+
module.exports.rewriteIndexImports = rewriteIndexImports;
|
package/scripts/list-files.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2010-2021 BSI Business Systems Integration AG.
|
|
3
|
-
* All rights reserved. This program and the accompanying materials
|
|
4
|
-
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
|
-
* which accompanies this distribution, and is available at
|
|
6
|
-
* http://www.eclipse.org/legal/epl-v10.html
|
|
7
|
-
*
|
|
8
|
-
* Contributors:
|
|
9
|
-
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
|
-
*/
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
|
|
14
|
-
const _getAllFiles = dir => {
|
|
15
|
-
if (!fs.existsSync(dir)) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return fs.readdirSync(dir).reduce((files, file) => {
|
|
20
|
-
const name = path.join(dir, file);
|
|
21
|
-
const isDirectory = fs.statSync(name).isDirectory();
|
|
22
|
-
return isDirectory ? [...files, ..._getAllFiles(name)] : [...files, name];
|
|
23
|
-
}, []);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
module.exports = _getAllFiles;
|