From ebff6778ca5e83845d83e0cf755247fe04a60b18 Mon Sep 17 00:00:00 2001
From: liuzhe-lz <40699903+liuzhe-lz@users.noreply.github.com>
Date: Wed, 7 Aug 2019 13:56:43 +0800
Subject: [PATCH 01/10] Eject from react-scripts-ts-antd and bump webui
dependencies version (#1412)
* Eject from react-scripts-ts-antd
* test whether it can pass CI without ugilfy
* temporarily disable uglify
---
Makefile | 2 +-
src/webui/config/env.js | 96 +
src/webui/config/jest/cssTransform.js | 14 +
src/webui/config/jest/fileTransform.js | 12 +
src/webui/config/jest/typescriptTransform.js | 7 +
src/webui/config/loaders.js | 226 +
src/webui/config/paths.js | 58 +
src/webui/config/polyfills.js | 22 +
src/webui/config/webpack.config.dev.js | 207 +
src/webui/config/webpack.config.prod.js | 246 +
src/webui/config/webpackDevServer.config.js | 95 +
src/webui/package.json | 89 +-
src/webui/scripts/build.js | 150 +
src/webui/scripts/start.js | 116 +
src/webui/src/index.tsx | 16 +-
src/webui/tsconfig.json | 12 +-
src/webui/yarn.lock | 6347 ++++++++----------
17 files changed, 4039 insertions(+), 3676 deletions(-)
create mode 100644 src/webui/config/env.js
create mode 100644 src/webui/config/jest/cssTransform.js
create mode 100644 src/webui/config/jest/fileTransform.js
create mode 100644 src/webui/config/jest/typescriptTransform.js
create mode 100644 src/webui/config/loaders.js
create mode 100644 src/webui/config/paths.js
create mode 100644 src/webui/config/polyfills.js
create mode 100644 src/webui/config/webpack.config.dev.js
create mode 100644 src/webui/config/webpack.config.prod.js
create mode 100644 src/webui/config/webpackDevServer.config.js
create mode 100644 src/webui/scripts/build.js
create mode 100644 src/webui/scripts/start.js
diff --git a/Makefile b/Makefile
index 9217c83dba..8877e5c2ae 100644
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,7 @@ NNI_NODE_FOLDER = $(NNI_DEPENDENCY_FOLDER)/nni-node-$(OS_SPEC)-x64
NNI_NODE ?= $(BIN_FOLDER)/node
NNI_YARN_TARBALL ?= $(NNI_DEPENDENCY_FOLDER)/nni-yarn.tar.gz
NNI_YARN_FOLDER ?= $(NNI_DEPENDENCY_FOLDER)/nni-yarn
-NNI_YARN := PATH=$(BIN_FOLDER):$${PATH} $(NNI_YARN_FOLDER)/bin/yarn
+NNI_YARN ?= PATH=$(BIN_FOLDER):$${PATH} $(NNI_YARN_FOLDER)/bin/yarn
## Version number
NNI_VERSION_VALUE = $(shell git describe --tags)
diff --git a/src/webui/config/env.js b/src/webui/config/env.js
new file mode 100644
index 0000000000..7a31c25cb2
--- /dev/null
+++ b/src/webui/config/env.js
@@ -0,0 +1,96 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const paths = require('./paths');
+
+// Make sure that including paths.js after env.js will read .env variables.
+delete require.cache[require.resolve('./paths')];
+
+const NODE_ENV = process.env.NODE_ENV;
+if (!NODE_ENV) {
+ throw new Error(
+ 'The NODE_ENV environment variable is required but was not specified.'
+ );
+}
+
+// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
+var dotenvFiles = [
+ `${paths.dotenv}.${NODE_ENV}.local`,
+ `${paths.dotenv}.${NODE_ENV}`,
+ // Don't include `.env.local` for `test` environment
+ // since normally you expect tests to produce the same
+ // results for everyone
+ NODE_ENV !== 'test' && `${paths.dotenv}.local`,
+ paths.dotenv,
+].filter(Boolean);
+
+// Load environment variables from .env* files. Suppress warnings using silent
+// if this file is missing. dotenv will never modify any environment variables
+// that have already been set. Variable expansion is supported in .env files.
+// https://github.com/motdotla/dotenv
+// https://github.com/motdotla/dotenv-expand
+dotenvFiles.forEach(dotenvFile => {
+ if (fs.existsSync(dotenvFile)) {
+ require('dotenv-expand')(
+ require('dotenv').config({
+ path: dotenvFile,
+ })
+ );
+ }
+});
+
+// We support resolving modules according to `NODE_PATH`.
+// This lets you use absolute paths in imports inside large monorepos:
+// https://github.com/facebookincubator/create-react-app/issues/253.
+// It works similar to `NODE_PATH` in Node itself:
+// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
+// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
+// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
+// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
+// We also resolve them to make sure all tools using them work consistently.
+const appDirectory = fs.realpathSync(process.cwd());
+process.env.NODE_PATH = (process.env.NODE_PATH || '')
+ .split(path.delimiter)
+ .filter(folder => folder && !path.isAbsolute(folder))
+ .map(folder => path.resolve(appDirectory, folder))
+ .join(path.delimiter);
+
+// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
+// injected into the application via DefinePlugin in Webpack configuration.
+const REACT_APP = /^REACT_APP_/i;
+
+function getClientEnvironment(publicUrl) {
+ const raw = Object.keys(process.env)
+ .filter(key => REACT_APP.test(key))
+ .reduce(
+ (env, key) => {
+ env[key] = process.env[key];
+ return env;
+ },
+ {
+ // Useful for determining whether we’re running in production mode.
+ // Most importantly, it switches React into the correct mode.
+ NODE_ENV: process.env.NODE_ENV || 'development',
+ // Useful for resolving the correct path to static assets in `public`.
+ // For example, .
+ // This should only be used as an escape hatch. Normally you would put
+ // images into the `src` and `import` them in code to get their paths.
+ PUBLIC_URL: publicUrl,
+ }
+ );
+ // Stringify all values so we can feed into Webpack DefinePlugin
+ const stringified = {
+ 'process.env': Object.keys(raw).reduce(
+ (env, key) => {
+ env[key] = JSON.stringify(raw[key]);
+ return env;
+ },
+ {}
+ ),
+ };
+
+ return { raw, stringified };
+}
+
+module.exports = getClientEnvironment;
diff --git a/src/webui/config/jest/cssTransform.js b/src/webui/config/jest/cssTransform.js
new file mode 100644
index 0000000000..8f65114812
--- /dev/null
+++ b/src/webui/config/jest/cssTransform.js
@@ -0,0 +1,14 @@
+'use strict';
+
+// This is a custom Jest transformer turning style imports into empty objects.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+ process() {
+ return 'module.exports = {};';
+ },
+ getCacheKey() {
+ // The output is always the same.
+ return 'cssTransform';
+ },
+};
diff --git a/src/webui/config/jest/fileTransform.js b/src/webui/config/jest/fileTransform.js
new file mode 100644
index 0000000000..9e4047d358
--- /dev/null
+++ b/src/webui/config/jest/fileTransform.js
@@ -0,0 +1,12 @@
+'use strict';
+
+const path = require('path');
+
+// This is a custom Jest transformer turning file imports into filenames.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+ process(src, filename) {
+ return `module.exports = ${JSON.stringify(path.basename(filename))};`;
+ },
+};
diff --git a/src/webui/config/jest/typescriptTransform.js b/src/webui/config/jest/typescriptTransform.js
new file mode 100644
index 0000000000..9b138ac8ec
--- /dev/null
+++ b/src/webui/config/jest/typescriptTransform.js
@@ -0,0 +1,7 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+'use strict';
+
+const tsJestPreprocessor = require('ts-jest/preprocessor');
+
+module.exports = tsJestPreprocessor;
diff --git a/src/webui/config/loaders.js b/src/webui/config/loaders.js
new file mode 100644
index 0000000000..75dbdadafe
--- /dev/null
+++ b/src/webui/config/loaders.js
@@ -0,0 +1,226 @@
+const paths = require('./paths');
+const tsImportPluginFactory = require('ts-import-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+const autoprefixer = require('autoprefixer')
+
+const precss = require('precss')();
+const flexBugFixes = require('postcss-flexbugs-fixes')();
+
+// Webpack uses `publicPath` to determine where the app is being served from.
+// It requires a trailing slash, or the file assets will get an incorrect path.
+const publicPath = paths.servedPath;
+// Some apps do not use client-side routing with pushState.
+// For these, "homepage" can be set to "." to enable relative asset paths.
+const shouldUseRelativeAssetPaths = publicPath === './';
+// Source maps are resource heavy and can cause out of memory issue for large source files.
+const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
+
+// Note: defined here because it will be used more than once.
+const cssFilename = 'static/css/[name].[contenthash:8].css';
+
+// ExtractTextPlugin expects the build output to be flat.
+// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
+// However, our output is structured with css, js and media folders.
+// To have this structure working with relative paths, we have to use custom options.
+const extractTextPluginOptions = shouldUseRelativeAssetPaths
+ ? // Making sure that the publicPath goes back to to build folder.
+ { publicPath: Array(cssFilename.split('/').length).join('../') }
+ : {};
+
+
+// "url" loader works like "file" loader except that it embeds assets
+// smaller than specified limit in bytes as data URLs to avoid requests.
+// A missing `test` is equivalent to a match.
+const urlLoader = {
+ test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
+ loader: require.resolve('url-loader'),
+ options: {
+ limit: 10000,
+ name: 'static/media/[name].[hash:8].[ext]',
+ },
+};
+
+const importPluginOption = [
+ {
+ libraryName: 'antd',
+ libraryDirectory: 'lib',
+ style: 'css'
+ },
+ {
+ libraryName: 'antd-mobile',
+ libraryDirectory: 'lib',
+ style: 'css',
+ }
+];
+
+// js loader
+const jsLoader = {
+ test: /\.(js|jsx|mjs)$/,
+ include: paths.appSrc,
+ loader: require.resolve('babel-loader'),
+ options: {
+
+ compact: true,
+ },
+};
+
+
+// ts loader
+const tsLoader = {
+ test: /\.(ts|tsx)$/,
+ include: paths.appSrc,
+ use: [
+ {
+ loader: require.resolve('ts-loader'),
+ options: {
+ transpileOnly: true,
+ getCustomTransformers: () => ({
+ before: [tsImportPluginFactory(importPluginOption)]
+ })
+ }
+ }
+ ]
+};
+
+const postcssLoader = {
+ loader: require.resolve('postcss-loader'),
+ options: {
+ // Necessary for external CSS imports to work
+ // https://github.com/facebookincubator/create-react-app/issues/2677
+ // don't need now
+ // ident: 'postcss',
+ plugins: () => [
+ flexBugFixes,
+ autoprefixer
+ ],
+ },
+};
+
+const precssLoader = {
+ loader: require.resolve('postcss-loader'),
+ options: {
+ // Necessary for external CSS imports to work
+ // https://github.com/facebookincubator/create-react-app/issues/2677
+ // don't need now
+ // ident: 'postcss',
+ plugins: () => [
+ precss,
+ flexBugFixes,
+ autoprefixer
+ ],
+ },
+};
+
+const rawCssLoaderDev = {
+ loader: require.resolve('css-loader'),
+ options: {
+ importLoaders: 1,
+ },
+};
+
+const rawCssLoaderProd = {
+ loader: require.resolve('css-loader'),
+ options: {
+ importLoaders: 1,
+ minimize: true,
+ sourceMap: shouldUseSourceMap,
+ },
+};
+
+const cssLoaderDev = {
+ test: /\.css$/,
+ use: [
+ require.resolve('style-loader'),
+ rawCssLoaderDev,
+ postcssLoader,
+ ],
+};
+
+const cssLoaderProd = {
+ test: /\.css$/,
+ use: [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: { } // TODO
+ },
+ rawCssLoaderProd,
+ postcssLoader,
+ ],
+};
+
+// scss loader
+const scssLoaderDev = {
+ test: /\.scss$/,
+ use: [
+ require.resolve('style-loader'),
+ rawCssLoaderDev,
+ precssLoader,
+ ],
+};
+
+const scssLoaderProd = {
+ test: /\.scss$/,
+ use: [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: { }
+ },
+ rawCssLoaderProd,
+ precssLoader,
+ ]
+};
+
+// less loader
+const lessLoaderDev = {
+ test: /\.less$/,
+ use: [
+ require.resolve('style-loader'),
+ rawCssLoaderDev,
+ postcssLoader,
+ require.resolve('less-loader')
+ ],
+};
+
+const lessLoaderProd = {
+ test: /\.less$/,
+ use: [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: { }
+ },
+ rawCssLoaderProd,
+ postcssLoader,
+ require.resolve('less-loader')
+ ],
+}
+
+// Exclude `js` files to keep "css" loader working as it injects
+// it's runtime that would otherwise processed through "file" loader.
+// Also exclude `html` and `json` extensions so they get processed
+// by webpacks internal loaders.
+const fileLoader = {
+ loader: require.resolve('file-loader'),
+ // Exclude `js` files to keep "css" loader working as it injects
+ // it's runtime that would otherwise processed through "file" loader.
+ // Also exclude `html` and `json` extensions so they get processed
+ // by webpacks internal loaders.
+ exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
+ options: {
+ name: 'static/media/[name].[hash:8].[ext]',
+ },
+};
+
+module.exports = {
+ urlLoader,
+ jsLoader,
+ tsLoader,
+ cssLoaderDev,
+ cssLoaderProd,
+ scssLoaderDev,
+ scssLoaderProd,
+ lessLoaderDev,
+ lessLoaderProd,
+ fileLoader,
+ postcssLoader
+};
diff --git a/src/webui/config/paths.js b/src/webui/config/paths.js
new file mode 100644
index 0000000000..2b280e3cf1
--- /dev/null
+++ b/src/webui/config/paths.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const path = require('path');
+const fs = require('fs');
+const url = require('url');
+
+// Make sure any symlinks in the project folder are resolved:
+// https://github.com/facebookincubator/create-react-app/issues/637
+const appDirectory = fs.realpathSync(process.cwd());
+const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
+
+const envPublicUrl = process.env.PUBLIC_URL;
+
+function ensureSlash(path, needsSlash) {
+ const hasSlash = path.endsWith('/');
+ if (hasSlash && !needsSlash) {
+ return path.substr(path, path.length - 1);
+ } else if (!hasSlash && needsSlash) {
+ return `${path}/`;
+ } else {
+ return path;
+ }
+}
+
+const getPublicUrl = appPackageJson =>
+ envPublicUrl || require(appPackageJson).homepage;
+
+// We use `PUBLIC_URL` environment variable or "homepage" field to infer
+// "public path" at which the app is served.
+// Webpack needs to know it to put the right