Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/gopath
/Godeps/_workspace/src/github.com/openshift/console
/frontend/.cache-loader
/frontend/.webpack-cycles
/frontend/__coverage__
/frontend/__chrome_browser__
/frontend/**/node_modules
Expand Down
6 changes: 4 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dev": "yarn clean && NODE_OPTIONS=--max-old-space-size=4096 ts-node -O '{\"module\":\"commonjs\"}' ./node_modules/.bin/webpack-dev-server",
"dev-once": "yarn clean && NODE_OPTIONS=--max-old-space-size=4096 ts-node -O '{\"module\":\"commonjs\"}' ./node_modules/.bin/webpack --mode=development",
"build": "yarn clean && NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 ts-node -O '{\"module\":\"commonjs\"}' ./node_modules/.bin/webpack --mode=production",
"check-cycles": "CHECK_CYCLES=true yarn dev-once",
"coverage": "jest --coverage .",
"eslint": "eslint --ext .js,.jsx,.ts,.tsx,.json --color",
"lint": "NODE_OPTIONS=--max-old-space-size=4096 yarn eslint .",
Expand Down Expand Up @@ -76,13 +77,13 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^5.9.0",
"@patternfly/patternfly": "2.65.3",
"@patternfly/react-catalog-view-extension": "1.4.11",
"@patternfly/react-charts": "5.2.2",
"@patternfly/react-core": "3.140.11",
"@patternfly/react-table": "2.24.41",
"@patternfly/react-tokens": "2.7.10",
"@patternfly/react-topology": "2.11.27",
"@patternfly/react-virtualized-extension": "1.3.40",
"@patternfly/react-catalog-view-extension": "1.4.11",
"abort-controller": "3.0.0",
"classnames": "2.x",
"core-js": "2.x",
Expand Down Expand Up @@ -165,7 +166,7 @@
"cache-loader": "1.x",
"chalk": "2.3.x",
"chromedriver": "77.x",
"circular-dependency-plugin": "5.0.2",
"circular-dependency-plugin": "5.x",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, this dependency was introduced in #1456 (unused until now).

"css-loader": "0.28.x",
"enzyme": "3.10.x",
"enzyme-adapter-react-16": "1.15.2",
Expand All @@ -182,6 +183,7 @@
"jest": "21.x",
"jest-cli": "21.x",
"mini-css-extract-plugin": "0.4.x",
"moment": "2.22.x",
"monaco-editor-core": "0.14.0",
"monaco-editor-webpack-plugin": "^1.7.0",
"node-sass": "4.13.x",
Expand Down
83 changes: 83 additions & 0 deletions frontend/webpack.circular-deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-env node */
/* eslint-disable no-console */

import * as webpack from 'webpack';
import * as path from 'path';
import * as fs from 'fs';
import * as moment from 'moment';
import * as CircularDependencyPlugin from 'circular-dependency-plugin';

type PresetOptions = {
exclude: RegExp;
reportFile: string;
};

type DetectedCycle = {
// webpack module record that caused the cycle
causedBy: string;
// relative module paths that make up the cycle
modulePaths: string[];
};

export class CircularDependencyPreset {
private readonly HandleCyclesPluginName = 'HandleCyclesPlugin';

constructor(private readonly options: PresetOptions) {}

private getCycleReport(cycles: DetectedCycle[], compilation: webpack.compilation.Compilation) {
const hash = compilation.getStats().hash;
const builtAt = moment(compilation.getStats().endTime).format('MM/DD/YYYY HH:mm:ss');

const countByDir = cycles
.map((c) => c.modulePaths[0].replace(/\/.*$/, ''))
.reduce((acc, dir) => {
acc[dir] = (acc[dir] ?? 0) + 1;
return acc;
}, {} as { [key: string]: number });

const header =
`# webpack compilation ${hash} built at ${builtAt}\n` +
'# this file is auto-generated on every webpack development build\n';

const stats =
`# ${cycles.length} total cycles: ${Object.keys(countByDir)
.map((d) => `${d} (${countByDir[d]})`)
.join(', ')}\n` +
`# ${
cycles.filter((c) => c.modulePaths.length === 3).length
} minimal-length cycles (A -> B -> A)\n`;

const entries = cycles.map((c) => `${c.causedBy}\n${c.modulePaths.join('\n-> ')}\n`).join('\n');

return [header, stats, entries].join('\n');
}

apply(plugins: webpack.Plugin[]) {
const cycles: DetectedCycle[] = [];

plugins.push(
new CircularDependencyPlugin({
exclude: this.options.exclude,
onDetected: ({ module: { resource }, paths: modulePaths }) => {
cycles.push({ causedBy: resource, modulePaths });
},
}),
{
// Ad-hoc plugin to handle detected module cycle information
apply: (compiler) => {
compiler.hooks.emit.tap(this.HandleCyclesPluginName, (compilation) => {
if (cycles.length === 0) {
return;
}

const reportPath = path.resolve(__dirname, this.options.reportFile);
fs.writeFileSync(reportPath, this.getCycleReport(cycles, compilation));

console.log(`detected ${cycles.length} cycles`);
console.log(`module cycle report written to ${reportPath}`);
});
},
},
);
}
}
13 changes: 11 additions & 2 deletions frontend/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import * as VirtualModulesPlugin from 'webpack-virtual-modules';

import { resolvePluginPackages, getActivePluginsModule } from '@console/plugin-sdk/src/codegen';
import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import { CircularDependencyPreset } from './webpack.circular-deps';

interface Configuration extends webpack.Configuration {
devServer?: WebpackDevServerConfiguration;
}

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

const NODE_ENV = process.env.NODE_ENV;
const HOT_RELOAD = process.env.HOT_RELOAD;
const NODE_ENV = process.env.NODE_ENV || 'development';
const HOT_RELOAD = process.env.HOT_RELOAD || 'false';
const CHECK_CYCLES = process.env.CHECK_CYCLES || 'false';

/* Helpers */
const extractCSS = new MiniCssExtractPlugin({ filename: 'app-bundle.[contenthash].css' });
Expand Down Expand Up @@ -163,6 +165,13 @@ const config: Configuration = {
stats: 'minimal',
};

if (CHECK_CYCLES === 'true') {
new CircularDependencyPreset({
exclude: /node_modules|public\/dist/,
reportFile: '.webpack-cycles',
}).apply(config.plugins);
}

/* Production settings */
if (NODE_ENV === 'production') {
config.output.filename = '[name]-bundle-[hash].min.js';
Expand Down
10 changes: 5 additions & 5 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4783,10 +4783,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"

circular-dependency-plugin@5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz#da168c0b37e7b43563fb9f912c1c007c213389ef"
integrity sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==
circular-dependency-plugin@5.x:
version "5.2.0"
resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz#e09dbc2dd3e2928442403e2d45b41cea06bc0a93"
integrity sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==

clap@^1.0.9:
version "1.2.3"
Expand Down Expand Up @@ -11259,7 +11259,7 @@ moment-timezone@^0.4.0, moment-timezone@^0.4.1:
dependencies:
moment ">= 2.6.0"

"moment@>= 2.6.0", moment@^2.10, moment@^2.19.1:
moment@2.22.x, "moment@>= 2.6.0", moment@^2.10, moment@^2.19.1:
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"

Expand Down