@@ -0,0 +1,104 @@ | |||
'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 | |||
const dotenvFiles = [ | |||
`${paths.dotenv}.${NODE_ENV}.local`, | |||
// 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}.${NODE_ENV}`, | |||
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/facebook/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/facebook/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, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />. | |||
// 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, | |||
// We support configuring the sockjs pathname during development. | |||
// These settings let a developer run multiple simultaneous projects. | |||
// They are used as the connection `hostname`, `pathname` and `port` | |||
// in webpackHotDevClient. They are used as the `sockHost`, `sockPath` | |||
// and `sockPort` options in webpack-dev-server. | |||
WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST, | |||
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH, | |||
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT, | |||
// Whether or not react-refresh is enabled. | |||
// It is defined here so it is available in the webpackHotDevClient. | |||
FAST_REFRESH: process.env.FAST_REFRESH !== 'false', | |||
} | |||
); | |||
// 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; |
@@ -0,0 +1,66 @@ | |||
'use strict'; | |||
const fs = require('fs'); | |||
const path = require('path'); | |||
const crypto = require('crypto'); | |||
const chalk = require('react-dev-utils/chalk'); | |||
const paths = require('./paths'); | |||
// Ensure the certificate and key provided are valid and if not | |||
// throw an easy to debug error | |||
function validateKeyAndCerts({ cert, key, keyFile, crtFile }) { | |||
let encrypted; | |||
try { | |||
// publicEncrypt will throw an error with an invalid cert | |||
encrypted = crypto.publicEncrypt(cert, Buffer.from('test')); | |||
} catch (err) { | |||
throw new Error( | |||
`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}` | |||
); | |||
} | |||
try { | |||
// privateDecrypt will throw an error with an invalid key | |||
crypto.privateDecrypt(key, encrypted); | |||
} catch (err) { | |||
throw new Error( | |||
`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${ | |||
err.message | |||
}` | |||
); | |||
} | |||
} | |||
// Read file and throw an error if it doesn't exist | |||
function readEnvFile(file, type) { | |||
if (!fs.existsSync(file)) { | |||
throw new Error( | |||
`You specified ${chalk.cyan( | |||
type | |||
)} in your env, but the file "${chalk.yellow(file)}" can't be found.` | |||
); | |||
} | |||
return fs.readFileSync(file); | |||
} | |||
// Get the https config | |||
// Return cert files if provided in env, otherwise just true or false | |||
function getHttpsConfig() { | |||
const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env; | |||
const isHttps = HTTPS === 'true'; | |||
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) { | |||
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE); | |||
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE); | |||
const config = { | |||
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'), | |||
key: readEnvFile(keyFile, 'SSL_KEY_FILE'), | |||
}; | |||
validateKeyAndCerts({ ...config, keyFile, crtFile }); | |||
return config; | |||
} | |||
return isHttps; | |||
} | |||
module.exports = getHttpsConfig; |
@@ -0,0 +1,29 @@ | |||
'use strict'; | |||
const babelJest = require('babel-jest').default; | |||
const hasJsxRuntime = (() => { | |||
if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { | |||
return false; | |||
} | |||
try { | |||
require.resolve('react/jsx-runtime'); | |||
return true; | |||
} catch (e) { | |||
return false; | |||
} | |||
})(); | |||
module.exports = babelJest.createTransformer({ | |||
presets: [ | |||
[ | |||
require.resolve('babel-preset-react-app'), | |||
{ | |||
runtime: hasJsxRuntime ? 'automatic' : 'classic', | |||
}, | |||
], | |||
], | |||
babelrc: false, | |||
configFile: false, | |||
}); |
@@ -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'; | |||
}, | |||
}; |
@@ -0,0 +1,40 @@ | |||
'use strict'; | |||
const path = require('path'); | |||
const camelcase = require('camelcase'); | |||
// 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) { | |||
const assetFilename = JSON.stringify(path.basename(filename)); | |||
if (filename.match(/\.svg$/)) { | |||
// Based on how SVGR generates a component name: | |||
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 | |||
const pascalCaseFilename = camelcase(path.parse(filename).name, { | |||
pascalCase: true, | |||
}); | |||
const componentName = `Svg${pascalCaseFilename}`; | |||
return `const React = require('react'); | |||
module.exports = { | |||
__esModule: true, | |||
default: ${assetFilename}, | |||
ReactComponent: React.forwardRef(function ${componentName}(props, ref) { | |||
return { | |||
$$typeof: Symbol.for('react.element'), | |||
type: 'svg', | |||
ref: ref, | |||
key: null, | |||
props: Object.assign({}, props, { | |||
children: ${assetFilename} | |||
}) | |||
}; | |||
}), | |||
};`; | |||
} | |||
return `module.exports = ${assetFilename};`; | |||
}, | |||
}; |
@@ -0,0 +1,134 @@ | |||
'use strict'; | |||
const fs = require('fs'); | |||
const path = require('path'); | |||
const paths = require('./paths'); | |||
const chalk = require('react-dev-utils/chalk'); | |||
const resolve = require('resolve'); | |||
/** | |||
* Get additional module paths based on the baseUrl of a compilerOptions object. | |||
* | |||
* @param {Object} options | |||
*/ | |||
function getAdditionalModulePaths(options = {}) { | |||
const baseUrl = options.baseUrl; | |||
if (!baseUrl) { | |||
return ''; | |||
} | |||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl); | |||
// We don't need to do anything if `baseUrl` is set to `node_modules`. This is | |||
// the default behavior. | |||
if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { | |||
return null; | |||
} | |||
// Allow the user set the `baseUrl` to `appSrc`. | |||
if (path.relative(paths.appSrc, baseUrlResolved) === '') { | |||
return [paths.appSrc]; | |||
} | |||
// If the path is equal to the root directory we ignore it here. | |||
// We don't want to allow importing from the root directly as source files are | |||
// not transpiled outside of `src`. We do allow importing them with the | |||
// absolute path (e.g. `src/Components/Button.js`) but we set that up with | |||
// an alias. | |||
if (path.relative(paths.appPath, baseUrlResolved) === '') { | |||
return null; | |||
} | |||
// Otherwise, throw an error. | |||
throw new Error( | |||
chalk.red.bold( | |||
"Your project's `baseUrl` can only be set to `src` or `node_modules`." + | |||
' Create React App does not support other values at this time.' | |||
) | |||
); | |||
} | |||
/** | |||
* Get webpack aliases based on the baseUrl of a compilerOptions object. | |||
* | |||
* @param {*} options | |||
*/ | |||
function getWebpackAliases(options = {}) { | |||
const baseUrl = options.baseUrl; | |||
if (!baseUrl) { | |||
return {}; | |||
} | |||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl); | |||
if (path.relative(paths.appPath, baseUrlResolved) === '') { | |||
return { | |||
src: paths.appSrc, | |||
}; | |||
} | |||
} | |||
/** | |||
* Get jest aliases based on the baseUrl of a compilerOptions object. | |||
* | |||
* @param {*} options | |||
*/ | |||
function getJestAliases(options = {}) { | |||
const baseUrl = options.baseUrl; | |||
if (!baseUrl) { | |||
return {}; | |||
} | |||
const baseUrlResolved = path.resolve(paths.appPath, baseUrl); | |||
if (path.relative(paths.appPath, baseUrlResolved) === '') { | |||
return { | |||
'^src/(.*)$': '<rootDir>/src/$1', | |||
}; | |||
} | |||
} | |||
function getModules() { | |||
// Check if TypeScript is setup | |||
const hasTsConfig = fs.existsSync(paths.appTsConfig); | |||
const hasJsConfig = fs.existsSync(paths.appJsConfig); | |||
if (hasTsConfig && hasJsConfig) { | |||
throw new Error( | |||
'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' | |||
); | |||
} | |||
let config; | |||
// If there's a tsconfig.json we assume it's a | |||
// TypeScript project and set up the config | |||
// based on tsconfig.json | |||
if (hasTsConfig) { | |||
const ts = require(resolve.sync('typescript', { | |||
basedir: paths.appNodeModules, | |||
})); | |||
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; | |||
// Otherwise we'll check if there is jsconfig.json | |||
// for non TS projects. | |||
} else if (hasJsConfig) { | |||
config = require(paths.appJsConfig); | |||
} | |||
config = config || {}; | |||
const options = config.compilerOptions || {}; | |||
const additionalModulePaths = getAdditionalModulePaths(options); | |||
return { | |||
additionalModulePaths: additionalModulePaths, | |||
webpackAliases: getWebpackAliases(options), | |||
jestAliases: getJestAliases(options), | |||
hasTsConfig, | |||
}; | |||
} | |||
module.exports = getModules(); |
@@ -0,0 +1,77 @@ | |||
'use strict'; | |||
const path = require('path'); | |||
const fs = require('fs'); | |||
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); | |||
// Make sure any symlinks in the project folder are resolved: | |||
// https://github.com/facebook/create-react-app/issues/637 | |||
const appDirectory = fs.realpathSync(process.cwd()); | |||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath); | |||
// 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 <script> hrefs into HTML even in | |||
// single-page apps that may serve index.html for nested URLs like /todos/42. | |||
// We can't use a relative path in HTML because we don't want to load something | |||
// like /todos/42/static/js/bundle.7289d.js. We have to know the root. | |||
const publicUrlOrPath = getPublicUrlOrPath( | |||
process.env.NODE_ENV === 'development', | |||
require(resolveApp('package.json')).homepage, | |||
process.env.PUBLIC_URL | |||
); | |||
const buildPath = process.env.BUILD_PATH || 'build'; | |||
const moduleFileExtensions = [ | |||
'web.mjs', | |||
'mjs', | |||
'web.js', | |||
'js', | |||
'web.ts', | |||
'ts', | |||
'web.tsx', | |||
'tsx', | |||
'json', | |||
'web.jsx', | |||
'jsx', | |||
]; | |||
// Resolve file paths in the same order as webpack | |||
const resolveModule = (resolveFn, filePath) => { | |||
const extension = moduleFileExtensions.find(extension => | |||
fs.existsSync(resolveFn(`${filePath}.${extension}`)) | |||
); | |||
if (extension) { | |||
return resolveFn(`${filePath}.${extension}`); | |||
} | |||
return resolveFn(`${filePath}.js`); | |||
}; | |||
// config after eject: we're in ./config/ | |||
module.exports = { | |||
dotenv: resolveApp('.env'), | |||
appPath: resolveApp('.'), | |||
appBuild: resolveApp(buildPath), | |||
appPublic: resolveApp('public'), | |||
appHtml: resolveApp('public/index.html'), | |||
appIndexJs: resolveModule(resolveApp, 'src/index'), | |||
appPackageJson: resolveApp('package.json'), | |||
appSrc: resolveApp('src'), | |||
appTsConfig: resolveApp('tsconfig.json'), | |||
appJsConfig: resolveApp('jsconfig.json'), | |||
yarnLockFile: resolveApp('yarn.lock'), | |||
testsSetup: resolveModule(resolveApp, 'src/setupTests'), | |||
proxySetup: resolveApp('src/setupProxy.js'), | |||
appNodeModules: resolveApp('node_modules'), | |||
appWebpackCache: resolveApp('node_modules/.cache'), | |||
appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'), | |||
swSrc: resolveModule(resolveApp, 'src/service-worker'), | |||
publicUrlOrPath, | |||
}; | |||
module.exports.moduleFileExtensions = moduleFileExtensions; |
@@ -0,0 +1,758 @@ | |||
"use strict"; | |||
const fs = require("fs"); | |||
const path = require("path"); | |||
const webpack = require("webpack"); | |||
const resolve = require("resolve"); | |||
const HtmlWebpackPlugin = require("html-webpack-plugin"); | |||
const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin"); | |||
const InlineChunkHtmlPlugin = require("react-dev-utils/InlineChunkHtmlPlugin"); | |||
const TerserPlugin = require("terser-webpack-plugin"); | |||
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); | |||
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); | |||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin"); | |||
const InterpolateHtmlPlugin = require("react-dev-utils/InterpolateHtmlPlugin"); | |||
const WorkboxWebpackPlugin = require("workbox-webpack-plugin"); | |||
const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin"); | |||
const getCSSModuleLocalIdent = require("react-dev-utils/getCSSModuleLocalIdent"); | |||
const ESLintPlugin = require("eslint-webpack-plugin"); | |||
const paths = require("./paths"); | |||
const modules = require("./modules"); | |||
const getClientEnvironment = require("./env"); | |||
const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin"); | |||
const ForkTsCheckerWebpackPlugin = | |||
process.env.TSC_COMPILE_ON_ERROR === "true" | |||
? require("react-dev-utils/ForkTsCheckerWarningWebpackPlugin") | |||
: require("react-dev-utils/ForkTsCheckerWebpackPlugin"); | |||
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"); | |||
const createEnvironmentHash = require("./webpack/persistentCache/createEnvironmentHash"); | |||
// Source maps are resource heavy and can cause out of memory issue for large source files. | |||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false"; | |||
const reactRefreshRuntimeEntry = require.resolve("react-refresh/runtime"); | |||
const reactRefreshWebpackPluginRuntimeEntry = require.resolve( | |||
"@pmmmwh/react-refresh-webpack-plugin" | |||
); | |||
const babelRuntimeEntry = require.resolve("babel-preset-react-app"); | |||
const babelRuntimeEntryHelpers = require.resolve( | |||
"@babel/runtime/helpers/esm/assertThisInitialized", | |||
{ paths: [babelRuntimeEntry] } | |||
); | |||
const babelRuntimeRegenerator = require.resolve("@babel/runtime/regenerator", { | |||
paths: [babelRuntimeEntry], | |||
}); | |||
// Some apps do not need the benefits of saving a web request, so not inlining the chunk | |||
// makes for a smoother build process. | |||
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== "false"; | |||
const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === "true"; | |||
const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === "true"; | |||
const imageInlineSizeLimit = parseInt( | |||
process.env.IMAGE_INLINE_SIZE_LIMIT || "10000" | |||
); | |||
// Check if TypeScript is setup | |||
const useTypeScript = fs.existsSync(paths.appTsConfig); | |||
// Check if Tailwind config exists | |||
const useTailwind = fs.existsSync( | |||
path.join(paths.appPath, "tailwind.config.js") | |||
); | |||
// Get the path to the uncompiled service worker (if it exists). | |||
const swSrc = paths.swSrc; | |||
// style files regexes | |||
const cssRegex = /\.css$/; | |||
const cssModuleRegex = /\.module\.css$/; | |||
const sassRegex = /\.(scss|sass)$/; | |||
const sassModuleRegex = /\.module\.(scss|sass)$/; | |||
const lessRegex = /\.(less)$/; | |||
const lessModuleRegex = /\.module\.(less)$/; | |||
const hasJsxRuntime = (() => { | |||
if (process.env.DISABLE_NEW_JSX_TRANSFORM === "true") { | |||
return false; | |||
} | |||
try { | |||
require.resolve("react/jsx-runtime"); | |||
return true; | |||
} catch (e) { | |||
return false; | |||
} | |||
})(); | |||
// This is the production and development configuration. | |||
// It is focused on developer experience, fast rebuilds, and a minimal bundle. | |||
module.exports = function (webpackEnv) { | |||
const isEnvDevelopment = webpackEnv === "development"; | |||
const isEnvProduction = webpackEnv === "production"; | |||
// Variable used for enabling profiling in Production | |||
// passed into alias object. Uses a flag if passed into the build command | |||
const isEnvProductionProfile = | |||
isEnvProduction && process.argv.includes("--profile"); | |||
// We will provide `paths.publicUrlOrPath` to our app | |||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. | |||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. | |||
// Get environment variables to inject into our app. | |||
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); | |||
const shouldUseReactRefresh = env.raw.FAST_REFRESH; | |||
// common function to get style loaders | |||
const getStyleLoaders = (cssOptions, preProcessor) => { | |||
const loaders = [ | |||
isEnvDevelopment && require.resolve("style-loader"), | |||
isEnvProduction && { | |||
loader: MiniCssExtractPlugin.loader, | |||
// css is located in `static/css`, use '../../' to locate index.html folder | |||
// in production `paths.publicUrlOrPath` can be a relative path | |||
options: paths.publicUrlOrPath.startsWith(".") | |||
? { publicPath: "../../" } | |||
: {}, | |||
}, | |||
{ | |||
loader: require.resolve("css-loader"), | |||
options: cssOptions, | |||
}, | |||
{ | |||
// Options for PostCSS as we reference these options twice | |||
// Adds vendor prefixing based on your specified browser support in | |||
// package.json | |||
loader: require.resolve("postcss-loader"), | |||
options: { | |||
postcssOptions: { | |||
// Necessary for external CSS imports to work | |||
// https://github.com/facebook/create-react-app/issues/2677 | |||
ident: "postcss", | |||
config: false, | |||
plugins: !useTailwind | |||
? [ | |||
"postcss-flexbugs-fixes", | |||
[ | |||
"postcss-preset-env", | |||
{ | |||
autoprefixer: { | |||
flexbox: "no-2009", | |||
}, | |||
stage: 3, | |||
}, | |||
], | |||
// Adds PostCSS Normalize as the reset css with default options, | |||
// so that it honors browserslist config in package.json | |||
// which in turn let's users customize the target behavior as per their needs. | |||
"postcss-normalize", | |||
] | |||
: [ | |||
"tailwindcss", | |||
"postcss-flexbugs-fixes", | |||
[ | |||
"postcss-preset-env", | |||
{ | |||
autoprefixer: { | |||
flexbox: "no-2009", | |||
}, | |||
stage: 3, | |||
}, | |||
], | |||
], | |||
}, | |||
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, | |||
}, | |||
}, | |||
].filter(Boolean); | |||
if (preProcessor) { | |||
loaders.push( | |||
{ | |||
loader: require.resolve("resolve-url-loader"), | |||
options: { | |||
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, | |||
root: paths.appSrc, | |||
}, | |||
}, | |||
{ | |||
loader: require.resolve(preProcessor), | |||
options: { | |||
sourceMap: true, | |||
}, | |||
} | |||
); | |||
} | |||
return loaders; | |||
}; | |||
return { | |||
target: ["browserslist"], | |||
// Webpack noise constrained to errors and warnings | |||
stats: "errors-warnings", | |||
mode: isEnvProduction ? "production" : isEnvDevelopment && "development", | |||
// Stop compilation early in production | |||
bail: isEnvProduction, | |||
devtool: isEnvProduction | |||
? shouldUseSourceMap | |||
? "source-map" | |||
: false | |||
: isEnvDevelopment && "cheap-module-source-map", | |||
// These are the "entry points" to our application. | |||
// This means they will be the "root" imports that are included in JS bundle. | |||
entry: paths.appIndexJs, | |||
output: { | |||
// The build folder. | |||
path: paths.appBuild, | |||
// Add /* filename */ comments to generated require()s in the output. | |||
pathinfo: isEnvDevelopment, | |||
// There will be one main bundle, and one file per asynchronous chunk. | |||
// In development, it does not produce real files. | |||
filename: isEnvProduction | |||
? "static/js/[name].[contenthash:8].js" | |||
: isEnvDevelopment && "static/js/bundle.js", | |||
// There are also additional JS chunk files if you use code splitting. | |||
chunkFilename: isEnvProduction | |||
? "static/js/[name].[contenthash:8].chunk.js" | |||
: isEnvDevelopment && "static/js/[name].chunk.js", | |||
assetModuleFilename: "static/media/[name].[hash][ext]", | |||
// 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. | |||
// We inferred the "public path" (such as / or /my-project) from homepage. | |||
publicPath: paths.publicUrlOrPath, | |||
// Point sourcemap entries to original disk location (format as URL on Windows) | |||
devtoolModuleFilenameTemplate: isEnvProduction | |||
? (info) => | |||
path | |||
.relative(paths.appSrc, info.absoluteResourcePath) | |||
.replace(/\\/g, "/") | |||
: isEnvDevelopment && | |||
((info) => | |||
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")), | |||
}, | |||
cache: { | |||
type: "filesystem", | |||
version: createEnvironmentHash(env.raw), | |||
cacheDirectory: paths.appWebpackCache, | |||
store: "pack", | |||
buildDependencies: { | |||
defaultWebpack: ["webpack/lib/"], | |||
config: [__filename], | |||
tsconfig: [paths.appTsConfig, paths.appJsConfig].filter((f) => | |||
fs.existsSync(f) | |||
), | |||
}, | |||
}, | |||
infrastructureLogging: { | |||
level: "none", | |||
}, | |||
optimization: { | |||
minimize: isEnvProduction, | |||
minimizer: [ | |||
// This is only used in production mode | |||
new TerserPlugin({ | |||
terserOptions: { | |||
parse: { | |||
// We want terser to parse ecma 8 code. However, we don't want it | |||
// to apply any minification steps that turns valid ecma 5 code | |||
// into invalid ecma 5 code. This is why the 'compress' and 'output' | |||
// sections only apply transformations that are ecma 5 safe | |||
// https://github.com/facebook/create-react-app/pull/4234 | |||
ecma: 8, | |||
}, | |||
compress: { | |||
ecma: 5, | |||
warnings: false, | |||
// Disabled because of an issue with Uglify breaking seemingly valid code: | |||
// https://github.com/facebook/create-react-app/issues/2376 | |||
// Pending further investigation: | |||
// https://github.com/mishoo/UglifyJS2/issues/2011 | |||
comparisons: false, | |||
// Disabled because of an issue with Terser breaking valid code: | |||
// https://github.com/facebook/create-react-app/issues/5250 | |||
// Pending further investigation: | |||
// https://github.com/terser-js/terser/issues/120 | |||
inline: 2, | |||
}, | |||
mangle: { | |||
safari10: true, | |||
}, | |||
// Added for profiling in devtools | |||
keep_classnames: isEnvProductionProfile, | |||
keep_fnames: isEnvProductionProfile, | |||
output: { | |||
ecma: 5, | |||
comments: false, | |||
// Turned on because emoji and regex is not minified properly using default | |||
// https://github.com/facebook/create-react-app/issues/2488 | |||
ascii_only: true, | |||
}, | |||
}, | |||
}), | |||
// This is only used in production mode | |||
new CssMinimizerPlugin(), | |||
], | |||
}, | |||
resolve: { | |||
// This allows you to set a fallback for where webpack should look for modules. | |||
// We placed these paths second because we want `node_modules` to "win" | |||
// if there are any conflicts. This matches Node resolution mechanism. | |||
// https://github.com/facebook/create-react-app/issues/253 | |||
modules: ["node_modules", paths.appNodeModules].concat( | |||
modules.additionalModulePaths || [] | |||
), | |||
// These are the reasonable defaults supported by the Node ecosystem. | |||
// We also include JSX as a common component filename extension to support | |||
// some tools, although we do not recommend using it, see: | |||
// https://github.com/facebook/create-react-app/issues/290 | |||
// `web` extension prefixes have been added for better support | |||
// for React Native Web. | |||
extensions: paths.moduleFileExtensions | |||
.map((ext) => `.${ext}`) | |||
.filter((ext) => useTypeScript || !ext.includes("ts")), | |||
alias: { | |||
// Support React Native Web | |||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ | |||
"react-native": "react-native-web", | |||
// Allows for better profiling with ReactDevTools | |||
...(isEnvProductionProfile && { | |||
"react-dom$": "react-dom/profiling", | |||
"scheduler/tracing": "scheduler/tracing-profiling", | |||
}), | |||
...(modules.webpackAliases || {}), | |||
}, | |||
plugins: [ | |||
// Prevents users from importing files from outside of src/ (or node_modules/). | |||
// This often causes confusion because we only process files within src/ with babel. | |||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to, | |||
// please link the files into your node_modules/ and let module-resolution kick in. | |||
// Make sure your source files are compiled, as they will not be processed in any way. | |||
new ModuleScopePlugin(paths.appSrc, [ | |||
paths.appPackageJson, | |||
reactRefreshRuntimeEntry, | |||
reactRefreshWebpackPluginRuntimeEntry, | |||
babelRuntimeEntry, | |||
babelRuntimeEntryHelpers, | |||
babelRuntimeRegenerator, | |||
]), | |||
], | |||
}, | |||
module: { | |||
strictExportPresence: true, | |||
rules: [ | |||
// Handle node_modules packages that contain sourcemaps | |||
shouldUseSourceMap && { | |||
enforce: "pre", | |||
exclude: /@babel(?:\/|\\{1,2})runtime/, | |||
test: /\.(js|mjs|jsx|ts|tsx|css)$/, | |||
loader: require.resolve("source-map-loader"), | |||
}, | |||
{ | |||
// "oneOf" will traverse all following loaders until one will | |||
// match the requirements. When no loader matches it will fall | |||
// back to the "file" loader at the end of the loader list. | |||
oneOf: [ | |||
// TODO: Merge this config once `image/avif` is in the mime-db | |||
// https://github.com/jshttp/mime-db | |||
{ | |||
test: [/\.avif$/], | |||
type: "asset", | |||
mimetype: "image/avif", | |||
parser: { | |||
dataUrlCondition: { | |||
maxSize: imageInlineSizeLimit, | |||
}, | |||
}, | |||
}, | |||
// "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. | |||
{ | |||
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], | |||
type: "asset", | |||
parser: { | |||
dataUrlCondition: { | |||
maxSize: imageInlineSizeLimit, | |||
}, | |||
}, | |||
}, | |||
{ | |||
test: /\.svg$/, | |||
use: [ | |||
{ | |||
loader: require.resolve("@svgr/webpack"), | |||
options: { | |||
prettier: false, | |||
svgo: false, | |||
svgoConfig: { | |||
plugins: [{ removeViewBox: false }], | |||
}, | |||
titleProp: true, | |||
ref: true, | |||
}, | |||
}, | |||
{ | |||
loader: require.resolve("file-loader"), | |||
options: { | |||
name: "static/media/[name].[hash].[ext]", | |||
}, | |||
}, | |||
], | |||
issuer: { | |||
and: [/\.(ts|tsx|js|jsx|md|mdx)$/], | |||
}, | |||
}, | |||
// Process application JS with Babel. | |||
// The preset includes JSX, Flow, TypeScript, and some ESnext features. | |||
{ | |||
test: /\.(js|mjs|jsx|ts|tsx)$/, | |||
include: paths.appSrc, | |||
loader: require.resolve("babel-loader"), | |||
options: { | |||
customize: require.resolve( | |||
"babel-preset-react-app/webpack-overrides" | |||
), | |||
presets: [ | |||
[ | |||
require.resolve("babel-preset-react-app"), | |||
{ | |||
runtime: hasJsxRuntime ? "automatic" : "classic", | |||
}, | |||
], | |||
], | |||
plugins: [ | |||
isEnvDevelopment && | |||
shouldUseReactRefresh && | |||
require.resolve("react-refresh/babel"), | |||
].filter(Boolean), | |||
// This is a feature of `babel-loader` for webpack (not Babel itself). | |||
// It enables caching results in ./node_modules/.cache/babel-loader/ | |||
// directory for faster rebuilds. | |||
cacheDirectory: true, | |||
// See #6846 for context on why cacheCompression is disabled | |||
cacheCompression: false, | |||
compact: isEnvProduction, | |||
}, | |||
}, | |||
// Process any JS outside of the app with Babel. | |||
// Unlike the application JS, we only compile the standard ES features. | |||
{ | |||
test: /\.(js|mjs)$/, | |||
exclude: /@babel(?:\/|\\{1,2})runtime/, | |||
loader: require.resolve("babel-loader"), | |||
options: { | |||
babelrc: false, | |||
configFile: false, | |||
compact: false, | |||
presets: [ | |||
[ | |||
require.resolve("babel-preset-react-app/dependencies"), | |||
{ helpers: true }, | |||
], | |||
], | |||
cacheDirectory: true, | |||
// See #6846 for context on why cacheCompression is disabled | |||
cacheCompression: false, | |||
// Babel sourcemaps are needed for debugging into node_modules | |||
// code. Without the options below, debuggers like VSCode | |||
// show incorrect code and set breakpoints on the wrong lines. | |||
sourceMaps: shouldUseSourceMap, | |||
inputSourceMap: shouldUseSourceMap, | |||
}, | |||
}, | |||
// "postcss" loader applies autoprefixer to our CSS. | |||
// "css" loader resolves paths in CSS and adds assets as dependencies. | |||
// "style" loader turns CSS into JS modules that inject <style> tags. | |||
// In production, we use MiniCSSExtractPlugin to extract that CSS | |||
// to a file, but in development "style" loader enables hot editing | |||
// of CSS. | |||
// By default we support CSS Modules with the extension .module.css | |||
{ | |||
test: cssRegex, | |||
exclude: cssModuleRegex, | |||
use: getStyleLoaders({ | |||
importLoaders: 1, | |||
sourceMap: isEnvProduction | |||
? shouldUseSourceMap | |||
: isEnvDevelopment, | |||
modules: { | |||
mode: "icss", | |||
}, | |||
}), | |||
// Don't consider CSS imports dead code even if the | |||
// containing package claims to have no side effects. | |||
// Remove this when webpack adds a warning or an error for this. | |||
// See https://github.com/webpack/webpack/issues/6571 | |||
sideEffects: true, | |||
}, | |||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules) | |||
// using the extension .module.css | |||
{ | |||
test: cssModuleRegex, | |||
use: getStyleLoaders({ | |||
importLoaders: 1, | |||
sourceMap: isEnvProduction | |||
? shouldUseSourceMap | |||
: isEnvDevelopment, | |||
modules: { | |||
mode: "local", | |||
getLocalIdent: getCSSModuleLocalIdent, | |||
}, | |||
}), | |||
}, | |||
// Opt-in support for SASS (using .scss or .sass extensions). | |||
// By default we support SASS Modules with the | |||
// extensions .module.scss or .module.sass | |||
{ | |||
test: sassRegex, | |||
exclude: sassModuleRegex, | |||
use: getStyleLoaders( | |||
{ | |||
importLoaders: 3, | |||
sourceMap: isEnvProduction | |||
? shouldUseSourceMap | |||
: isEnvDevelopment, | |||
modules: { | |||
mode: "icss", | |||
}, | |||
}, | |||
"sass-loader" | |||
), | |||
// Don't consider CSS imports dead code even if the | |||
// containing package claims to have no side effects. | |||
// Remove this when webpack adds a warning or an error for this. | |||
// See https://github.com/webpack/webpack/issues/6571 | |||
sideEffects: true, | |||
}, | |||
// Adds support for CSS Modules, but using SASS | |||
// using the extension .module.scss or .module.sass | |||
{ | |||
test: sassModuleRegex, | |||
use: getStyleLoaders( | |||
{ | |||
importLoaders: 3, | |||
sourceMap: isEnvProduction | |||
? shouldUseSourceMap | |||
: isEnvDevelopment, | |||
modules: { | |||
mode: "local", | |||
getLocalIdent: getCSSModuleLocalIdent, | |||
}, | |||
}, | |||
"sass-loader" | |||
), | |||
}, | |||
// "file" loader makes sure those assets get served by WebpackDevServer. | |||
// When you `import` an asset, you get its (virtual) filename. | |||
// In production, they would get copied to the `build` folder. | |||
// This loader doesn't use a "test" so it will catch all modules | |||
// that fall through the other loaders. | |||
{ | |||
// Exclude `js` files to keep "css" loader working as it injects | |||
// its runtime that would otherwise be processed through "file" loader. | |||
// Also exclude `html` and `json` extensions so they get processed | |||
// by webpacks internal loaders. | |||
exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], | |||
type: "asset/resource", | |||
}, | |||
// ** STOP ** Are you adding a new loader? | |||
// Make sure to add the new loader(s) before the "file" loader. | |||
], | |||
}, | |||
].filter(Boolean), | |||
}, | |||
plugins: [ | |||
// Generates an `index.html` file with the <script> injected. | |||
new HtmlWebpackPlugin( | |||
Object.assign( | |||
{}, | |||
{ | |||
inject: true, | |||
template: paths.appHtml, | |||
}, | |||
isEnvProduction | |||
? { | |||
minify: { | |||
removeComments: true, | |||
collapseWhitespace: true, | |||
removeRedundantAttributes: true, | |||
useShortDoctype: true, | |||
removeEmptyAttributes: true, | |||
removeStyleLinkTypeAttributes: true, | |||
keepClosingSlash: true, | |||
minifyJS: true, | |||
minifyCSS: true, | |||
minifyURLs: true, | |||
}, | |||
} | |||
: undefined | |||
) | |||
), | |||
// Inlines the webpack runtime script. This script is too small to warrant | |||
// a network request. | |||
// https://github.com/facebook/create-react-app/issues/5358 | |||
isEnvProduction && | |||
shouldInlineRuntimeChunk && | |||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]), | |||
// Makes some environment variables available in index.html. | |||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.: | |||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico"> | |||
// It will be an empty string unless you specify "homepage" | |||
// in `package.json`, in which case it will be the pathname of that URL. | |||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), | |||
// This gives some necessary context to module not found errors, such as | |||
// the requesting resource. | |||
new ModuleNotFoundPlugin(paths.appPath), | |||
// Makes some environment variables available to the JS code, for example: | |||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. | |||
// It is absolutely essential that NODE_ENV is set to production | |||
// during a production build. | |||
// Otherwise React will be compiled in the very slow development mode. | |||
new webpack.DefinePlugin(env.stringified), | |||
// Experimental hot reloading for React . | |||
// https://github.com/facebook/react/tree/main/packages/react-refresh | |||
isEnvDevelopment && | |||
shouldUseReactRefresh && | |||
new ReactRefreshWebpackPlugin({ | |||
overlay: false, | |||
}), | |||
// Watcher doesn't work well if you mistype casing in a path so we use | |||
// a plugin that prints an error when you attempt to do this. | |||
// See https://github.com/facebook/create-react-app/issues/240 | |||
isEnvDevelopment && new CaseSensitivePathsPlugin(), | |||
isEnvProduction && | |||
new MiniCssExtractPlugin({ | |||
// Options similar to the same options in webpackOptions.output | |||
// both options are optional | |||
filename: "static/css/[name].[contenthash:8].css", | |||
chunkFilename: "static/css/[name].[contenthash:8].chunk.css", | |||
}), | |||
// Generate an asset manifest file with the following content: | |||
// - "files" key: Mapping of all asset filenames to their corresponding | |||
// output file so that tools can pick it up without having to parse | |||
// `index.html` | |||
// - "entrypoints" key: Array of files which are included in `index.html`, | |||
// can be used to reconstruct the HTML if necessary | |||
new WebpackManifestPlugin({ | |||
fileName: "asset-manifest.json", | |||
publicPath: paths.publicUrlOrPath, | |||
generate: (seed, files, entrypoints) => { | |||
const manifestFiles = files.reduce((manifest, file) => { | |||
manifest[file.name] = file.path; | |||
return manifest; | |||
}, seed); | |||
const entrypointFiles = entrypoints.main.filter( | |||
(fileName) => !fileName.endsWith(".map") | |||
); | |||
return { | |||
files: manifestFiles, | |||
entrypoints: entrypointFiles, | |||
}; | |||
}, | |||
}), | |||
// Moment.js is an extremely popular library that bundles large locale files | |||
// by default due to how webpack interprets its code. This is a practical | |||
// solution that requires the user to opt into importing specific locales. | |||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack | |||
// You can remove this if you don't use Moment.js: | |||
new webpack.IgnorePlugin({ | |||
resourceRegExp: /^\.\/locale$/, | |||
contextRegExp: /moment$/, | |||
}), | |||
// Generate a service worker script that will precache, and keep up to date, | |||
// the HTML & assets that are part of the webpack build. | |||
isEnvProduction && | |||
fs.existsSync(swSrc) && | |||
new WorkboxWebpackPlugin.InjectManifest({ | |||
swSrc, | |||
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./, | |||
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/], | |||
// Bump up the default maximum size (2mb) that's precached, | |||
// to make lazy-loading failure scenarios less likely. | |||
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270 | |||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, | |||
}), | |||
// TypeScript type checking | |||
useTypeScript && | |||
new ForkTsCheckerWebpackPlugin({ | |||
async: isEnvDevelopment, | |||
typescript: { | |||
typescriptPath: resolve.sync("typescript", { | |||
basedir: paths.appNodeModules, | |||
}), | |||
configOverwrite: { | |||
compilerOptions: { | |||
sourceMap: isEnvProduction | |||
? shouldUseSourceMap | |||
: isEnvDevelopment, | |||
skipLibCheck: true, | |||
inlineSourceMap: false, | |||
declarationMap: false, | |||
noEmit: true, | |||
incremental: true, | |||
tsBuildInfoFile: paths.appTsBuildInfoFile, | |||
}, | |||
}, | |||
context: paths.appPath, | |||
diagnosticOptions: { | |||
syntactic: true, | |||
}, | |||
mode: "write-references", | |||
// profile: true, | |||
}, | |||
issue: { | |||
// This one is specifically to match during CI tests, | |||
// as micromatch doesn't match | |||
// '../cra-template-typescript/template/src/App.tsx' | |||
// otherwise. | |||
include: [ | |||
{ file: "../**/src/**/*.{ts,tsx}" }, | |||
{ file: "**/src/**/*.{ts,tsx}" }, | |||
], | |||
exclude: [ | |||
{ file: "**/src/**/__tests__/**" }, | |||
{ file: "**/src/**/?(*.){spec|test}.*" }, | |||
{ file: "**/src/setupProxy.*" }, | |||
{ file: "**/src/setupTests.*" }, | |||
], | |||
}, | |||
logger: { | |||
infrastructure: "silent", | |||
}, | |||
}), | |||
!disableESLintPlugin && | |||
new ESLintPlugin({ | |||
// Plugin options | |||
extensions: ["js", "mjs", "jsx", "ts", "tsx"], | |||
formatter: require.resolve("react-dev-utils/eslintFormatter"), | |||
eslintPath: require.resolve("eslint"), | |||
failOnError: !(isEnvDevelopment && emitErrorsAsWarnings), | |||
context: paths.appSrc, | |||
cache: true, | |||
cacheLocation: path.resolve( | |||
paths.appNodeModules, | |||
".cache/.eslintcache" | |||
), | |||
// ESLint class options | |||
cwd: paths.appPath, | |||
resolvePluginsRelativeTo: __dirname, | |||
baseConfig: { | |||
extends: [require.resolve("eslint-config-react-app/base")], | |||
rules: { | |||
...(!hasJsxRuntime && { | |||
"react/react-in-jsx-scope": "error", | |||
}), | |||
}, | |||
}, | |||
}), | |||
].filter(Boolean), | |||
// Turn off performance processing because we utilize | |||
// our own hints via the FileSizeReporter | |||
performance: false, | |||
}; | |||
}; |
@@ -0,0 +1,9 @@ | |||
'use strict'; | |||
const { createHash } = require('crypto'); | |||
module.exports = env => { | |||
const hash = createHash('md5'); | |||
hash.update(JSON.stringify(env)); | |||
return hash.digest('hex'); | |||
}; |
@@ -0,0 +1,127 @@ | |||
'use strict'; | |||
const fs = require('fs'); | |||
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware'); | |||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware'); | |||
const ignoredFiles = require('react-dev-utils/ignoredFiles'); | |||
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware'); | |||
const paths = require('./paths'); | |||
const getHttpsConfig = require('./getHttpsConfig'); | |||
const host = process.env.HOST || '0.0.0.0'; | |||
const sockHost = process.env.WDS_SOCKET_HOST; | |||
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/ws' | |||
const sockPort = process.env.WDS_SOCKET_PORT; | |||
module.exports = function (proxy, allowedHost) { | |||
const disableFirewall = | |||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true'; | |||
return { | |||
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote | |||
// websites from potentially accessing local content through DNS rebinding: | |||
// https://github.com/webpack/webpack-dev-server/issues/887 | |||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a | |||
// However, it made several existing use cases such as development in cloud | |||
// environment or subdomains in development significantly more complicated: | |||
// https://github.com/facebook/create-react-app/issues/2271 | |||
// https://github.com/facebook/create-react-app/issues/2233 | |||
// While we're investigating better solutions, for now we will take a | |||
// compromise. Since our WDS configuration only serves files in the `public` | |||
// folder we won't consider accessing them a vulnerability. However, if you | |||
// use the `proxy` feature, it gets more dangerous because it can expose | |||
// remote code execution vulnerabilities in backends like Django and Rails. | |||
// So we will disable the host check normally, but enable it if you have | |||
// specified the `proxy` setting. Finally, we let you override it if you | |||
// really know what you're doing with a special environment variable. | |||
// Note: ["localhost", ".localhost"] will support subdomains - but we might | |||
// want to allow setting the allowedHosts manually for more complex setups | |||
allowedHosts: disableFirewall ? 'all' : [allowedHost], | |||
headers: { | |||
'Access-Control-Allow-Origin': '*', | |||
'Access-Control-Allow-Methods': '*', | |||
'Access-Control-Allow-Headers': '*', | |||
}, | |||
// Enable gzip compression of generated files. | |||
compress: true, | |||
static: { | |||
// By default WebpackDevServer serves physical files from current directory | |||
// in addition to all the virtual build products that it serves from memory. | |||
// This is confusing because those files won’t automatically be available in | |||
// production build folder unless we copy them. However, copying the whole | |||
// project directory is dangerous because we may expose sensitive files. | |||
// Instead, we establish a convention that only files in `public` directory | |||
// get served. Our build script will copy `public` into the `build` folder. | |||
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%: | |||
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico"> | |||
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`. | |||
// Note that we only recommend to use `public` folder as an escape hatch | |||
// for files like `favicon.ico`, `manifest.json`, and libraries that are | |||
// for some reason broken when imported through webpack. If you just want to | |||
// use an image, put it in `src` and `import` it from JavaScript instead. | |||
directory: paths.appPublic, | |||
publicPath: [paths.publicUrlOrPath], | |||
// By default files from `contentBase` will not trigger a page reload. | |||
watch: { | |||
// Reportedly, this avoids CPU overload on some systems. | |||
// https://github.com/facebook/create-react-app/issues/293 | |||
// src/node_modules is not ignored to support absolute imports | |||
// https://github.com/facebook/create-react-app/issues/1065 | |||
ignored: ignoredFiles(paths.appSrc), | |||
}, | |||
}, | |||
client: { | |||
webSocketURL: { | |||
// Enable custom sockjs pathname for websocket connection to hot reloading server. | |||
// Enable custom sockjs hostname, pathname and port for websocket connection | |||
// to hot reloading server. | |||
hostname: sockHost, | |||
pathname: sockPath, | |||
port: sockPort, | |||
}, | |||
overlay: { | |||
errors: true, | |||
warnings: false, | |||
}, | |||
}, | |||
devMiddleware: { | |||
// It is important to tell WebpackDevServer to use the same "publicPath" path as | |||
// we specified in the webpack config. When homepage is '.', default to serving | |||
// from the root. | |||
// remove last slash so user can land on `/test` instead of `/test/` | |||
publicPath: paths.publicUrlOrPath.slice(0, -1), | |||
}, | |||
https: getHttpsConfig(), | |||
host, | |||
historyApiFallback: { | |||
// Paths with dots should still use the history fallback. | |||
// See https://github.com/facebook/create-react-app/issues/387. | |||
disableDotRule: true, | |||
index: paths.publicUrlOrPath, | |||
}, | |||
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks | |||
proxy, | |||
onBeforeSetupMiddleware(devServer) { | |||
// Keep `evalSourceMapMiddleware` | |||
// middlewares before `redirectServedPath` otherwise will not have any effect | |||
// This lets us fetch source contents from webpack for the error overlay | |||
devServer.app.use(evalSourceMapMiddleware(devServer)); | |||
if (fs.existsSync(paths.proxySetup)) { | |||
// This registers user provided middleware for proxy reasons | |||
require(paths.proxySetup)(devServer.app); | |||
} | |||
}, | |||
onAfterSetupMiddleware(devServer) { | |||
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match | |||
devServer.app.use(redirectServedPath(paths.publicUrlOrPath)); | |||
// This service worker file is effectively a 'no-op' that will reset any | |||
// previous service worker registered for the same host:port combination. | |||
// We do this in development to avoid hitting the production cache if | |||
// it used the same host and port. | |||
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432 | |||
devServer.app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath)); | |||
}, | |||
}; | |||
}; |
@@ -3,24 +3,70 @@ | |||
"version": "0.1.0", | |||
"private": true, | |||
"dependencies": { | |||
"@babel/core": "^7.16.0", | |||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", | |||
"@reduxjs/toolkit": "^1.9.7", | |||
"@svgr/webpack": "^5.5.0", | |||
"@testing-library/jest-dom": "^5.17.0", | |||
"@testing-library/react": "^13.4.0", | |||
"@testing-library/user-event": "^14.5.1", | |||
"antd": "^4.20.6", | |||
"antd": "^5.11.0", | |||
"babel-jest": "^27.4.2", | |||
"babel-loader": "^8.2.3", | |||
"babel-plugin-named-asset-import": "^0.3.8", | |||
"babel-preset-react-app": "^10.0.1", | |||
"bfj": "^7.0.2", | |||
"browserslist": "^4.18.1", | |||
"camelcase": "^6.2.1", | |||
"case-sensitive-paths-webpack-plugin": "^2.4.0", | |||
"css-loader": "^6.5.1", | |||
"css-minimizer-webpack-plugin": "^3.2.0", | |||
"dotenv": "^10.0.0", | |||
"dotenv-expand": "^5.1.0", | |||
"echarts": "^5.4.3", | |||
"echarts-for-react": "^3.0.2", | |||
"eslint": "^8.3.0", | |||
"eslint-config-react-app": "^7.0.1", | |||
"eslint-webpack-plugin": "^3.1.1", | |||
"file-loader": "^6.2.0", | |||
"framer-motion": "^10.16.4", | |||
"fs-extra": "^10.0.0", | |||
"html-webpack-plugin": "^5.5.0", | |||
"identity-obj-proxy": "^3.0.0", | |||
"jest": "^27.4.3", | |||
"jest-resolve": "^27.4.2", | |||
"jest-watch-typeahead": "^1.0.0", | |||
"mini-css-extract-plugin": "^2.4.5", | |||
"postcss": "^8.4.4", | |||
"postcss-flexbugs-fixes": "^5.0.2", | |||
"postcss-loader": "^6.2.1", | |||
"postcss-normalize": "^10.0.1", | |||
"postcss-preset-env": "^7.0.1", | |||
"prompts": "^2.4.2", | |||
"react": "^18.2.0", | |||
"react-app-polyfill": "^3.0.0", | |||
"react-dev-utils": "^12.0.1", | |||
"react-dom": "^18.2.0", | |||
"react-redux": "^8.1.3", | |||
"react-scripts": "5.0.1" | |||
"react-refresh": "^0.11.0", | |||
"resolve": "^1.20.0", | |||
"resolve-url-loader": "^4.0.0", | |||
"sass": "^1.69.5", | |||
"sass-loader": "^12.3.0", | |||
"semver": "^7.3.5", | |||
"source-map-loader": "^3.0.0", | |||
"style-loader": "^3.3.1", | |||
"tailwindcss": "^3.0.2", | |||
"terser-webpack-plugin": "^5.2.5", | |||
"webpack": "^5.64.4", | |||
"webpack-dev-server": "^4.6.0", | |||
"webpack-manifest-plugin": "^4.0.2", | |||
"workbox-webpack-plugin": "^6.4.1" | |||
}, | |||
"scripts": { | |||
"start": "react-scripts start", | |||
"build": "react-scripts build", | |||
"test": "react-scripts test", | |||
"eject": "react-scripts eject" | |||
"start": "node scripts/start.js", | |||
"build": "node scripts/build.js", | |||
"test": "node scripts/test.js" | |||
}, | |||
"eslintConfig": { | |||
"extends": [ | |||
@@ -44,5 +90,59 @@ | |||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", | |||
"less": "^4.2.0", | |||
"less-loader": "^11.1.3" | |||
}, | |||
"jest": { | |||
"roots": [ | |||
"<rootDir>/src" | |||
], | |||
"collectCoverageFrom": [ | |||
"src/**/*.{js,jsx,ts,tsx}", | |||
"!src/**/*.d.ts" | |||
], | |||
"setupFiles": [ | |||
"react-app-polyfill/jsdom" | |||
], | |||
"setupFilesAfterEnv": [], | |||
"testMatch": [ | |||
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}", | |||
"<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}" | |||
], | |||
"testEnvironment": "jsdom", | |||
"transform": { | |||
"^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/config/jest/babelTransform.js", | |||
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js", | |||
"^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js" | |||
}, | |||
"transformIgnorePatterns": [ | |||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$", | |||
"^.+\\.module\\.(css|sass|scss)$" | |||
], | |||
"modulePaths": [], | |||
"moduleNameMapper": { | |||
"^react-native$": "react-native-web", | |||
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy" | |||
}, | |||
"moduleFileExtensions": [ | |||
"web.js", | |||
"js", | |||
"web.ts", | |||
"ts", | |||
"web.tsx", | |||
"tsx", | |||
"json", | |||
"web.jsx", | |||
"jsx", | |||
"node" | |||
], | |||
"watchPlugins": [ | |||
"jest-watch-typeahead/filename", | |||
"jest-watch-typeahead/testname" | |||
], | |||
"resetMocks": true | |||
}, | |||
"babel": { | |||
"presets": [ | |||
"react-app" | |||
] | |||
} | |||
} |
@@ -0,0 +1,217 @@ | |||
'use strict'; | |||
// Do this as the first thing so that any code reading it knows the right env. | |||
process.env.BABEL_ENV = 'production'; | |||
process.env.NODE_ENV = 'production'; | |||
// Makes the script crash on unhandled rejections instead of silently | |||
// ignoring them. In the future, promise rejections that are not handled will | |||
// terminate the Node.js process with a non-zero exit code. | |||
process.on('unhandledRejection', err => { | |||
throw err; | |||
}); | |||
// Ensure environment variables are read. | |||
require('../config/env'); | |||
const path = require('path'); | |||
const chalk = require('react-dev-utils/chalk'); | |||
const fs = require('fs-extra'); | |||
const bfj = require('bfj'); | |||
const webpack = require('webpack'); | |||
const configFactory = require('../config/webpack.config'); | |||
const paths = require('../config/paths'); | |||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); | |||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); | |||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions'); | |||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter'); | |||
const printBuildError = require('react-dev-utils/printBuildError'); | |||
const measureFileSizesBeforeBuild = | |||
FileSizeReporter.measureFileSizesBeforeBuild; | |||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild; | |||
const useYarn = fs.existsSync(paths.yarnLockFile); | |||
// These sizes are pretty large. We'll warn for bundles exceeding them. | |||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; | |||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; | |||
const isInteractive = process.stdout.isTTY; | |||
// Warn and crash if required files are missing | |||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { | |||
process.exit(1); | |||
} | |||
const argv = process.argv.slice(2); | |||
const writeStatsJson = argv.indexOf('--stats') !== -1; | |||
// Generate configuration | |||
const config = configFactory('production'); | |||
// We require that you explicitly set browsers and do not fall back to | |||
// browserslist defaults. | |||
const { checkBrowsers } = require('react-dev-utils/browsersHelper'); | |||
checkBrowsers(paths.appPath, isInteractive) | |||
.then(() => { | |||
// First, read the current file sizes in build directory. | |||
// This lets us display how much they changed later. | |||
return measureFileSizesBeforeBuild(paths.appBuild); | |||
}) | |||
.then(previousFileSizes => { | |||
// Remove all content but keep the directory so that | |||
// if you're in it, you don't end up in Trash | |||
fs.emptyDirSync(paths.appBuild); | |||
// Merge with the public folder | |||
copyPublicFolder(); | |||
// Start the webpack build | |||
return build(previousFileSizes); | |||
}) | |||
.then( | |||
({ stats, previousFileSizes, warnings }) => { | |||
if (warnings.length) { | |||
console.log(chalk.yellow('Compiled with warnings.\n')); | |||
console.log(warnings.join('\n\n')); | |||
console.log( | |||
'\nSearch for the ' + | |||
chalk.underline(chalk.yellow('keywords')) + | |||
' to learn more about each warning.' | |||
); | |||
console.log( | |||
'To ignore, add ' + | |||
chalk.cyan('// eslint-disable-next-line') + | |||
' to the line before.\n' | |||
); | |||
} else { | |||
console.log(chalk.green('Compiled successfully.\n')); | |||
} | |||
console.log('File sizes after gzip:\n'); | |||
printFileSizesAfterBuild( | |||
stats, | |||
previousFileSizes, | |||
paths.appBuild, | |||
WARN_AFTER_BUNDLE_GZIP_SIZE, | |||
WARN_AFTER_CHUNK_GZIP_SIZE | |||
); | |||
console.log(); | |||
const appPackage = require(paths.appPackageJson); | |||
const publicUrl = paths.publicUrlOrPath; | |||
const publicPath = config.output.publicPath; | |||
const buildFolder = path.relative(process.cwd(), paths.appBuild); | |||
printHostingInstructions( | |||
appPackage, | |||
publicUrl, | |||
publicPath, | |||
buildFolder, | |||
useYarn | |||
); | |||
}, | |||
err => { | |||
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; | |||
if (tscCompileOnError) { | |||
console.log( | |||
chalk.yellow( | |||
'Compiled with the following type errors (you may want to check these before deploying your app):\n' | |||
) | |||
); | |||
printBuildError(err); | |||
} else { | |||
console.log(chalk.red('Failed to compile.\n')); | |||
printBuildError(err); | |||
process.exit(1); | |||
} | |||
} | |||
) | |||
.catch(err => { | |||
if (err && err.message) { | |||
console.log(err.message); | |||
} | |||
process.exit(1); | |||
}); | |||
// Create the production build and print the deployment instructions. | |||
function build(previousFileSizes) { | |||
console.log('Creating an optimized production build...'); | |||
const compiler = webpack(config); | |||
return new Promise((resolve, reject) => { | |||
compiler.run((err, stats) => { | |||
let messages; | |||
if (err) { | |||
if (!err.message) { | |||
return reject(err); | |||
} | |||
let errMessage = err.message; | |||
// Add additional information for postcss errors | |||
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) { | |||
errMessage += | |||
'\nCompileError: Begins at CSS selector ' + | |||
err['postcssNode'].selector; | |||
} | |||
messages = formatWebpackMessages({ | |||
errors: [errMessage], | |||
warnings: [], | |||
}); | |||
} else { | |||
messages = formatWebpackMessages( | |||
stats.toJson({ all: false, warnings: true, errors: true }) | |||
); | |||
} | |||
if (messages.errors.length) { | |||
// Only keep the first error. Others are often indicative | |||
// of the same problem, but confuse the reader with noise. | |||
if (messages.errors.length > 1) { | |||
messages.errors.length = 1; | |||
} | |||
return reject(new Error(messages.errors.join('\n\n'))); | |||
} | |||
if ( | |||
process.env.CI && | |||
(typeof process.env.CI !== 'string' || | |||
process.env.CI.toLowerCase() !== 'false') && | |||
messages.warnings.length | |||
) { | |||
// Ignore sourcemap warnings in CI builds. See #8227 for more info. | |||
const filteredWarnings = messages.warnings.filter( | |||
w => !/Failed to parse source map/.test(w) | |||
); | |||
if (filteredWarnings.length) { | |||
console.log( | |||
chalk.yellow( | |||
'\nTreating warnings as errors because process.env.CI = true.\n' + | |||
'Most CI servers set it automatically.\n' | |||
) | |||
); | |||
return reject(new Error(filteredWarnings.join('\n\n'))); | |||
} | |||
} | |||
const resolveArgs = { | |||
stats, | |||
previousFileSizes, | |||
warnings: messages.warnings, | |||
}; | |||
if (writeStatsJson) { | |||
return bfj | |||
.write(paths.appBuild + '/bundle-stats.json', stats.toJson()) | |||
.then(() => resolve(resolveArgs)) | |||
.catch(error => reject(new Error(error))); | |||
} | |||
return resolve(resolveArgs); | |||
}); | |||
}); | |||
} | |||
function copyPublicFolder() { | |||
fs.copySync(paths.appPublic, paths.appBuild, { | |||
dereference: true, | |||
filter: file => file !== paths.appHtml, | |||
}); | |||
} |
@@ -0,0 +1,154 @@ | |||
'use strict'; | |||
// Do this as the first thing so that any code reading it knows the right env. | |||
process.env.BABEL_ENV = 'development'; | |||
process.env.NODE_ENV = 'development'; | |||
// Makes the script crash on unhandled rejections instead of silently | |||
// ignoring them. In the future, promise rejections that are not handled will | |||
// terminate the Node.js process with a non-zero exit code. | |||
process.on('unhandledRejection', err => { | |||
throw err; | |||
}); | |||
// Ensure environment variables are read. | |||
require('../config/env'); | |||
const fs = require('fs'); | |||
const chalk = require('react-dev-utils/chalk'); | |||
const webpack = require('webpack'); | |||
const WebpackDevServer = require('webpack-dev-server'); | |||
const clearConsole = require('react-dev-utils/clearConsole'); | |||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); | |||
const { | |||
choosePort, | |||
createCompiler, | |||
prepareProxy, | |||
prepareUrls, | |||
} = require('react-dev-utils/WebpackDevServerUtils'); | |||
const openBrowser = require('react-dev-utils/openBrowser'); | |||
const semver = require('semver'); | |||
const paths = require('../config/paths'); | |||
const configFactory = require('../config/webpack.config'); | |||
const createDevServerConfig = require('../config/webpackDevServer.config'); | |||
const getClientEnvironment = require('../config/env'); | |||
const react = require(require.resolve('react', { paths: [paths.appPath] })); | |||
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); | |||
const useYarn = fs.existsSync(paths.yarnLockFile); | |||
const isInteractive = process.stdout.isTTY; | |||
// Warn and crash if required files are missing | |||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { | |||
process.exit(1); | |||
} | |||
// Tools like Cloud9 rely on this. | |||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; | |||
const HOST = process.env.HOST || '0.0.0.0'; | |||
if (process.env.HOST) { | |||
console.log( | |||
chalk.cyan( | |||
`Attempting to bind to HOST environment variable: ${chalk.yellow( | |||
chalk.bold(process.env.HOST) | |||
)}` | |||
) | |||
); | |||
console.log( | |||
`If this was unintentional, check that you haven't mistakenly set it in your shell.` | |||
); | |||
console.log( | |||
`Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}` | |||
); | |||
console.log(); | |||
} | |||
// We require that you explicitly set browsers and do not fall back to | |||
// browserslist defaults. | |||
const { checkBrowsers } = require('react-dev-utils/browsersHelper'); | |||
checkBrowsers(paths.appPath, isInteractive) | |||
.then(() => { | |||
// We attempt to use the default port but if it is busy, we offer the user to | |||
// run on a different port. `choosePort()` Promise resolves to the next free port. | |||
return choosePort(HOST, DEFAULT_PORT); | |||
}) | |||
.then(port => { | |||
if (port == null) { | |||
// We have not found a port. | |||
return; | |||
} | |||
const config = configFactory('development'); | |||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; | |||
const appName = require(paths.appPackageJson).name; | |||
const useTypeScript = fs.existsSync(paths.appTsConfig); | |||
const urls = prepareUrls( | |||
protocol, | |||
HOST, | |||
port, | |||
paths.publicUrlOrPath.slice(0, -1) | |||
); | |||
// Create a webpack compiler that is configured with custom messages. | |||
const compiler = createCompiler({ | |||
appName, | |||
config, | |||
urls, | |||
useYarn, | |||
useTypeScript, | |||
webpack, | |||
}); | |||
// Load proxy config | |||
const proxySetting = require(paths.appPackageJson).proxy; | |||
const proxyConfig = prepareProxy( | |||
proxySetting, | |||
paths.appPublic, | |||
paths.publicUrlOrPath | |||
); | |||
// Serve webpack assets generated by the compiler over a web server. | |||
const serverConfig = { | |||
...createDevServerConfig(proxyConfig, urls.lanUrlForConfig), | |||
host: HOST, | |||
port, | |||
}; | |||
const devServer = new WebpackDevServer(serverConfig, compiler); | |||
// Launch WebpackDevServer. | |||
devServer.startCallback(() => { | |||
if (isInteractive) { | |||
clearConsole(); | |||
} | |||
if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) { | |||
console.log( | |||
chalk.yellow( | |||
`Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.` | |||
) | |||
); | |||
} | |||
console.log(chalk.cyan('Starting the development server...\n')); | |||
openBrowser(urls.localUrlForBrowser); | |||
}); | |||
['SIGINT', 'SIGTERM'].forEach(function (sig) { | |||
process.on(sig, function () { | |||
devServer.close(); | |||
process.exit(); | |||
}); | |||
}); | |||
if (process.env.CI !== 'true') { | |||
// Gracefully exit when stdin ends | |||
process.stdin.on('end', function () { | |||
devServer.close(); | |||
process.exit(); | |||
}); | |||
} | |||
}) | |||
.catch(err => { | |||
if (err && err.message) { | |||
console.log(err.message); | |||
} | |||
process.exit(1); | |||
}); |
@@ -0,0 +1,52 @@ | |||
'use strict'; | |||
// Do this as the first thing so that any code reading it knows the right env. | |||
process.env.BABEL_ENV = 'test'; | |||
process.env.NODE_ENV = 'test'; | |||
process.env.PUBLIC_URL = ''; | |||
// Makes the script crash on unhandled rejections instead of silently | |||
// ignoring them. In the future, promise rejections that are not handled will | |||
// terminate the Node.js process with a non-zero exit code. | |||
process.on('unhandledRejection', err => { | |||
throw err; | |||
}); | |||
// Ensure environment variables are read. | |||
require('../config/env'); | |||
const jest = require('jest'); | |||
const execSync = require('child_process').execSync; | |||
let argv = process.argv.slice(2); | |||
function isInGitRepository() { | |||
try { | |||
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); | |||
return true; | |||
} catch (e) { | |||
return false; | |||
} | |||
} | |||
function isInMercurialRepository() { | |||
try { | |||
execSync('hg --cwd . root', { stdio: 'ignore' }); | |||
return true; | |||
} catch (e) { | |||
return false; | |||
} | |||
} | |||
// Watch unless on CI or explicitly running all tests | |||
if ( | |||
!process.env.CI && | |||
argv.indexOf('--watchAll') === -1 && | |||
argv.indexOf('--watchAll=false') === -1 | |||
) { | |||
// https://github.com/facebook/create-react-app/issues/5210 | |||
const hasSourceControl = isInGitRepository() || isInMercurialRepository(); | |||
argv.push(hasSourceControl ? '--watch' : '--watchAll'); | |||
} | |||
jest.run(argv); |
@@ -1,14 +1,14 @@ | |||
// import "./App.css"; | |||
import "./global.css"; | |||
import "./index.css"; | |||
import Head from "./components/公共组件/顶部公司名称"; | |||
import Head from "./components/Common/Company"; | |||
// import { SocketContextProvider } from "../store/socket-data-provider"; | |||
import useSlider, { Slider } from "./hooks/useSlider"; | |||
import NavMenu from "./components/公共组件/导航菜单"; | |||
import NavMenu from "./components/Common/NavMenu"; | |||
import { useState } from "react"; | |||
import Home from "./pages/总览"; | |||
import EnergyAnalysis from "./pages/能耗分析"; | |||
import RulerContainer from "./components/工具组件/Ruler"; | |||
import Home from "./pages/Home"; | |||
import EnergyAnalysis from "./pages/EnergyCostAnalysis"; | |||
import RulerContainer from "./components/Tools/Ruler"; | |||
import { createPortal } from "react-dom"; | |||
function App() { | |||
@@ -4,7 +4,7 @@ import TopSide from '../../../assets/TopSide.png'; | |||
import LeftLine from '../../../assets/TopTitleLeftIcon.png'; | |||
import RightLine from '../../../assets/TopTitleRightIcon.png'; | |||
import ButtonLine from '../../../assets/TopButtonLine.png'; | |||
import './index.less'; | |||
import './index.scss'; | |||
export default function CompanyName() { | |||
const [now, setNow] = useState('2023.07.01 12:00:00'); |
@@ -45,7 +45,7 @@ | |||
} | |||
} | |||
.TopSiderightLine { | |||
.TopSideRightLine { | |||
background: url('../../../assets/TopTitleRight.png'); | |||
width: 899px; | |||
height: 40px; | |||
@@ -66,7 +66,6 @@ | |||
margin-top: 15px; | |||
color: rgb(255, 255, 255, 0.8); | |||
font-size: 20px; | |||
font-weight: 600px; | |||
line-height: 22.174976px; | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
import BottomBarItem from '../BottomItemBackground'; | |||
import React, { Component } from 'react'; | |||
import './righttable.module.less'; | |||
import './righttable.module.scss'; | |||
// import { ScrollBoard } from '@jiaminghi/data-view-react'; | |||
@@ -1,4 +1,4 @@ | |||
import cls from './index.module.less'; | |||
import cls from './index.module.scss'; | |||
import Container from '../../Container'; | |||
import TechSplitline from '../TechSplitline'; | |||
import EnergyCostChart from './EnergyCostChart'; |
@@ -1,5 +1,5 @@ | |||
import GraphBase from "../../公共组件/GraphBase"; | |||
import "./index.module.less"; | |||
import GraphBase from "../../Common/GraphBase"; | |||
import "./index.module.scss"; | |||
// import { ScrollBoard } from '@jiaminghi/data-view-react'; | |||
@@ -1,9 +1,9 @@ | |||
// 风机运行频率 | |||
// FanRunFrequence | |||
import cls from "./index.module.css"; | |||
import ReactECharts from "echarts-for-react"; | |||
import * as echarts from "echarts"; | |||
import { Switch } from "antd"; | |||
import GraphBase from "../../公共组件/GraphBase"; | |||
import GraphBase from "../../Common/GraphBase"; | |||
import { useState, useContext } from "react"; | |||
// import SocketContext from '../../../store/socket-data-provider'; | |||
@@ -167,7 +167,7 @@ function WindFrequence(props) { | |||
return ( | |||
<GraphBase | |||
icon="kiln" | |||
title="风机运行频率" | |||
title="FanRunFrequence" | |||
size={["middle", "long"]} | |||
switchOptions={true} | |||
switchPosition={[null, 200]} // [top, left] |
@@ -3,7 +3,8 @@ import { useContext } from "react"; | |||
import Container from "../../Container"; | |||
// import SocketContext from '../../../store/socket-data-provider'; | |||
import cls from "./kiln.module.less"; | |||
import cls from "./kiln.module.scss"; | |||
export default function Kiln() { | |||
// const ctx = useContext(SocketContext); | |||
@@ -14,7 +15,10 @@ export default function Kiln() { | |||
{ label: "循环水温度", value: ctx?.runState?.waterTemp || "0℃" }, | |||
{ label: "循环水流量", value: ctx?.runState?.waterFlow || "0㎡/h" }, | |||
{ label: "循环水压力", value: ctx?.runState?.waterPressure || "0Pa" }, | |||
{ label: "助燃风压力", value: ctx?.runState?.combustionAirPressure || "0℃" }, | |||
{ | |||
label: "助燃风压力", | |||
value: ctx?.runState?.combustionAirPressure || "0℃", | |||
}, | |||
{ label: "碹顶加权温度", value: ctx?.runState?.topTemp || "0℃" }, | |||
{ | |||
label: "压缩气压力", |
@@ -1,5 +1,5 @@ | |||
import { useCallback, useState } from 'react'; | |||
import cls from './index.module.less'; | |||
import cls from './index.module.scss'; | |||
export default function CenterMenu({ active, onChangeActive }) { | |||
const menuList = [ |
@@ -1,4 +1,4 @@ | |||
import cls from './index.module.less'; | |||
import cls from './index.module.scss'; | |||
import Container from '../../Container'; | |||
import TechSplitline from '../TechSplitline'; | |||
import SmokeTrendChart from './SmokeTrendChart'; |
@@ -1,4 +1,4 @@ | |||
import cls from './index.module.less'; | |||
import cls from './index.module.scss'; | |||
const TechSplitline = (props) => { | |||
return <div className={cls.techSplitline}></div>; |
@@ -5,7 +5,7 @@ import icon2 from "../../../assets/CenterChart2icon2.svg"; | |||
import icon3 from "../../../assets/CenterChart2icon3.svg"; | |||
import icon4 from "../../../assets/CenterChart2icon4.svg"; | |||
import cls from "./leftbox.module.less"; | |||
import cls from "./leftbox.module.scss"; | |||
const Chart2 = () => { | |||
// const ctx = useContext(SocketContext); |
@@ -1,4 +1,4 @@ | |||
import cls from './good.module.less'; | |||
import cls from './good.module.scss'; | |||
import Container from '../../Container'; | |||
import TodayTableData from './components/TodayTableData'; | |||
import GoodRateChart from './components/GoodRateChart'; |
@@ -1,5 +1,5 @@ | |||
import { useState } from 'react'; | |||
import cls from './index.module.less'; | |||
import cls from './index.module.scss'; | |||
// import { ScrollBoard } from '@jiaminghi/data-view-react'; | |||
const TodayTableData = (props) => { |
@@ -1,6 +1,6 @@ | |||
import { useEffect, useRef } from 'react'; | |||
import useIcon from '../hooks/useIcon'; | |||
import cls from './container.module.less'; | |||
import cls from './container.module.scss'; | |||
const Container = (props) => { | |||
let icon = useIcon(props.icon); | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,5 +1,5 @@ | |||
import cls from './index.module.css'; | |||
import GradientText from '../../../公共组件/GradientText'; | |||
import GradientText from '../../../Common/GradientText'; | |||
function Energy(props) { | |||
return ( |
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||
@@ -1,5 +1,5 @@ | |||
import cls from './index.module.css'; | |||
import GradientText from '../../../公共组件/GradientText'; | |||
import GradientText from '../../../Common/GradientText'; | |||
function SmokeHandle(props) { | |||
return ( |
@@ -1,4 +1,4 @@ | |||
import GraphBase from '../../../公共组件/GraphBase'; | |||
import GraphBase from '../../../Common/GraphBase'; | |||
import ReactECharts from 'echarts-for-react'; | |||
import getOptions from '../../../../hooks/getChartOption'; | |||