@redhat-cloud-services/frontend-components-config 4.5.11 → 4.5.12
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 +3 -0
- package/bin/fec.js +19 -2
- package/index.js +61 -63
- package/package.json +1 -1
- package/src/config.js +183 -177
- package/src/config.test.js +86 -109
- package/src/plugins.js +48 -54
- package/src/plugins.test.js +31 -35
package/README.md
CHANGED
|
@@ -340,6 +340,9 @@ Use binary in your `package.json` scripts section:
|
|
|
340
340
|
}
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
+
## Patch etc hosts
|
|
344
|
+
This is a required step for first time setup. It will allow your localhost to map to [env].foo.redhat.com. This is required to run only once on your machine. **Your OS may require running the script as sudo**!
|
|
345
|
+
|
|
343
346
|
## Static
|
|
344
347
|
|
|
345
348
|
A script that will run webpack build and serve webpack output through `http-serve` server. **This is not supposed to replace webpack dev server!**
|
package/bin/fec.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
const { execSync } = require('child_process');
|
|
3
3
|
const static = require('@redhat-cloud-services/frontend-components-config-utilities/serve-federated');
|
|
4
4
|
const yargs = require('yargs');
|
|
5
5
|
|
|
6
|
+
function patchHosts() {
|
|
7
|
+
const command = `
|
|
8
|
+
for host in prod.foo.redhat.com stage.foo.redhat.com qa.foo.redhat.com ci.foo.redhat.com
|
|
9
|
+
do
|
|
10
|
+
grep -q $host /etc/hosts 2>/dev/null
|
|
11
|
+
if [ $? -ne 0 ]
|
|
12
|
+
then
|
|
13
|
+
echo "Adding $host to /etc/hosts"
|
|
14
|
+
echo "127.0.0.1 $host" >>/etc/hosts
|
|
15
|
+
fi
|
|
16
|
+
done
|
|
17
|
+
`
|
|
18
|
+
execSync(command)
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
const cwd = process.cwd();
|
|
7
22
|
|
|
8
23
|
const argv = yargs
|
|
@@ -19,11 +34,13 @@ const argv = yargs
|
|
|
19
34
|
default: 8003
|
|
20
35
|
});
|
|
21
36
|
})
|
|
37
|
+
.command('patch-etc-hosts', 'You may have to run this as \'sudo\'. Setup your etc/hosts allow development hosts in your browser')
|
|
22
38
|
.help()
|
|
23
39
|
.argv;
|
|
24
40
|
|
|
25
41
|
const scripts = {
|
|
26
|
-
static
|
|
42
|
+
static,
|
|
43
|
+
'patch-etc-hosts': patchHosts
|
|
27
44
|
};
|
|
28
45
|
|
|
29
46
|
const args = [ argv, cwd ];
|
package/index.js
CHANGED
|
@@ -2,81 +2,79 @@ const config = require('./src/config');
|
|
|
2
2
|
const plugins = require('./src/plugins');
|
|
3
3
|
const { sync } = require('glob');
|
|
4
4
|
|
|
5
|
-
const gitRevisionPlugin = new(require('git-revision-webpack-plugin'))({
|
|
6
|
-
|
|
5
|
+
const gitRevisionPlugin = new (require('git-revision-webpack-plugin'))({
|
|
6
|
+
branch: true,
|
|
7
7
|
});
|
|
8
|
-
const betaBranches = [
|
|
9
|
-
const akamaiBranches = [
|
|
8
|
+
const betaBranches = ['master', 'qa-beta', 'ci-beta', 'prod-beta', 'main', 'devel', 'stage-beta'];
|
|
9
|
+
const akamaiBranches = ['prod-beta', 'prod-stable'];
|
|
10
10
|
|
|
11
11
|
const getAppEntry = (rootFolder, isProd) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (entries.length > 0) {
|
|
20
|
-
return `${rootFolder}/${entries[0]}`;
|
|
21
|
-
}
|
|
12
|
+
// Use entry-dev if it exists
|
|
13
|
+
if (!isProd) {
|
|
14
|
+
const entries = sync('src/entry-dev.{js,jsx,ts,tsx}', { cwd: rootFolder });
|
|
15
|
+
if (entries.length > 1) {
|
|
16
|
+
console.warn('Found multiple entry-dev files. Using', entries[0]);
|
|
22
17
|
}
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
console.warn('Found multiple entry files. Using', entries[0]);
|
|
19
|
+
if (entries.length > 0) {
|
|
20
|
+
return `${rootFolder}/${entries[0]}`;
|
|
27
21
|
}
|
|
22
|
+
}
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
const entries = sync('src/entry.{js,jsx,ts,tsx}', { cwd: rootFolder });
|
|
25
|
+
if (entries.length > 1) {
|
|
26
|
+
console.warn('Found multiple entry files. Using', entries[0]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return `${rootFolder}/${entries[0]}`;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
module.exports = (configurations) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
'beta/apps' :
|
|
39
|
-
'apps');
|
|
40
|
-
|
|
41
|
-
const publicPath = `/${appDeployment}/${insights.appname}/`;
|
|
42
|
-
const appEntry = configurations.appEntry || getAppEntry(configurations.rootFolder, isProd);
|
|
43
|
-
const generateSourceMaps = !akamaiBranches.includes(gitBranch);
|
|
33
|
+
configurations.isProd = configurations.isProd || process.env.NODE_ENV === 'production';
|
|
34
|
+
const isProd = configurations.isProd;
|
|
35
|
+
const { insights } = require(`${configurations.rootFolder}/package.json`);
|
|
36
|
+
const gitBranch = process.env.TRAVIS_BRANCH || process.env.BRANCH || gitRevisionPlugin.branch();
|
|
37
|
+
const appDeployment = configurations.deployment || (isProd && betaBranches.includes(gitBranch) ? 'beta/apps' : 'apps');
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.log(`Root folder: ${configurations.rootFolder}`);
|
|
49
|
-
console.log(`Current branch: ${gitBranch}`);
|
|
50
|
-
!generateSourceMaps && console.log(`Source map generation for "${gitBranch}" deployment has been disabled.`);
|
|
51
|
-
console.log(`Beta branches: ${betaBranches}`);
|
|
52
|
-
console.log(`Using deployments: ${appDeployment}`);
|
|
53
|
-
console.log(`Public path: ${publicPath}`);
|
|
54
|
-
console.log(`App entry: ${appEntry}`);
|
|
55
|
-
console.log(`Use proxy: ${configurations.useProxy ? 'true' : 'false'}`);
|
|
56
|
-
if (!(configurations.useProxy || configurations.standalone)) {
|
|
57
|
-
console.warn('Insights-proxy is deprecated in favor of "useProxy" or "standalone".');
|
|
58
|
-
console.warn('See https://github.com/RedHatInsights/frontend-components/blob/master/packages/config/README.md');
|
|
59
|
-
}
|
|
39
|
+
const publicPath = `/${appDeployment}/${insights.appname}/`;
|
|
40
|
+
const appEntry = configurations.appEntry || getAppEntry(configurations.rootFolder, isProd);
|
|
41
|
+
const generateSourceMaps = !akamaiBranches.includes(gitBranch);
|
|
60
42
|
|
|
61
|
-
|
|
62
|
-
|
|
43
|
+
if (configurations.debug) {
|
|
44
|
+
/* eslint-disable no-console */
|
|
45
|
+
console.log('~~~Using variables~~~');
|
|
46
|
+
console.log(`Root folder: ${configurations.rootFolder}`);
|
|
47
|
+
console.log(`Current branch: ${gitBranch}`);
|
|
48
|
+
!generateSourceMaps && console.log(`Source map generation for "${gitBranch}" deployment has been disabled.`);
|
|
49
|
+
console.log(`Beta branches: ${betaBranches}`);
|
|
50
|
+
console.log(`Using deployments: ${appDeployment}`);
|
|
51
|
+
console.log(`Public path: ${publicPath}`);
|
|
52
|
+
console.log(`App entry: ${appEntry}`);
|
|
53
|
+
console.log(`Use proxy: ${configurations.useProxy ? 'true' : 'false'}`);
|
|
54
|
+
if (!(configurations.useProxy || configurations.standalone)) {
|
|
55
|
+
console.warn('Insights-proxy is deprecated in favor of "useProxy" or "standalone".');
|
|
56
|
+
console.warn('See https://github.com/RedHatInsights/frontend-components/blob/master/packages/config/README.md');
|
|
63
57
|
}
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
59
|
+
console.log('~~~~~~~~~~~~~~~~~~~~~');
|
|
60
|
+
/* eslint-enable no-console */
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
config: config({
|
|
65
|
+
...configurations,
|
|
66
|
+
appDeployment,
|
|
67
|
+
insights,
|
|
68
|
+
publicPath,
|
|
69
|
+
appEntry,
|
|
70
|
+
appName: insights.appname,
|
|
71
|
+
}),
|
|
72
|
+
plugins: plugins({
|
|
73
|
+
...configurations,
|
|
74
|
+
generateSourceMaps,
|
|
75
|
+
appDeployment,
|
|
76
|
+
insights,
|
|
77
|
+
publicPath,
|
|
78
|
+
}),
|
|
79
|
+
};
|
|
82
80
|
};
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -6,192 +6,198 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
|
6
6
|
const searchIgnoredStyles = require('@redhat-cloud-services/frontend-components-config-utilities/search-ignored-styles');
|
|
7
7
|
|
|
8
8
|
module.exports = ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
9
|
+
port,
|
|
10
|
+
publicPath,
|
|
11
|
+
appEntry,
|
|
12
|
+
rootFolder,
|
|
13
|
+
https,
|
|
14
|
+
mode,
|
|
15
|
+
appName,
|
|
16
|
+
useFileHash = true,
|
|
17
|
+
betaEnv,
|
|
18
|
+
env,
|
|
19
|
+
sassPrefix,
|
|
20
|
+
skipChrome2 = false,
|
|
21
|
+
useProxy,
|
|
22
|
+
proxyURL,
|
|
23
|
+
localChrome,
|
|
24
|
+
keycloakUri,
|
|
25
|
+
customProxy,
|
|
26
|
+
routes,
|
|
27
|
+
routesPath,
|
|
28
|
+
isProd,
|
|
29
|
+
standalone = false,
|
|
30
|
+
reposDir,
|
|
31
|
+
appUrl = [],
|
|
32
|
+
proxyVerbose,
|
|
33
|
+
useCloud,
|
|
34
|
+
target,
|
|
35
|
+
registry,
|
|
36
|
+
client = {},
|
|
37
|
+
bundlePfModules = false,
|
|
38
|
+
useChromeTemplate = false,
|
|
39
39
|
} = {}) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const filenameMask = `js/[name]${useFileHash ? `.${Date.now()}.[fullhash]` : ''}.js`;
|
|
41
|
+
if (betaEnv) {
|
|
42
|
+
env = `${betaEnv}-beta`;
|
|
43
|
+
console.warn('betaEnv is deprecated in favor of env');
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
const outputPath = `${rootFolder || ''}/dist`;
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const copyTemplate = (chromePath) => {
|
|
49
|
+
const template = fs.readFileSync(`${chromePath}/index.html`, { encoding: 'utf-8' });
|
|
50
|
+
if (!fs.existsSync(outputPath)) {
|
|
51
|
+
fs.mkdirSync(outputPath);
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
fs.writeFileSync(`${outputPath}/index.html`, template);
|
|
55
|
+
};
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
const devServerPort = typeof port === 'number' ? port : useProxy || standalone ? 1337 : 8002;
|
|
58
|
+
return {
|
|
59
|
+
mode: mode || (isProd ? 'production' : 'development'),
|
|
60
|
+
devtool: false,
|
|
61
|
+
entry: {
|
|
62
|
+
App: appEntry,
|
|
63
|
+
},
|
|
64
|
+
output: {
|
|
65
|
+
filename: filenameMask,
|
|
66
|
+
path: outputPath,
|
|
67
|
+
publicPath,
|
|
68
|
+
chunkFilename: filenameMask,
|
|
69
|
+
},
|
|
70
|
+
module: {
|
|
71
|
+
rules: [
|
|
72
|
+
{
|
|
73
|
+
test: new RegExp(appEntry),
|
|
74
|
+
loader: path.resolve(__dirname, './chrome-render-loader.js'),
|
|
75
|
+
options: {
|
|
76
|
+
appName,
|
|
77
|
+
skipChrome2,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
test: /src\/.*\.js$/,
|
|
82
|
+
exclude: /(node_modules|bower_components)/i,
|
|
83
|
+
use: ['babel-loader'],
|
|
63
84
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
chunkFilename: filenameMask
|
|
85
|
+
{
|
|
86
|
+
test: /src\/.*\.tsx?$/,
|
|
87
|
+
loader: 'ts-loader',
|
|
88
|
+
exclude: /(node_modules)/i,
|
|
69
89
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
* Second sass loader used for scoping the css with class name.
|
|
94
|
-
* Has to be included as second in order to re-scope already compiled sass files.
|
|
95
|
-
* Second loader is required to avoid scoping mixins, includes and other sass partials. We want to only scope the CSS output.
|
|
96
|
-
*/
|
|
97
|
-
loader: 'sass-loader',
|
|
98
|
-
options: {
|
|
99
|
-
additionalData: function(content, loaderContext) {
|
|
100
|
-
const { resourcePath, rootContext } = loaderContext;
|
|
101
|
-
const relativePath = path.relative(rootContext, resourcePath);
|
|
102
|
-
/**
|
|
103
|
-
* Add app class context for local style files.
|
|
104
|
-
* Context class is equal to app name and that class ass added to root element via the chrome-render-loader.
|
|
105
|
-
*/
|
|
106
|
-
if (relativePath.match(/^src/)) {
|
|
107
|
-
return `${sassPrefix || `.${appName}`}{\n${content}\n}`;
|
|
108
|
-
}
|
|
90
|
+
{
|
|
91
|
+
test: /\.s?[ac]ss$/,
|
|
92
|
+
use: [
|
|
93
|
+
MiniCssExtractPlugin.loader,
|
|
94
|
+
'css-loader',
|
|
95
|
+
{
|
|
96
|
+
/**
|
|
97
|
+
* Second sass loader used for scoping the css with class name.
|
|
98
|
+
* Has to be included as second in order to re-scope already compiled sass files.
|
|
99
|
+
* Second loader is required to avoid scoping mixins, includes and other sass partials. We want to only scope the CSS output.
|
|
100
|
+
*/
|
|
101
|
+
loader: 'sass-loader',
|
|
102
|
+
options: {
|
|
103
|
+
additionalData: function (content, loaderContext) {
|
|
104
|
+
const { resourcePath, rootContext } = loaderContext;
|
|
105
|
+
const relativePath = path.relative(rootContext, resourcePath);
|
|
106
|
+
/**
|
|
107
|
+
* Add app class context for local style files.
|
|
108
|
+
* Context class is equal to app name and that class ass added to root element via the chrome-render-loader.
|
|
109
|
+
*/
|
|
110
|
+
if (relativePath.match(/^src/)) {
|
|
111
|
+
return `${sassPrefix || `.${appName}`}{\n${content}\n}`;
|
|
112
|
+
}
|
|
109
113
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
'sass-loader'
|
|
115
|
-
]
|
|
116
|
-
}, {
|
|
117
|
-
test: /\.(woff(2)?|ttf|jpg|png|eot|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
|
118
|
-
type: 'asset/resource',
|
|
119
|
-
generator: {
|
|
120
|
-
filename: 'fonts/[name][ext]'
|
|
121
|
-
}
|
|
114
|
+
return content;
|
|
115
|
+
},
|
|
116
|
+
},
|
|
122
117
|
},
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
include: /node_modules/,
|
|
126
|
-
type: 'javascript/auto'
|
|
127
|
-
}]
|
|
118
|
+
'sass-loader',
|
|
119
|
+
],
|
|
128
120
|
},
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
path: require.resolve('path-browserify'),
|
|
136
|
-
stream: require.resolve('stream-browserify'),
|
|
137
|
-
zlib: require.resolve('browserify-zlib'),
|
|
138
|
-
assert: require.resolve('assert/'),
|
|
139
|
-
buffer: require.resolve('buffer/'),
|
|
140
|
-
url: require.resolve('url/'),
|
|
141
|
-
util: require.resolve('util/'),
|
|
142
|
-
process: 'process/browser.js'
|
|
143
|
-
}
|
|
121
|
+
{
|
|
122
|
+
test: /\.(woff(2)?|ttf|jpg|png|eot|gif|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
|
123
|
+
type: 'asset/resource',
|
|
124
|
+
generator: {
|
|
125
|
+
filename: 'fonts/[name][ext]',
|
|
126
|
+
},
|
|
144
127
|
},
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
128
|
+
{
|
|
129
|
+
test: /\.mjs$/,
|
|
130
|
+
include: /node_modules/,
|
|
131
|
+
type: 'javascript/auto',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
resolve: {
|
|
136
|
+
extensions: ['.ts', '.tsx', '.mjs', '.js', '.scss'],
|
|
137
|
+
alias: {
|
|
138
|
+
...(bundlePfModules ? {} : searchIgnoredStyles(rootFolder)),
|
|
139
|
+
},
|
|
140
|
+
fallback: {
|
|
141
|
+
path: require.resolve('path-browserify'),
|
|
142
|
+
stream: require.resolve('stream-browserify'),
|
|
143
|
+
zlib: require.resolve('browserify-zlib'),
|
|
144
|
+
assert: require.resolve('assert/'),
|
|
145
|
+
buffer: require.resolve('buffer/'),
|
|
146
|
+
url: require.resolve('url/'),
|
|
147
|
+
util: require.resolve('util/'),
|
|
148
|
+
process: 'process/browser.js',
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
devServer: {
|
|
152
|
+
static: {
|
|
153
|
+
directory: `${rootFolder || ''}/dist`,
|
|
154
|
+
},
|
|
155
|
+
port: devServerPort,
|
|
156
|
+
https: https || Boolean(useProxy),
|
|
157
|
+
host: '0.0.0.0', // This shares on local network. Needed for docker.host.internal
|
|
158
|
+
hot: false, // Use livereload instead of HMR which is spotty with federated modules
|
|
159
|
+
allowedHosts: 'all',
|
|
160
|
+
// https://github.com/bripkens/connect-history-api-fallback
|
|
161
|
+
historyApiFallback: {
|
|
162
|
+
// We should really implement the same logic as cloud-services-config
|
|
163
|
+
// and only redirect (/beta)?/bundle/app-name to /index.html
|
|
164
|
+
//
|
|
165
|
+
// Until then let known api calls fall through instead of returning /index.html
|
|
166
|
+
// for easier `fetch` debugging
|
|
167
|
+
rewrites: [
|
|
168
|
+
{ from: /^\/api/, to: '/404.html' },
|
|
169
|
+
{ from: /^(\/beta)?\/config/, to: '/404.html' },
|
|
170
|
+
],
|
|
171
|
+
verbose: Boolean(proxyVerbose),
|
|
172
|
+
},
|
|
173
|
+
devMiddleware: {
|
|
174
|
+
writeToDisk: true,
|
|
175
|
+
},
|
|
176
|
+
client,
|
|
177
|
+
...proxy({
|
|
178
|
+
useCloud,
|
|
179
|
+
env,
|
|
180
|
+
localChrome,
|
|
181
|
+
keycloakUri,
|
|
182
|
+
customProxy,
|
|
183
|
+
routes,
|
|
184
|
+
routesPath,
|
|
185
|
+
useProxy,
|
|
186
|
+
proxyURL,
|
|
187
|
+
standalone,
|
|
188
|
+
port: devServerPort,
|
|
189
|
+
reposDir,
|
|
190
|
+
appUrl,
|
|
191
|
+
publicPath,
|
|
192
|
+
proxyVerbose,
|
|
193
|
+
target,
|
|
194
|
+
registry,
|
|
195
|
+
onBeforeSetupMiddleware: ({ chromePath }) => {
|
|
196
|
+
if (useChromeTemplate && chromePath) {
|
|
197
|
+
copyTemplate(chromePath);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
}),
|
|
201
|
+
},
|
|
202
|
+
};
|
|
197
203
|
};
|
package/src/config.test.js
CHANGED
|
@@ -9,135 +9,112 @@ import config from './config';
|
|
|
9
9
|
const configBuilder = (c) => config({ rootFolder: '', ...c });
|
|
10
10
|
|
|
11
11
|
describe('should create dummy config with no options', () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
const { mode, optimization, entry, output, devServer } = config({ rootFolder: '' });
|
|
13
|
+
|
|
14
|
+
const { mode: prodMode } = configBuilder({ mode: 'production' });
|
|
15
|
+
test('mode', () => {
|
|
16
|
+
expect(mode).toBe('development');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('prodMode', () => {
|
|
20
|
+
expect(prodMode).toBe('production');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('optimization', () => {
|
|
24
|
+
expect(optimization).toEqual(undefined);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('entry', () => {
|
|
28
|
+
expect(entry).toEqual({ App: undefined });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('output', () => {
|
|
32
|
+
expect(output).toEqual({
|
|
33
|
+
filename: expect.stringMatching(/js\/\[name\]\.\d+\.\[fullhash\]\.js/),
|
|
34
|
+
path: '/dist',
|
|
35
|
+
publicPath: undefined,
|
|
36
|
+
chunkFilename: expect.stringMatching(/js\/\[name\]\.\d+\.\[fullhash\]\.js/),
|
|
23
37
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
onListening: expect.any(Function),
|
|
50
|
-
static: {
|
|
51
|
-
directory: '/dist'
|
|
52
|
-
},
|
|
53
|
-
https: false,
|
|
54
|
-
host: '0.0.0.0',
|
|
55
|
-
port: 8002,
|
|
56
|
-
hot: false,
|
|
57
|
-
allowedHosts: 'all',
|
|
58
|
-
historyApiFallback: {
|
|
59
|
-
rewrites: [
|
|
60
|
-
{ from: /^\/api/, to: '/404.html' },
|
|
61
|
-
{ from: /^(\/beta)?\/config/, to: '/404.html' }
|
|
62
|
-
],
|
|
63
|
-
verbose: false
|
|
64
|
-
},
|
|
65
|
-
client: {},
|
|
66
|
-
devMiddleware: {
|
|
67
|
-
writeToDisk: true
|
|
68
|
-
}
|
|
69
|
-
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('devServer', () => {
|
|
41
|
+
expect(devServer).toEqual({
|
|
42
|
+
onBeforeSetupMiddleware: expect.any(Function),
|
|
43
|
+
onListening: expect.any(Function),
|
|
44
|
+
static: {
|
|
45
|
+
directory: '/dist',
|
|
46
|
+
},
|
|
47
|
+
https: false,
|
|
48
|
+
host: '0.0.0.0',
|
|
49
|
+
port: 8002,
|
|
50
|
+
hot: false,
|
|
51
|
+
allowedHosts: 'all',
|
|
52
|
+
historyApiFallback: {
|
|
53
|
+
rewrites: [
|
|
54
|
+
{ from: /^\/api/, to: '/404.html' },
|
|
55
|
+
{ from: /^(\/beta)?\/config/, to: '/404.html' },
|
|
56
|
+
],
|
|
57
|
+
verbose: false,
|
|
58
|
+
},
|
|
59
|
+
client: {},
|
|
60
|
+
devMiddleware: {
|
|
61
|
+
writeToDisk: true,
|
|
62
|
+
},
|
|
70
63
|
});
|
|
64
|
+
});
|
|
71
65
|
});
|
|
72
66
|
|
|
73
67
|
describe('rootFolder', () => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
test('devServer', () => {
|
|
83
|
-
expect(devServer.static.directory).toBe('/some/dist');
|
|
84
|
-
});
|
|
68
|
+
const { output, devServer } = configBuilder({ rootFolder: '/some' });
|
|
69
|
+
test('output', () => {
|
|
70
|
+
expect(output.path).toBe('/some/dist');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('devServer', () => {
|
|
74
|
+
expect(devServer.static.directory).toBe('/some/dist');
|
|
75
|
+
});
|
|
85
76
|
});
|
|
86
77
|
|
|
87
78
|
describe('module rules', () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
test('
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
test('first to be chrome-render-loader', () => {
|
|
104
|
-
const {
|
|
105
|
-
module
|
|
106
|
-
} = configBuilder({ appEntry: 'testEntry', appName: 'someName', skipChrome2: true });
|
|
107
|
-
expect(module.rules[0].options.skipChrome2).toBe(true);
|
|
108
|
-
});
|
|
79
|
+
test('length', () => {
|
|
80
|
+
const { module } = configBuilder({ appEntry: 'testEntry', appName: 'someName' });
|
|
81
|
+
expect(module.rules.length).toBe(6);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('first to be chrome-render-loader', () => {
|
|
85
|
+
const { module } = configBuilder({ appEntry: 'testEntry', appName: 'someName' });
|
|
86
|
+
expect(new RegExp(module.rules[0].rules).test('testEntry')).toBe(true);
|
|
87
|
+
expect(module.rules[0].options.skipChrome2).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('first to be chrome-render-loader', () => {
|
|
91
|
+
const { module } = configBuilder({ appEntry: 'testEntry', appName: 'someName', skipChrome2: true });
|
|
92
|
+
expect(module.rules[0].options.skipChrome2).toBe(true);
|
|
93
|
+
});
|
|
109
94
|
});
|
|
110
95
|
|
|
111
96
|
test('appEntry correctly set', () => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} = configBuilder({ appEntry: 'testEntry' });
|
|
115
|
-
expect(entry).toEqual({ App: 'testEntry' });
|
|
97
|
+
const { entry } = configBuilder({ appEntry: 'testEntry' });
|
|
98
|
+
expect(entry).toEqual({ App: 'testEntry' });
|
|
116
99
|
});
|
|
117
100
|
|
|
118
101
|
describe('publicPath', () => {
|
|
119
|
-
|
|
120
|
-
output
|
|
121
|
-
} = configBuilder({ publicPath: 'test-value' });
|
|
102
|
+
const { output } = configBuilder({ publicPath: 'test-value' });
|
|
122
103
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
104
|
+
test('output', () => {
|
|
105
|
+
expect(output.publicPath).toBe('test-value');
|
|
106
|
+
});
|
|
126
107
|
});
|
|
127
108
|
|
|
128
109
|
describe('port', () => {
|
|
129
|
-
|
|
130
|
-
devServer
|
|
131
|
-
} = configBuilder({ port: 1000 });
|
|
110
|
+
const { devServer } = configBuilder({ port: 1000 });
|
|
132
111
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
112
|
+
test('devServer', () => {
|
|
113
|
+
expect(devServer.port).toBe(1000);
|
|
114
|
+
});
|
|
136
115
|
});
|
|
137
116
|
|
|
138
117
|
test('https', () => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
} = configBuilder({ https: true });
|
|
142
|
-
expect(devServer.https).toBe(true);
|
|
118
|
+
const { devServer } = configBuilder({ https: true });
|
|
119
|
+
expect(devServer.https).toBe(true);
|
|
143
120
|
});
|
package/src/plugins.js
CHANGED
|
@@ -8,62 +8,56 @@ const ChunkMapperPlugin = require('@redhat-cloud-services/frontend-components-co
|
|
|
8
8
|
const jsVarName = require('@redhat-cloud-services/frontend-components-config-utilities/jsVarName');
|
|
9
9
|
|
|
10
10
|
module.exports = ({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
rootFolder,
|
|
12
|
+
appDeployment,
|
|
13
|
+
htmlPlugin,
|
|
14
|
+
replacePlugin,
|
|
15
|
+
insights,
|
|
16
|
+
modules,
|
|
17
|
+
generateSourceMaps,
|
|
18
|
+
plugins,
|
|
19
|
+
useChromeTemplate = false,
|
|
20
20
|
} = {}) => [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
]
|
|
43
|
-
}),
|
|
44
|
-
...(useChromeTemplate ? [] : [
|
|
21
|
+
...(generateSourceMaps
|
|
22
|
+
? [
|
|
23
|
+
new SourceMapDevToolPlugin({
|
|
24
|
+
test: 'js',
|
|
25
|
+
exclude: /(node_modules|bower_components)/i,
|
|
26
|
+
filename: 'sourcemaps/[name].[contenthash].js.map',
|
|
27
|
+
}),
|
|
28
|
+
]
|
|
29
|
+
: []),
|
|
30
|
+
new MiniCssExtractPlugin({
|
|
31
|
+
chunkFilename: 'css/[name].[contenthash].css',
|
|
32
|
+
filename: 'css/[name].[contenthash].css',
|
|
33
|
+
ignoreOrder: true,
|
|
34
|
+
}),
|
|
35
|
+
new CleanWebpackPlugin({
|
|
36
|
+
cleanStaleWebpackAssets: false,
|
|
37
|
+
cleanOnceBeforeBuildPatterns: useChromeTemplate ? ['**/*', '!index.html'] : ['**/*'],
|
|
38
|
+
}),
|
|
39
|
+
...(useChromeTemplate
|
|
40
|
+
? []
|
|
41
|
+
: [
|
|
45
42
|
new HtmlWebpackPlugin({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
title: 'My App',
|
|
44
|
+
filename: 'index.html',
|
|
45
|
+
template: `${rootFolder || ''}/src/index.html`,
|
|
46
|
+
inject: false,
|
|
47
|
+
...(htmlPlugin || {}),
|
|
51
48
|
}),
|
|
52
49
|
new HtmlReplaceWebpackPlugin([
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
])
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
...modules || []
|
|
67
|
-
] }),
|
|
68
|
-
...(plugins || [])
|
|
50
|
+
{
|
|
51
|
+
pattern: '@@env',
|
|
52
|
+
replacement: appDeployment || '',
|
|
53
|
+
},
|
|
54
|
+
...(replacePlugin || []),
|
|
55
|
+
]),
|
|
56
|
+
]),
|
|
57
|
+
new ProvidePlugin({
|
|
58
|
+
process: 'process/browser.js',
|
|
59
|
+
Buffer: ['buffer', 'Buffer'],
|
|
60
|
+
}),
|
|
61
|
+
new ChunkMapperPlugin({ modules: [...(insights ? [jsVarName(insights.appname)] : []), ...(modules || [])] }),
|
|
62
|
+
...(plugins || []),
|
|
69
63
|
];
|
package/src/plugins.test.js
CHANGED
|
@@ -4,55 +4,51 @@ const HTML_WEBPACK = 2;
|
|
|
4
4
|
const REPLACE = 3;
|
|
5
5
|
|
|
6
6
|
describe('plugins generations, no option', () => {
|
|
7
|
-
|
|
7
|
+
const enabledPlugins = plugins();
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
it('should generate plugins', () => {
|
|
10
|
+
expect(enabledPlugins.length).toBe(6);
|
|
11
|
+
});
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
it('should generate plugins with sourceMaps', () => {
|
|
14
|
+
const enabledPlugins = plugins({ generateSourceMaps: true });
|
|
15
|
+
expect(enabledPlugins.length).toBe(7);
|
|
16
|
+
});
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
it('should generate correct template path for HtmlWebpackPlugin', () => {
|
|
19
|
+
expect(enabledPlugins[HTML_WEBPACK].userOptions.template).toBe('/src/index.html');
|
|
20
|
+
});
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
describe('rootFolder', () => {
|
|
24
|
-
|
|
24
|
+
const enabledPlugins = plugins({ rootFolder: '/test/folder' });
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
it('should generate correct template path for HtmlWebpackPlugin', () => {
|
|
27
|
+
expect(enabledPlugins[HTML_WEBPACK].userOptions.template).toBe('/test/folder/src/index.html');
|
|
28
|
+
});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
describe('appDeployment', () => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
(_, { html }) => expect(html).toBe('string /test/folder')
|
|
38
|
-
);
|
|
39
|
-
});
|
|
32
|
+
const enabledPlugins = plugins({ appDeployment: '/test/folder' });
|
|
33
|
+
|
|
34
|
+
it('should replace correct string', () => {
|
|
35
|
+
enabledPlugins[REPLACE].replace({ html: 'string @@env' }, (_, { html }) => expect(html).toBe('string /test/folder'));
|
|
36
|
+
});
|
|
40
37
|
});
|
|
41
38
|
|
|
42
39
|
it('htmlPlugin should update', () => {
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const enabledPlugins = plugins({ htmlPlugin: { title: 'myTitle' } });
|
|
41
|
+
expect(enabledPlugins[HTML_WEBPACK].userOptions.title).toBe('myTitle');
|
|
45
42
|
});
|
|
46
43
|
|
|
47
44
|
it('replacePlugin should update', () => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
);
|
|
45
|
+
const enabledPlugins = plugins({
|
|
46
|
+
replacePlugin: [
|
|
47
|
+
{
|
|
48
|
+
pattern: '@@another',
|
|
49
|
+
replacement: 'test-string',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
enabledPlugins[REPLACE].replace({ html: '@@another string @@env' }, (_, { html }) => expect(html).toBe('test-string string '));
|
|
58
54
|
});
|