NIFIREG-289 - UI - isolate webpack loaders used specifically for code coverage purposes

This closes #203

Signed-off-by: Scott Aslan <scottyaslan@gmail.com>
diff --git a/.gitignore b/.gitignore
index d8111db..077a155 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,4 +29,4 @@
 nifi-registry-core/nifi-registry-web-ui/src/main/coverage
 nifi-registry-core/nifi-registry-web-ui/src/main/assets
 nifi-registry-core/nifi-registry-web-ui/src/main/*.png
-nifi-registry-core/nifi-registry-web-ui/src/main/.cache-loader
+nifi-registry-core/nifi-registry-web-ui/src/main/.cache-loader*
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index 51e5b27..ec82e63 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -1990,6 +1990,95 @@
         "babel-runtime": "6.26.0"
       }
     },
+    "babel-plugin-istanbul": {
+      "version": "5.1.4",
+      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz",
+      "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==",
+      "dev": true,
+      "requires": {
+        "find-up": "3.0.0",
+        "istanbul-lib-instrument": "3.3.0",
+        "test-exclude": "5.2.3"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "3.0.0"
+          }
+        },
+        "istanbul-lib-coverage": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+          "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+          "dev": true
+        },
+        "istanbul-lib-instrument": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+          "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+          "dev": true,
+          "requires": {
+            "@babel/generator": "7.4.4",
+            "@babel/parser": "7.4.4",
+            "@babel/template": "7.4.4",
+            "@babel/traverse": "7.4.4",
+            "@babel/types": "7.4.4",
+            "istanbul-lib-coverage": "2.0.5",
+            "semver": "6.1.3"
+          }
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "3.0.0",
+            "path-exists": "3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+          "dev": true,
+          "requires": {
+            "p-try": "2.2.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "path-exists": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+          "dev": true
+        },
+        "semver": {
+          "version": "6.1.3",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.3.tgz",
+          "integrity": "sha512-aymF+56WJJMyXQHcd4hlK4N75rwj5RQpfW8ePlQnJsTYOBLlLbcIErR/G1s9SkIvKBqOudR3KAx4wEqP+F1hNQ==",
+          "dev": true
+        }
+      }
+    },
     "babel-polyfill": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
@@ -14515,6 +14604,139 @@
         }
       }
     },
+    "test-exclude": {
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
+      "dev": true,
+      "requires": {
+        "glob": "7.1.3",
+        "minimatch": "3.0.4",
+        "read-pkg-up": "4.0.0",
+        "require-main-filename": "2.0.0"
+      },
+      "dependencies": {
+        "find-up": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+          "dev": true,
+          "requires": {
+            "locate-path": "3.0.0"
+          }
+        },
+        "load-json-file": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+          "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "4.1.15",
+            "parse-json": "4.0.0",
+            "pify": "3.0.0",
+            "strip-bom": "3.0.0"
+          }
+        },
+        "locate-path": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+          "dev": true,
+          "requires": {
+            "p-locate": "3.0.0",
+            "path-exists": "3.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+          "dev": true,
+          "requires": {
+            "p-try": "2.2.0"
+          }
+        },
+        "p-locate": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+          "dev": true,
+          "requires": {
+            "p-limit": "2.2.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+          "dev": true
+        },
+        "parse-json": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+          "dev": true,
+          "requires": {
+            "error-ex": "1.3.1",
+            "json-parse-better-errors": "1.0.2"
+          }
+        },
+        "path-exists": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+          "dev": true
+        },
+        "path-type": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+          "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+          "dev": true,
+          "requires": {
+            "pify": "3.0.0"
+          }
+        },
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        },
+        "read-pkg": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+          "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+          "dev": true,
+          "requires": {
+            "load-json-file": "4.0.0",
+            "normalize-package-data": "2.4.0",
+            "path-type": "3.0.0"
+          }
+        },
+        "read-pkg-up": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+          "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+          "dev": true,
+          "requires": {
+            "find-up": "3.0.0",
+            "read-pkg": "3.0.0"
+          }
+        },
+        "require-main-filename": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+          "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+          "dev": true
+        },
+        "strip-bom": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+          "dev": true
+        }
+      }
+    },
     "text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
index 2d26082..ce255d3 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
@@ -85,6 +85,7 @@
     "@babel/runtime": "7.4.4",
     "@typescript-eslint/eslint-plugin": "1.6.0",
     "babel-loader": "8.0.5",
+    "babel-plugin-istanbul": "5.1.4",
     "babel-polyfill": "6.26.0",
     "cache-loader": "3.0.0",
     "compression-webpack-plugin": "2.0.0",
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.common.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.common.js
index 4fc698a..713900e 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.common.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.common.js
@@ -74,8 +74,6 @@
 
     module: {
         rules: [
-            loaders.ts,
-            loaders.js,
             loaders.html,
             loaders.scss,
             loaders.images,
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.dev.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.dev.js
index 8aec742..fed85f3 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.dev.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.dev.js
@@ -24,13 +24,14 @@
 const CompressionPlugin = require('compression-webpack-plugin');
 
 const commonConfig = require('./webpack.common');
+const loaders = require('./webpack.loader');
 
 module.exports = merge(commonConfig, {
     // Tells webpack to use its built-in optimizations accordingly
     mode: 'development',
 
     // Source maps
-    devtool: 'eval-source-map',
+    devtool: 'inline-source-map',
 
     // Output bundles
     output: {
@@ -72,14 +73,17 @@
         stats: 'verbose'
     },
 
+    module: {
+        rules: [
+            loaders.ts,
+            loaders.js,
+        ]
+    },
+
     plugins: [
         // Hot Module Replacement
         new webpack.HotModuleReplacementPlugin(),
 
-        // Source map generation
-        new webpack.SourceMapDevToolPlugin({
-            filename: '[file].map'
-        }),
         // Create CSS files separately
         new MiniCssExtractPlugin({
             filename: '[name].css',
@@ -116,7 +120,7 @@
                             const missingLicenseText = `*** No license text found ***\n`
                             const licText =`This product bundles '${lic.packageJson.name}' which is available under a(n) ${lic.packageJson.license} license.\n\t${missingLicenseText}`;
 
-                            return licText
+                            return licText;
                         } else {
                             return `\n\n!!! No license information found for ${lic.packageJson.name} !!!\n\n`;
                         }
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
index bd4c555..01eb073 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
@@ -30,8 +30,8 @@
 
     module: {
         rules: [
-            loaders.tsDev,
-            loaders.jsDev,
+            loaders.tsCoverage,
+            loaders.jsCoverage,
             loaders.html,
             loaders.ignoreScss,
             loaders.images,
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
index 1d9bc7a..5014a98 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
@@ -18,6 +18,8 @@
 const path = require('path');
 const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 
+const cacheCoverageDir = '.cache-loader-coverage';
+
 module.exports = {
     ts: {
         test: /\.tsx?$/,
@@ -37,7 +39,7 @@
         ]
     },
 
-    tsDev: {
+    tsCoverage: {
         test: /\.tsx?$/,
         include: [
             path.resolve(__dirname, 'webapp')
@@ -51,14 +53,14 @@
                 loader: 'cache-loader'
             },
             {
+                loader: path.resolve(__dirname, 'angular-url-loader')
+            },
+            {
                 // Instrument TS files with istanbul-lib-instrument for subsequent code coverage reporting
                 loader: 'istanbul-instrumenter-loader',
                 options: { esModules: true }
             },
             {
-                loader: path.resolve(__dirname, 'angular-url-loader')
-            },
-            {
                 loader: 'ts-loader'
             }
         ]
@@ -86,7 +88,7 @@
         ]
     },
 
-    jsDev: {
+    jsCoverage: {
         test: /\.js$/,
         include: [
             path.resolve(__dirname, 'webapp'),
@@ -99,12 +101,10 @@
         ],
         use: [
             {
-                loader: 'cache-loader'
-            },
-            {
-                // Instrument JS files with istanbul-lib-instrument for subsequent code coverage reporting
-                loader: 'istanbul-instrumenter-loader',
-                options: { esModules: true }
+                loader: 'cache-loader',
+                options: {
+                    cacheDirectory: cacheCoverageDir
+                }
             },
             {
                 loader: path.resolve(__dirname, 'angular-url-loader')
@@ -112,7 +112,8 @@
             {
                 loader: 'babel-loader',
                 options: {
-                    presets: ['@babel/preset-env']
+                    presets: ['@babel/preset-env'],
+                    plugins: ['babel-plugin-istanbul']
                 }
             }
         ]
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.prod.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.prod.js
index 1763d2d..2e43f61 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.prod.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.prod.js
@@ -25,6 +25,7 @@
 const path = require('path');
 
 const commonConfig = require('./webpack.common');
+const loaders = require('./webpack.loader');
 
 module.exports = merge(commonConfig, {
     // Tells webpack to use its built-in optimizations accordingly
@@ -38,6 +39,13 @@
         filename: '[name].[contenthash].js'
     },
 
+    module: {
+        rules: [
+            loaders.ts,
+            loaders.js,
+        ]
+    },
+
     optimization: {
         minimizer: [
             // Minify JavaScript