From 464bb3b8857ca7da87de4df85c6204141975816c Mon Sep 17 00:00:00 2001 From: Nikhil Date: Wed, 29 Dec 2021 16:18:48 -0800 Subject: [PATCH] [Build] webpack5 upgrade (#4242) --- .npmrc | 5 ++ app.js | 20 +++-- karma.conf.js | 5 +- package.json | 26 ++++--- src/MCT.js | 2 - .../components/layout-frame.scss | 4 +- .../components/flexible-layout.scss | 4 +- .../folderView/components/grid-view.scss | 6 +- src/plugins/timeConductor/conductor-axis.scss | 4 +- src/styles/_constants-mobile.scss | 5 +- src/styles/_controls.scss | 6 +- src/styles/_global.scss | 5 +- src/styles/_legacy-messages.scss | 5 +- src/styles/_legacy.scss | 5 +- src/styles/_mixins.scss | 8 +- src/ui/components/toggle-switch.scss | 4 +- src/ui/layout/mct-tree.scss | 4 +- src/ui/layout/pane.scss | 10 ++- webpack.config.js => webpack.common.js | 75 ++++++++----------- webpack.dev.js | 20 +++++ webpack.prod.js | 20 +++++ 21 files changed, 155 insertions(+), 88 deletions(-) rename webpack.config.js => webpack.common.js (74%) create mode 100644 webpack.dev.js create mode 100644 webpack.prod.js diff --git a/.npmrc b/.npmrc index 8ab02bf6ed..3b88981879 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,6 @@ loglevel=warn + +# Temporary: istanbul-instrumenter-loader is working with webpack 5, but states +# webpack 4 being the latest version it supports, so this legacy-peer-deps +# allows us to install it anyway. +legacy-peer-deps=true \ No newline at end of file diff --git a/app.js b/app.js index 5d98b5b964..76f9f66ff4 100644 --- a/app.js +++ b/app.js @@ -7,7 +7,6 @@ * node app.js [options] */ - const options = require('minimist')(process.argv.slice(2)); const express = require('express'); const app = express(); @@ -40,10 +39,19 @@ app.use('/proxyUrl', function proxyRequest(req, res, next) { }).on('error', next)).pipe(res); }); +class WatchRunPlugin { + apply(compiler) { + compiler.hooks.emit.tapAsync('WatchRunPlugin', (compilation, callback) => { + console.log('Begin compile at ' + new Date()); + callback(); + }); + } +} + const webpack = require('webpack'); -const webpackConfig = require('./webpack.config.js'); +const webpackConfig = require('./webpack.dev.js'); webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin()); -webpackConfig.plugins.push(function() { this.plugin('watch-run', function(watching, callback) { console.log('Begin compile at ' + new Date()); callback(); }) }); +webpackConfig.plugins.push(new WatchRunPlugin()); webpackConfig.entry.openmct = [ 'webpack-hot-middleware/client?reload=true', @@ -62,9 +70,7 @@ app.use(require('webpack-dev-middleware')( app.use(require('webpack-hot-middleware')( compiler, - { - - } + {} )); // Expose index.html for development users. @@ -74,5 +80,5 @@ app.get('/', function (req, res) { // Finally, open the HTTP server and log the instance to the console app.listen(options.port, options.host, function() { - console.log('Open MCT application running at %s:%s', options.host, options.port) + console.log('Open MCT application running at %s:%s', options.host, options.port); }); diff --git a/karma.conf.js b/karma.conf.js index 7a99a4f453..e0afe2ee16 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -22,7 +22,6 @@ /*global module,process*/ -const devMode = process.env.NODE_ENV !== 'production'; const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless']; const coverageEnabled = process.env.COVERAGE === 'true'; const reporters = ['spec', 'junit']; @@ -32,10 +31,10 @@ if (coverageEnabled) { } module.exports = (config) => { - const webpackConfig = require('./webpack.config.js'); + const webpackConfig = require('./webpack.dev.js'); delete webpackConfig.output; - if (!devMode || coverageEnabled) { + if (coverageEnabled) { webpackConfig.module.rules.push({ test: /\.js$/, exclude: /node_modules|example|lib|dist/, diff --git a/package.json b/package.json index f88d49e906..39f0eec2e5 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "babel-eslint": "10.1.0", "comma-separated-values": "^3.6.4", "concurrently": "^3.6.1", - "copy-webpack-plugin": "^4.5.2", + "copy-webpack-plugin": "^9.0.0", "cross-env": "^6.0.3", - "css-loader": "^1.0.0", + "css-loader": "^4.0.0", "d3-axis": "1.0.x", "d3-scale": "1.0.x", "d3-selection": "1.3.x", @@ -26,8 +26,7 @@ "eventemitter3": "^1.2.0", "exports-loader": "^0.7.0", "express": "^4.13.1", - "fast-sass-loader": "1.4.6", - "file-loader": "^1.1.11", + "file-loader": "^6.1.0", "file-saver": "^1.3.8", "git-rev-sync": "^1.4.0", "glob": ">= 3.0.0", @@ -47,18 +46,17 @@ "karma-junit-reporter": "2.0.1", "karma-sourcemap-loader": "0.3.8", "karma-spec-reporter": "0.0.32", - "karma-webpack": "4.0.2", + "karma-webpack": "^5.0.0", "location-bar": "^3.0.1", "lodash": "^4.17.12", "markdown-toc": "^0.11.7", "marked": "^0.3.5", - "mini-css-extract-plugin": "^0.4.1", + "mini-css-extract-plugin": "^1.6.0", "minimist": "^1.2.5", "moment": "2.25.3", "moment-duration-format": "^2.2.2", "moment-timezone": "0.5.28", "node-bourbon": "^4.2.3", - "node-sass": "^4.14.1", "painterro": "^1.2.56", "playwright": "^1.16.3", "plotly.js-basic-dist": "^2.5.0", @@ -66,6 +64,9 @@ "printj": "^1.2.1", "raw-loader": "^0.5.1", "request": "^2.69.0", + "resolve-url-loader": "^4.0.0", + "sass": "^1.42.1", + "sass-loader": "^12.1.0", "sinon": "^12.0.1", "split": "^1.0.0", "style-loader": "^1.0.1", @@ -75,10 +76,11 @@ "vue-eslint-parser": "8.0.1", "vue-loader": "^15.2.6", "vue-template-compiler": "2.5.6", - "webpack": "^4.16.2", - "webpack-cli": "^3.1.0", + "webpack": "^5.53.0", + "webpack-cli": "^4.0.0", "webpack-dev-middleware": "^3.1.3", "webpack-hot-middleware": "^2.22.3", + "webpack-merge": "^5.8.0", "zepto": "^1.2.0" }, "scripts": { @@ -87,9 +89,9 @@ "start": "node app.js", "lint": "eslint platform example src --ext .js,.vue openmct.js", "lint:fix": "eslint platform example src --ext .js,.vue openmct.js --fix", - "build:prod": "cross-env NODE_ENV=production webpack", - "build:dev": "webpack", - "build:watch": "webpack --watch", + "build:prod": "cross-env webpack --config webpack.prod.js", + "build:dev": "webpack --config webpack.dev.js", + "build:watch": "webpack --config webpack.dev.js --watch", "test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run", "test:debug": "cross-env NODE_ENV=debug karma start --no-single-run", "test:coverage": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" COVERAGE=true karma start --single-run", diff --git a/src/MCT.js b/src/MCT.js index bf0181af50..90a282aa1e 100644 --- a/src/MCT.js +++ b/src/MCT.js @@ -22,7 +22,6 @@ define([ 'EventEmitter', - 'uuid', './BundleRegistry', './installDefaultBundles', './api/api', @@ -53,7 +52,6 @@ define([ 'vue' ], function ( EventEmitter, - uuid, BundleRegistry, installDefaultBundles, api, diff --git a/src/plugins/displayLayout/components/layout-frame.scss b/src/plugins/displayLayout/components/layout-frame.scss index 0dbc10f877..63f2299ecb 100644 --- a/src/plugins/displayLayout/components/layout-frame.scss +++ b/src/plugins/displayLayout/components/layout-frame.scss @@ -1,3 +1,5 @@ +@use 'sass:math'; + /******************* FRAME */ .c-frame { display: flex; @@ -89,7 +91,7 @@ &:before { // Grippy $h: 4px; - $tbOffset: ($editFrameMovebarH - $h) / 2; + $tbOffset: math.div($editFrameMovebarH - $h, 2); $lrOffset: 25%; @include grippy($editFrameMovebarColorFg); content: ''; diff --git a/src/plugins/flexibleLayout/components/flexible-layout.scss b/src/plugins/flexibleLayout/components/flexible-layout.scss index c496422ed1..ac44eb3d3c 100644 --- a/src/plugins/flexibleLayout/components/flexible-layout.scss +++ b/src/plugins/flexibleLayout/components/flexible-layout.scss @@ -1,7 +1,9 @@ +@use 'sass:math'; + @mixin containerGrippy($headerSize, $dir) { position: absolute; $h: 6px; - $minorOffset: ($headerSize - $h) / 2; + $minorOffset: math.div($headerSize - $h, 2); $majorOffset: 35%; content: ''; display: block; diff --git a/src/plugins/folderView/components/grid-view.scss b/src/plugins/folderView/components/grid-view.scss index fcb93c20f4..27c84b957d 100644 --- a/src/plugins/folderView/components/grid-view.scss +++ b/src/plugins/folderView/components/grid-view.scss @@ -1,3 +1,5 @@ +@use 'sass:math'; + /******************************* GRID VIEW */ .l-grid-view { display: flex; @@ -42,7 +44,7 @@ &__type-icon { filter: $colorKeyFilter; flex: 0 0 $gridItemMobile; - font-size: floor($gridItemMobile / 2); + font-size: floor(math.div($gridItemMobile, 2)); margin-right: $interiorMarginLg; } @@ -166,7 +168,7 @@ &__type-icon { flex: 1 1 auto; - font-size: floor($gridItemDesk / 3); + font-size: floor(math.div($gridItemDesk, 3)); margin: $interiorMargin 22.5% $interiorMargin * 3 22.5%; order: 2; transform-origin: center; diff --git a/src/plugins/timeConductor/conductor-axis.scss b/src/plugins/timeConductor/conductor-axis.scss index b16a58f718..c34ffadca4 100644 --- a/src/plugins/timeConductor/conductor-axis.scss +++ b/src/plugins/timeConductor/conductor-axis.scss @@ -1,6 +1,8 @@ +@use 'sass:math'; + .c-conductor-axis { $h: 18px; - $tickYPos: ($h / 2) + 12px; + $tickYPos: math.div($h, 2) + 12px; @include userSelectNone(); @include bgTicks($c: rgba($colorBodyFg, 0.4)); diff --git a/src/styles/_constants-mobile.scss b/src/styles/_constants-mobile.scss index 9eb9692f6b..832f6eaafd 100644 --- a/src/styles/_constants-mobile.scss +++ b/src/styles/_constants-mobile.scss @@ -21,14 +21,15 @@ *****************************************************************************/ /* REQUIRES /platform/commonUI/general/res/sass/_constants.scss */ +@use 'sass:math'; /************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */ $mobileListIconSize: 30px; $mobileTitleDescH: 35px; $mobileOverlayMargin: 20px; $mobileMenuIconD: 25px; -$phoneItemH: floor($gridItemMobile / 4); -$tabletItemH: floor($gridItemMobile / 3); +$phoneItemH: floor(math.div($gridItemMobile, 4)); +$tabletItemH: floor(math.div($gridItemMobile, 3)); /************************** MOBILE TREE MENU DIMENSIONS */ $mobileTreeItemH: 35px; diff --git a/src/styles/_controls.scss b/src/styles/_controls.scss index a58eb1f632..67a884bc13 100644 --- a/src/styles/_controls.scss +++ b/src/styles/_controls.scss @@ -20,6 +20,8 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ +@use 'sass:math'; + /******************************************************** BUTTONS */ // Optionally can include icon in :before via markup button { @@ -785,7 +787,7 @@ select { } &--swatched { - padding-bottom: floor($pTB / 2); + padding-bottom: floor(math.div($pTB, 2)); width: 2em; // Standardize the width } @@ -935,7 +937,7 @@ select { @mixin sliderTrack($bg: $scrollbarTrackColorBg, $knobH: 12px, $trackH: 3px) { border-radius: 2px; - $breakPointPx: floor(($knobH - $trackH) / 2); + $breakPointPx: floor(math.div($knobH - $trackH, 2)); $bp1: $breakPointPx; $bp2: $breakPointPx + $trackH; box-sizing: border-box; diff --git a/src/styles/_global.scss b/src/styles/_global.scss index 1c0c12d2d4..7b4ff1870c 100644 --- a/src/styles/_global.scss +++ b/src/styles/_global.scss @@ -19,6 +19,9 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ + +@use 'sass:math'; + /******************************************************** RESETS */ *, :before, @@ -308,7 +311,7 @@ body.desktop .has-local-controls { } &.c-tree__item { $d: $waitSpinnerTreeD; - $spinnerL: 19 + $d/2; + $spinnerL: 19 + math.div($d, 2); display: flex; align-items: center; diff --git a/src/styles/_legacy-messages.scss b/src/styles/_legacy-messages.scss index f19ce11a28..f476d65cc1 100644 --- a/src/styles/_legacy-messages.scss +++ b/src/styles/_legacy-messages.scss @@ -19,6 +19,9 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ + +@use 'sass:math'; + /******************************************************************* MESSAGES */ .w-message-contents { flex: 1 1 auto; @@ -120,7 +123,7 @@ body.desktop .t-message-list { } // Alert elements in views -mixin sUnSynced() { +@mixin sUnSynced { $c: $colorPausedBg; border: 1px solid $c; } diff --git a/src/styles/_legacy.scss b/src/styles/_legacy.scss index 310a71dd92..bb45728fcb 100644 --- a/src/styles/_legacy.scss +++ b/src/styles/_legacy.scss @@ -19,6 +19,9 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ + +@use 'sass:math'; + /*********************************************************************** CLOCKS AND TIMERS */ .c-clock, .c-timer { @@ -788,7 +791,7 @@ body.desktop { //width: $splitterHandleD; } &.flush-right { - width: ceil($splitterHandleD / 2); + width: ceil(math.div($splitterHandleD, 2)); &:after { width: $splitterHandleD; left: auto; right: 0; diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss index e84d5e6f94..4bb4b61776 100644 --- a/src/styles/_mixins.scss +++ b/src/styles/_mixins.scss @@ -20,6 +20,8 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ +@use 'sass:math'; + /************************** GLYPHS */ @mixin glyphBefore($unicode, $family: 'symbolsfont') { &:before { @@ -202,7 +204,7 @@ @mixin bgCheckerboard($c: $colorBodyFg, $opacity: 0.3, $size: 32px, $imp: false) { $color: rgba($c, $opacity); - $bgPos: floor($size / 2); + $bgPos: floor(math.div($size, 2)); $impStr: null; @if $imp { @@ -288,7 +290,7 @@ @mixin triangle($dir: "left", $size: 5px, $ratio: 1, $color: red) { width: 0; height: 0; - $slopedB: $size/$ratio solid transparent; + $slopedB: math.div($size, $ratio) solid transparent; $straightB: $size solid $color; @if $dir == "up" { border-left: $slopedB; @@ -780,7 +782,7 @@ } -@mixin sUnsynced() { +@mixin sUnsynced { $c: $colorPausedBg; border: 1px solid $c; } diff --git a/src/ui/components/toggle-switch.scss b/src/ui/components/toggle-switch.scss index 5ec9f0ef34..9feb46f0c9 100644 --- a/src/ui/components/toggle-switch.scss +++ b/src/ui/components/toggle-switch.scss @@ -1,7 +1,9 @@ +@use 'sass:math'; + .c-toggle-switch { $d: 12px; $m: 2px; - $br: $d/1.5; + $br: math.div($d, 1.5); cursor: pointer; display: inline-flex; align-items: center; diff --git a/src/ui/layout/mct-tree.scss b/src/ui/layout/mct-tree.scss index 30efad598a..95c900a833 100644 --- a/src/ui/layout/mct-tree.scss +++ b/src/ui/layout/mct-tree.scss @@ -1,3 +1,5 @@ +@use 'sass:math'; + .c-tree-and-search { display: flex; flex-direction: column; @@ -136,7 +138,7 @@ } > * + * { - margin-left: ceil($interiorMarginSm / 2); + margin-left: ceil(math.div($interiorMarginSm, 2)); } @include hover { diff --git a/src/ui/layout/pane.scss b/src/ui/layout/pane.scss index fdcb0913e3..b830f24aec 100644 --- a/src/ui/layout/pane.scss +++ b/src/ui/layout/pane.scss @@ -1,3 +1,5 @@ +@use 'sass:math'; + /**************************** BASE - MOBILE AND DESKTOP */ .l-multipane { display: flex; @@ -234,7 +236,7 @@ > .l-pane__handle { left: 0; - transform: translateX(floor($splitterHandleD / -2)); // Center over the pane edge + transform: translateX(floor(math.div($splitterHandleD, -2))); // Center over the pane edge } [class*="expand-button"] { @@ -251,7 +253,7 @@ > .l-pane__handle { right: 0; - transform: translateX(floor($splitterHandleD / 2)); + transform: translateX(floor(math.div($splitterHandleD, 2))); } [class*="expand-button"] { @@ -287,7 +289,7 @@ padding-top: $m; > .l-pane__handle { top: 0; - transform: translateY(floor($splitterHandleD / -1)); + transform: translateY(floor(math.div($splitterHandleD, -1))); } .l-pane__collapse-button:before { @@ -306,7 +308,7 @@ &[class*="-after"] { > .l-pane__handle { bottom: 0; - transform: translateY(floor($splitterHandleD / 1)); + transform: translateY(floor(math.div($splitterHandleD, 1))); } &:not(.l-pane--collapsed) > .l-pane__collapse-button { diff --git a/webpack.config.js b/webpack.common.js similarity index 74% rename from webpack.config.js rename to webpack.common.js index 49982c92fa..87bbc9c061 100644 --- a/webpack.config.js +++ b/webpack.common.js @@ -1,25 +1,18 @@ const path = require('path'); const packageDefinition = require('./package.json'); - -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CopyWebpackPlugin = require('copy-webpack-plugin'); const webpack = require('webpack'); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const devMode = process.env.NODE_ENV !== 'production'; const VueLoaderPlugin = require('vue-loader/lib/plugin'); -// TODO: Build Constants w/ git-rev-sync const gitRevision = require('child_process') .execSync('git rev-parse HEAD') .toString().trim(); const gitBranch = require('child_process') .execSync('git rev-parse --abbrev-ref HEAD') .toString().trim(); -const vueFile = devMode - ? path.join(__dirname, "node_modules/vue/dist/vue.js") - : path.join(__dirname, "node_modules/vue/dist/vue.min.js"); -const webpackConfig = { - mode: devMode ? 'development' : 'production', +module.exports = { entry: { openmct: './openmct.js', couchDBChangesFeed: './src/plugins/persistence/couch/CouchChangesFeed.js', @@ -33,7 +26,8 @@ const webpackConfig = { filename: '[name].js', library: '[name]', libraryTarget: 'umd', - path: path.resolve(__dirname, 'dist') + publicPath: '', + clean: true }, resolve: { alias: { @@ -45,7 +39,6 @@ const webpackConfig = { "bourbon": "bourbon.scss", "plotly-basic": "plotly.js-basic-dist", "plotly-gl2d": "plotly.js-gl2d-dist", - "vue": vueFile, "d3-scale": path.join(__dirname, "node_modules/d3-scale/build/d3-scale.min.js"), "printj": path.join(__dirname, "node_modules/printj/dist/printj.min.js"), "styles": path.join(__dirname, "src/styles"), @@ -55,32 +48,32 @@ const webpackConfig = { "utils": path.join(__dirname, "src/utils") } }, - devtool: devMode ? 'eval-source-map' : 'source-map', plugins: [ new webpack.DefinePlugin({ __OPENMCT_VERSION__: `'${packageDefinition.version}'`, __OPENMCT_BUILD_DATE__: `'${new Date()}'`, __OPENMCT_REVISION__: `'${gitRevision}'`, - __OPENMCT_BUILD_BRANCH__: `'${gitBranch}'`, - __OPENMCT_ROOT_RELATIVE__: `'${devMode ? 'dist/' : ''}'` + __OPENMCT_BUILD_BRANCH__: `'${gitBranch}'` }), new VueLoaderPlugin(), + new CopyWebpackPlugin({ + patterns: [ + { + from: 'src/images/favicons', + to: 'favicons' + }, + { + from: './index.html', + transform: function (content) { + return content.toString().replace(/dist\//g, ''); + } + } + ] + }), new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename: '[name].css' - }), - new CopyWebpackPlugin([ - { - from: 'src/images/favicons', - to: 'favicons' - }, - { - from: './index.html', - transform: function (content) { - return content.toString().replace(/dist\//g, ''); - } - } - ]) + }) ], module: { rules: [ @@ -88,10 +81,17 @@ const webpackConfig = { test: /\.(sc|sa|c)ss$/, use: [ MiniCssExtractPlugin.loader, - 'css-loader', - 'fast-sass-loader' + { + loader: 'css-loader' + }, + 'resolve-url-loader', + 'sass-loader' ] }, + { + test: /\.vue$/, + use: 'vue-loader' + }, { test: /\.html$/, use: 'html-loader' @@ -104,7 +104,7 @@ const webpackConfig = { ] }, { - test: /\.(jpg|jpeg|png|svg|ico|woff2?|eot|ttf)$/, + test: /\.(jpg|jpeg|png|svg|ico|woff|woff2?|eot|ttf)$/, loader: 'file-loader', options: { name: '[name].[ext]', @@ -117,26 +117,15 @@ const webpackConfig = { return `icons/${url}`; } - if (/\.(woff2?|eot|ttf)$/.test(url)) { + if (/\.(woff|woff2?|eot|ttf)$/.test(url)) { return `fonts/${url}`; } else { return `${url}`; } } } - }, - { - test: /\.vue$/, - use: 'vue-loader' } ] }, - stats: { - modules: false, - timings: true, - colors: true, - warningsFilter: /asset size limit/g - } + stats: 'detailed' }; - -module.exports = webpackConfig; diff --git a/webpack.dev.js b/webpack.dev.js new file mode 100644 index 0000000000..21262682f4 --- /dev/null +++ b/webpack.dev.js @@ -0,0 +1,20 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common'); + +const path = require('path'); +const webpack = require('webpack'); + +module.exports = merge(common, { + mode: 'development', + resolve: { + alias: { + "vue": path.join(__dirname, "node_modules/vue/dist/vue.js") + } + }, + plugins: [ + new webpack.DefinePlugin({ + __OPENMCT_ROOT_RELATIVE__: '"dist/"' + }) + ], + devtool: 'eval-source-map' +}); diff --git a/webpack.prod.js b/webpack.prod.js new file mode 100644 index 0000000000..a64d4ce548 --- /dev/null +++ b/webpack.prod.js @@ -0,0 +1,20 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.common'); + +const path = require('path'); +const webpack = require('webpack'); + +module.exports = merge(common, { + mode: 'production', + resolve: { + alias: { + "vue": path.join(__dirname, "node_modules/vue/dist/vue.min.js") + } + }, + plugins: [ + new webpack.DefinePlugin({ + __OPENMCT_ROOT_RELATIVE__: '""' + }) + ], + devtool: 'source-map' +});