Chore: upgrade webpack config

This commit is contained in:
Dreamacro 2020-11-01 20:05:16 +08:00
parent 1384ec6908
commit 68881b8840
14 changed files with 1383 additions and 2516 deletions

View File

@ -1,5 +1,3 @@
'use strict';
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const paths = require('./paths'); const paths = require('./paths');
@ -17,11 +15,11 @@ if (!NODE_ENV) {
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
const dotenvFiles = [ const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`, `${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment // Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same // since normally you expect tests to produce the same
// results for everyone // results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`, NODE_ENV !== 'test' && `${paths.dotenv}.local`,
`${paths.dotenv}.${NODE_ENV}`,
paths.dotenv, paths.dotenv,
].filter(Boolean); ].filter(Boolean);
@ -85,6 +83,11 @@ function getClientEnvironment(publicUrl) {
WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST, WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH, WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT, WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
// Whether or not react-refresh is enabled.
// react-refresh is not 100% stable at this time,
// which is why it's disabled by default.
// 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 // Stringify all values so we can feed into webpack DefinePlugin

View File

@ -1,5 +1,3 @@
'use strict';
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const crypto = require('crypto'); const crypto = require('crypto');

View File

@ -1,5 +1,3 @@
'use strict';
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const paths = require('./paths'); const paths = require('./paths');
@ -14,15 +12,8 @@ const resolve = require('resolve');
function getAdditionalModulePaths(options = {}) { function getAdditionalModulePaths(options = {}) {
const baseUrl = options.baseUrl; const baseUrl = options.baseUrl;
// We need to explicitly check for null and undefined (and not a falsy value) because if (!baseUrl) {
// TypeScript treats an empty string as `.`. return '';
if (baseUrl == null) {
// If there's no baseUrl set we respect NODE_PATH
// Note that NODE_PATH is deprecated and will be removed
// in the next major release of create-react-app.
const nodePath = process.env.NODE_PATH || '';
return nodePath.split(path.delimiter).filter(Boolean);
} }
const baseUrlResolved = path.resolve(paths.appPath, baseUrl); const baseUrlResolved = path.resolve(paths.appPath, baseUrl);

View File

@ -1,5 +1,3 @@
'use strict';
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
@ -17,6 +15,7 @@ const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
// like /todos/42/static/js/bundle.7289d.js. We have to know the root. // like /todos/42/static/js/bundle.7289d.js. We have to know the root.
const publicUrlOrPath = getPublicUrlOrPath( const publicUrlOrPath = getPublicUrlOrPath(
process.env.NODE_ENV === 'development', process.env.NODE_ENV === 'development',
require(resolveApp('package.json')).homepage,
process.env.PUBLIC_URL process.env.PUBLIC_URL
); );
@ -63,6 +62,7 @@ module.exports = {
testsSetup: resolveModule(resolveApp, 'src/setupTests'), testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'), proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'), appNodeModules: resolveApp('node_modules'),
swSrc: resolveModule(resolveApp, 'src/service-worker'),
publicUrlOrPath, publicUrlOrPath,
}; };

View File

@ -1,5 +1,3 @@
'use strict';
const { resolveModuleName } = require('ts-pnp'); const { resolveModuleName } = require('ts-pnp');
exports.resolveModuleName = ( exports.resolveModuleName = (

View File

@ -1,4 +1,4 @@
'use strict';
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
@ -19,12 +19,14 @@ const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent'); const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const ESLintPlugin = require('eslint-webpack-plugin');
const paths = require('./paths'); const paths = require('./paths');
const modules = require('./modules'); const modules = require('./modules');
const getClientEnvironment = require('./env'); const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin'); const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const postcssNormalize = require('postcss-normalize'); const postcssNormalize = require('postcss-normalize');
@ -32,6 +34,14 @@ const appPackageJson = require(paths.appPackageJson);
// Source maps are resource heavy and can cause out of memory issue for large source files. // Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
const webpackDevClientEntry = require.resolve(
'react-dev-utils/webpackHotDevClient'
);
const reactRefreshOverlayEntry = require.resolve(
'react-dev-utils/refreshOverlayInterop'
);
// Some apps do not need the benefits of saving a web request, so not inlining the chunk // Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process. // makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'; const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
@ -43,15 +53,31 @@ const imageInlineSizeLimit = parseInt(
// Check if TypeScript is setup // Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig); const useTypeScript = fs.existsSync(paths.appTsConfig);
// Get the path to the uncompiled service worker (if it exists).
const swSrc = paths.swSrc;
// style files regexes // style files regexes
const cssRegex = /\.css$/; const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/; const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/; const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/; const sassModuleRegex = /\.module\.(scss|sass)$/;
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. // This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle. // It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) { module.exports = function (webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development'; const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production'; const isEnvProduction = webpackEnv === 'production';
@ -66,6 +92,8 @@ module.exports = function(webpackEnv) {
// Get environment variables to inject into our app. // Get environment variables to inject into our app.
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
const shouldUseReactRefresh = env.raw.FAST_REFRESH;
// common function to get style loaders // common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => { const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [ const loaders = [
@ -106,7 +134,7 @@ module.exports = function(webpackEnv) {
postcssNormalize(), postcssNormalize(),
], ],
}, },
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
}, },
}, },
].filter(Boolean); ].filter(Boolean);
@ -115,7 +143,8 @@ module.exports = function(webpackEnv) {
{ {
loader: require.resolve('resolve-url-loader'), loader: require.resolve('resolve-url-loader'),
options: { options: {
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
root: paths.appSrc,
}, },
}, },
{ {
@ -140,7 +169,9 @@ module.exports = function(webpackEnv) {
: isEnvDevelopment && 'cheap-module-source-map', : isEnvDevelopment && 'cheap-module-source-map',
// These are the "entry points" to our application. // These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle. // This means they will be the "root" imports that are included in JS bundle.
entry: [ entry:
isEnvDevelopment && !shouldUseReactRefresh
? [
// Include an alternative client for WebpackDevServer. A client's job is to // Include an alternative client for WebpackDevServer. A client's job is to
// connect to WebpackDevServer by a socket and get notified about changes. // connect to WebpackDevServer by a socket and get notified about changes.
// When you save a file, the client will either apply hot updates (in case // When you save a file, the client will either apply hot updates (in case
@ -149,16 +180,20 @@ module.exports = function(webpackEnv) {
// Note: instead of the default WebpackDevServer client, we use a custom one // Note: instead of the default WebpackDevServer client, we use a custom one
// to bring better experience for Create React App users. You can replace // to bring better experience for Create React App users. You can replace
// the line below with these two lines if you prefer the stock client: // the line below with these two lines if you prefer the stock client:
//
// require.resolve('webpack-dev-server/client') + '?/', // require.resolve('webpack-dev-server/client') + '?/',
// require.resolve('webpack/hot/dev-server'), // require.resolve('webpack/hot/dev-server'),
isEnvDevelopment && //
require.resolve('react-dev-utils/webpackHotDevClient'), // When using the experimental react-refresh integration,
// the webpack plugin takes care of injecting the dev client for us.
webpackDevClientEntry,
// Finally, this is your app's code: // Finally, this is your app's code:
paths.appIndexJs, paths.appIndexJs,
// We include the app code last so that if there is a runtime error during // We include the app code last so that if there is a runtime error during
// initialization, it doesn't blow up the WebpackDevServer client, and // initialization, it doesn't blow up the WebpackDevServer client, and
// changing JS code would still trigger a refresh. // changing JS code would still trigger a refresh.
].filter(Boolean), ]
: paths.appIndexJs,
output: { output: {
// The build folder. // The build folder.
path: isEnvProduction ? paths.appBuild : undefined, path: isEnvProduction ? paths.appBuild : undefined,
@ -310,7 +345,10 @@ module.exports = function(webpackEnv) {
// To fix this, we prevent you from importing files out of src/ -- if you'd like to, // 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. // 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. // Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), new ModuleScopePlugin(paths.appSrc, [
paths.appPackageJson,
reactRefreshOverlayEntry,
]),
new TsConfigPathsPlugin(), new TsConfigPathsPlugin(),
], ],
}, },
@ -326,31 +364,22 @@ module.exports = function(webpackEnv) {
rules: [ rules: [
// Disable require.ensure as it's not a standard language feature. // Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } }, { parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
enforce: 'pre',
use: [
{
options: {
cache: true,
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
resolvePluginsRelativeTo: __dirname,
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{ {
// "oneOf" will traverse all following loaders until one will // "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall // match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list. // back to the "file" loader at the end of the loader list.
oneOf: [ oneOf: [
// TODO: Merge this config once `image/avif` is in the mime-db
// https://github.com/jshttp/mime-db
{
test: [/\.avif$/],
loader: require.resolve('url-loader'),
options: {
limit: imageInlineSizeLimit,
mimetype: 'image/avif',
name: 'static/media/[name].[hash:8].[ext]',
},
},
// "url" loader works like "file" loader except that it embeds assets // "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests. // smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match. // A missing `test` is equivalent to a match.
@ -385,7 +414,10 @@ module.exports = function(webpackEnv) {
}, },
}, },
], ],
], isEnvDevelopment &&
shouldUseReactRefresh &&
require.resolve('react-refresh/babel'),
].filter(Boolean),
// This is a feature of `babel-loader` for webpack (not Babel itself). // This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/ // It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds. // directory for faster rebuilds.
@ -434,7 +466,9 @@ module.exports = function(webpackEnv) {
exclude: cssModuleRegex, exclude: cssModuleRegex,
use: getStyleLoaders({ use: getStyleLoaders({
importLoaders: 1, importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
}), }),
// Don't consider CSS imports dead code even if the // Don't consider CSS imports dead code even if the
// containing package claims to have no side effects. // containing package claims to have no side effects.
@ -448,7 +482,9 @@ module.exports = function(webpackEnv) {
test: cssModuleRegex, test: cssModuleRegex,
use: getStyleLoaders({ use: getStyleLoaders({
importLoaders: 1, importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: { modules: {
getLocalIdent: getCSSModuleLocalIdent, getLocalIdent: getCSSModuleLocalIdent,
}, },
@ -463,7 +499,9 @@ module.exports = function(webpackEnv) {
use: getStyleLoaders( use: getStyleLoaders(
{ {
importLoaders: 3, importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
}, },
'sass-loader' 'sass-loader'
), ),
@ -480,7 +518,9 @@ module.exports = function(webpackEnv) {
use: getStyleLoaders( use: getStyleLoaders(
{ {
importLoaders: 3, importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: { modules: {
getLocalIdent: getCSSModuleLocalIdent, getLocalIdent: getCSSModuleLocalIdent,
}, },
@ -558,8 +598,23 @@ module.exports = function(webpackEnv) {
// during a production build. // during a production build.
// Otherwise React will be compiled in the very slow development mode. // Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified), new webpack.DefinePlugin(env.stringified),
// This is necessary to emit hot updates (currently CSS only): // This is necessary to emit hot updates (CSS and Fast Refresh):
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
// Experimental hot reloading for React .
// https://github.com/facebook/react/tree/master/packages/react-refresh
isEnvDevelopment &&
shouldUseReactRefresh &&
new ReactRefreshWebpackPlugin({
overlay: {
entry: webpackDevClientEntry,
// The expected exports are slightly different from what the overlay exports,
// so an interop is included here to enable feedback on module-level errors.
module: reactRefreshOverlayEntry,
// Since we ship a custom dev client and overlay integration,
// the bundled socket handling logic can be eliminated.
sockIntegration: false,
},
}),
// Watcher doesn't work well if you mistype casing in a path so we use // 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. // a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240 // See https://github.com/facebook/create-react-app/issues/240
@ -610,19 +665,11 @@ module.exports = function(webpackEnv) {
// Generate a service worker script that will precache, and keep up to date, // Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the webpack build. // the HTML & assets that are part of the webpack build.
isEnvProduction && isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({ fs.existsSync(swSrc) &&
clientsClaim: true, new WorkboxWebpackPlugin.InjectManifest({
exclude: [/\.map$/, /asset-manifest\.json$/], swSrc,
navigateFallback: paths.publicUrlOrPath + 'index.html', dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
navigateFallbackDenylist: [ exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude any URLs whose last part seems to be a file extension
// as they're likely a resource and not a SPA route.
// URLs containing a "?" character won't be blacklisted as they're likely
// a route with query params (e.g. auth callbacks).
new RegExp('/[^/?]+\\.[^/]+$'),
],
}), }),
// TypeScript type checking // TypeScript type checking
useTypeScript && useTypeScript &&
@ -631,7 +678,6 @@ module.exports = function(webpackEnv) {
basedir: paths.appNodeModules, basedir: paths.appNodeModules,
}), }),
async: isEnvDevelopment, async: isEnvDevelopment,
useTypescriptIncrementalApi: true,
checkSyntacticErrors: true, checkSyntacticErrors: true,
resolveModuleNameModule: process.versions.pnp resolveModuleNameModule: process.versions.pnp
? `${__dirname}/pnpTs.js` ? `${__dirname}/pnpTs.js`
@ -641,9 +687,14 @@ module.exports = function(webpackEnv) {
: undefined, : undefined,
tsconfig: paths.appTsConfig, tsconfig: paths.appTsConfig,
reportFiles: [ reportFiles: [
'**', // This one is specifically to match during CI tests,
'!**/__tests__/**', // as micromatch doesn't match
'!**/?(*.)(spec|test).*', // '../cra-template-typescript/template/src/App.tsx'
// otherwise.
'../**/src/**/*.{ts,tsx}',
'**/src/**/*.{ts,tsx}',
'!**/src/**/__tests__/**',
'!**/src/**/?(*.)(spec|test).*',
'!**/src/setupProxy.*', '!**/src/setupProxy.*',
'!**/src/setupTests.*', '!**/src/setupTests.*',
], ],
@ -651,6 +702,24 @@ module.exports = function(webpackEnv) {
// The formatter is invoked directly in WebpackDevServerUtils during development // The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined, formatter: isEnvProduction ? typescriptFormatter : undefined,
}), }),
new ESLintPlugin({
// Plugin options
extensions: ['js', 'mjs', 'jsx', 'ts', 'tsx'],
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
context: paths.appSrc,
// 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), ].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser. // Some libraries import Node modules but don't use them in the browser.
// Tell webpack to provide empty mocks for them so importing them works. // Tell webpack to provide empty mocks for them so importing them works.

View File

@ -1,5 +1,3 @@
'use strict';
const fs = require('fs'); const fs = require('fs');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware'); const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware'); const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
@ -14,7 +12,7 @@ const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node' const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT; const sockPort = process.env.WDS_SOCKET_PORT;
module.exports = function(proxy, allowedHost) { module.exports = function (proxy, allowedHost) {
return { return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote // WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding: // websites from potentially accessing local content through DNS rebinding:

3431
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
}, },
"homepage": "https://github.com/Dreamacro/clash-dashboard", "homepage": "https://github.com/Dreamacro/clash-dashboard",
"scripts": { "scripts": {
"start": "node scripts/start.js", "start": "FAST_REFRESH=true node scripts/start.js",
"build": "GENERATE_SOURCEMAP=false PUBLIC_URL=./ node scripts/build.js", "build": "GENERATE_SOURCEMAP=false PUBLIC_URL=./ node scripts/build.js",
"lint": "npm run lint:ts", "lint": "npm run lint:ts",
"lint:ts": "eslint --ext=jsx,ts,tsx --fix src", "lint:ts": "eslint --ext=jsx,ts,tsx --fix src",
@ -26,14 +26,15 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.3", "@babel/core": "^7.12.3",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.2",
"@svgr/webpack": "^5.4.0", "@svgr/webpack": "^5.4.0",
"@types/classnames": "^2.2.10", "@types/classnames": "^2.2.11",
"@types/lodash": "^4.14.162", "@types/lodash": "^4.14.164",
"@types/node": "^14.14.2", "@types/node": "^14.14.6",
"@types/react": "^16.9.53", "@types/react": "^16.9.55",
"@types/react-dom": "^16.9.0", "@types/react-dom": "^16.9.9",
"@types/react-router-dom": "^5.1.6", "@types/react-router-dom": "^5.1.6",
"@types/react-table": "^7.0.24", "@types/react-table": "^7.0.25",
"@types/react-virtualized-auto-sizer": "^1.0.0", "@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.2", "@types/react-window": "^1.8.2",
"@typescript-eslint/eslint-plugin": "^4.5.0", "@typescript-eslint/eslint-plugin": "^4.5.0",
@ -41,37 +42,39 @@
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-loader": "8.1.0", "babel-loader": "8.1.0",
"babel-plugin-named-asset-import": "^0.3.6", "babel-plugin-named-asset-import": "^0.3.6",
"babel-preset-react-app": "^9.1.2", "babel-preset-react-app": "^10.0.0",
"camelcase": "^6.1.0", "bfj": "^7.0.2",
"camelcase": "^6.2.0",
"case-sensitive-paths-webpack-plugin": "2.3.0", "case-sensitive-paths-webpack-plugin": "2.3.0",
"css-loader": "^5.0.0", "css-loader": "^5.0.0",
"dotenv": "8.2.0", "dotenv": "8.2.0",
"dotenv-expand": "5.1.0", "dotenv-expand": "5.1.0",
"eslint": "^7.11.0", "eslint": "^7.12.1",
"eslint-config-react-app": "^5.2.1", "eslint-config-react-app": "^6.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "^5.2.0", "eslint-plugin-flowtype": "^5.2.0",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.3.1", "eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.21.5", "eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"file-loader": "^6.1.1", "eslint-webpack-plugin": "^2.1.0",
"file-loader": "^6.2.0",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"html-webpack-plugin": "^4.5.0", "html-webpack-plugin": "^4.5.0",
"identity-obj-proxy": "3.0.0", "identity-obj-proxy": "3.0.0",
"mini-css-extract-plugin": "^1.1.1", "mini-css-extract-plugin": "^1.2.1",
"optimize-css-assets-webpack-plugin": "^5.0.4", "optimize-css-assets-webpack-plugin": "^5.0.4",
"pnp-webpack-plugin": "1.6.4", "pnp-webpack-plugin": "1.6.4",
"postcss-flexbugs-fixes": "^4.2.1", "postcss-flexbugs-fixes": "^5.0.0",
"postcss-loader": "^4.0.4", "postcss-loader": "^4.0.4",
"postcss-normalize": "^9.0.0", "postcss-normalize": "^9.0.0",
"postcss-preset-env": "6.7.0", "postcss-preset-env": "6.7.0",
"postcss-safe-parser": "^5.0.2", "postcss-safe-parser": "^5.0.2",
"react-app-polyfill": "^1.0.6", "react-app-polyfill": "^2.0.0",
"react-dev-utils": "^10.2.1", "react-dev-utils": "^11.0.0",
"react-refresh": "^0.9.0",
"resolve": "^1.18.1", "resolve": "^1.18.1",
"resolve-url-loader": "^3.1.2", "resolve-url-loader": "^3.1.2",
"sass": "^1.27.0", "sass": "^1.28.0",
"sass-loader": "^10.0.3", "sass-loader": "^10.0.3",
"semver": "^7.3.2", "semver": "^7.3.2",
"style-loader": "^2.0.0", "style-loader": "^2.0.0",
@ -79,15 +82,16 @@
"ts-pnp": "^1.2.0", "ts-pnp": "^1.2.0",
"tsconfig-paths-webpack-plugin": "^3.3.0", "tsconfig-paths-webpack-plugin": "^3.3.0",
"type-fest": "^0.18.0", "type-fest": "^0.18.0",
"typescript": "^4.0.3", "typescript": "^4.0.5",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"web-vitals": "^0.2.4",
"webpack": "^4.44.2", "webpack": "^4.44.2",
"webpack-dev-server": "3.11.0", "webpack-dev-server": "3.11.0",
"webpack-manifest-plugin": "2.2.0", "webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "^5.1.4" "workbox-webpack-plugin": "^5.1.4"
}, },
"dependencies": { "dependencies": {
"axios": "^0.20.0", "axios": "^0.21.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"dayjs": "^1.9.3", "dayjs": "^1.9.3",
"eventemitter3": "^4.0.7", "eventemitter3": "^4.0.7",
@ -96,11 +100,11 @@
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-table": "^7.6.0", "react-table": "^7.6.1",
"react-virtualized-auto-sizer": "^1.0.2", "react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5", "react-window": "^1.8.6",
"recoil": "0.0.13", "recoil": "^0.1.2",
"swr": "^0.3.6", "swr": "^0.3.8",
"use-immer": "^0.4.1" "use-immer": "^0.4.1"
}, },
"browserslist": { "browserslist": {

View File

@ -1,4 +1,4 @@
'use strict';
// Do this as the first thing so that any code reading it knows the right env. // Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production'; process.env.BABEL_ENV = 'production';
@ -18,6 +18,7 @@ require('../config/env');
const path = require('path'); const path = require('path');
const chalk = require('react-dev-utils/chalk'); const chalk = require('react-dev-utils/chalk');
const fs = require('fs-extra'); const fs = require('fs-extra');
const bfj = require('bfj');
const webpack = require('webpack'); const webpack = require('webpack');
const configFactory = require('../config/webpack.config'); const configFactory = require('../config/webpack.config');
const paths = require('../config/paths'); const paths = require('../config/paths');
@ -43,6 +44,9 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1); process.exit(1);
} }
const argv = process.argv.slice(2);
const writeStatsJson = argv.indexOf('--stats') !== -1;
// Generate configuration // Generate configuration
const config = configFactory('production'); const config = configFactory('production');
@ -130,18 +134,6 @@ checkBrowsers(paths.appPath, isInteractive)
// Create the production build and print the deployment instructions. // Create the production build and print the deployment instructions.
function build(previousFileSizes) { function build(previousFileSizes) {
// We used to support resolving modules according to `NODE_PATH`.
// This now has been deprecated in favor of jsconfig/tsconfig.json
// This lets you use absolute paths in imports inside large monorepos:
if (process.env.NODE_PATH) {
console.log(
chalk.yellow(
'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.'
)
);
console.log();
}
console.log('Creating an optimized production build...'); console.log('Creating an optimized production build...');
const compiler = webpack(config); const compiler = webpack(config);
@ -194,11 +186,20 @@ function build(previousFileSizes) {
return reject(new Error(messages.warnings.join('\n\n'))); return reject(new Error(messages.warnings.join('\n\n')));
} }
return resolve({ const resolveArgs = {
stats, stats,
previousFileSizes, previousFileSizes,
warnings: messages.warnings, 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);
}); });
}); });
} }

View File

@ -1,5 +1,3 @@
'use strict';
// Do this as the first thing so that any code reading it knows the right env. // Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'development'; process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development'; process.env.NODE_ENV = 'development';
@ -28,10 +26,14 @@ const {
prepareUrls, prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils'); } = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser'); const openBrowser = require('react-dev-utils/openBrowser');
const semver = require('semver');
const paths = require('../config/paths'); const paths = require('../config/paths');
const configFactory = require('../config/webpack.config'); const configFactory = require('../config/webpack.config');
const createDevServerConfig = require('../config/webpackDevServer.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 useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY; const isInteractive = process.stdout.isTTY;
@ -56,7 +58,7 @@ if (process.env.HOST) {
`If this was unintentional, check that you haven't mistakenly set it in your shell.` `If this was unintentional, check that you haven't mistakenly set it in your shell.`
); );
console.log( console.log(
`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}` `Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}`
); );
console.log(); console.log();
} }
@ -79,6 +81,7 @@ checkBrowsers(paths.appPath, isInteractive)
const config = configFactory('development'); const config = configFactory('development');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name; const appName = require(paths.appPackageJson).name;
const useTypeScript = fs.existsSync(paths.appTsConfig); const useTypeScript = fs.existsSync(paths.appTsConfig);
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
const urls = prepareUrls( const urls = prepareUrls(
@ -125,36 +128,31 @@ checkBrowsers(paths.appPath, isInteractive)
clearConsole(); clearConsole();
} }
// We used to support resolving modules according to `NODE_PATH`. if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) {
// This now has been deprecated in favor of jsconfig/tsconfig.json
// This lets you use absolute paths in imports inside large monorepos:
if (process.env.NODE_PATH) {
console.log( console.log(
chalk.yellow( chalk.yellow(
'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.' `Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.`
) )
); );
console.log();
} }
console.log(chalk.cyan('Starting the development server...\n')); console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser); openBrowser(urls.localUrlForBrowser);
}); });
['SIGINT', 'SIGTERM'].forEach(function(sig) { ['SIGINT', 'SIGTERM'].forEach(function (sig) {
process.on(sig, function() { process.on(sig, function () {
devServer.close(); devServer.close();
process.exit(); process.exit();
}); });
}); });
if (isInteractive || process.env.CI !== 'true') { if (process.env.CI !== 'true') {
// Gracefully exit when stdin ends // Gracefully exit when stdin ends
process.stdin.on('end', function() { process.stdin.on('end', function () {
devServer.close(); devServer.close();
process.exit(); process.exit();
}); });
process.stdin.resume();
} }
}) })
.catch(err => { .catch(err => {

View File

@ -14,7 +14,7 @@ import Connections from '@containers/Connections'
import ExternalControllerModal from '@containers/ExternalControllerDrawer' import ExternalControllerModal from '@containers/ExternalControllerDrawer'
import { getLogsStreamReader } from '@lib/request' import { getLogsStreamReader } from '@lib/request'
export default function () { export default function App () {
useEffect(() => { useEffect(() => {
getLogsStreamReader() getLogsStreamReader()
}, []) }, [])

View File

@ -1,4 +1,4 @@
export default { const EN = {
SideBar: { SideBar: {
Proxies: 'Proxies', Proxies: 'Proxies',
Overview: 'Overview', Overview: 'Overview',
@ -102,3 +102,5 @@ export default {
cancel: 'Cancel' cancel: 'Cancel'
} }
} }
export default EN

View File

@ -1,4 +1,4 @@
export default { const CN = {
SideBar: { SideBar: {
Proxies: '代理', Proxies: '代理',
Overview: '总览', Overview: '总览',
@ -102,3 +102,5 @@ export default {
cancel: '取 消' cancel: '取 消'
} }
} }
export default CN