Commit c134957a by zhanghaozhe

typescript

parent 94820305
...@@ -15,7 +15,7 @@ if (!NODE_ENV) { ...@@ -15,7 +15,7 @@ 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
var dotenvFiles = [ const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`, `${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`, `${paths.dotenv}.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment // Don't include `.env.local` for `test` environment
...@@ -46,7 +46,7 @@ dotenvFiles.forEach(dotenvFile => { ...@@ -46,7 +46,7 @@ dotenvFiles.forEach(dotenvFile => {
// It works similar to `NODE_PATH` in Node itself: // It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders // 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. // 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. // 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 // https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently. // We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd()); const appDirectory = fs.realpathSync(process.cwd());
...@@ -57,7 +57,7 @@ process.env.NODE_PATH = (process.env.NODE_PATH || '') ...@@ -57,7 +57,7 @@ process.env.NODE_PATH = (process.env.NODE_PATH || '')
.join(path.delimiter); .join(path.delimiter);
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration. // injected into the application via DefinePlugin in webpack configuration.
const REACT_APP = /^REACT_APP_/i; const REACT_APP = /^REACT_APP_/i;
function getClientEnvironment(publicUrl) { function getClientEnvironment(publicUrl) {
...@@ -77,15 +77,24 @@ function getClientEnvironment(publicUrl) { ...@@ -77,15 +77,24 @@ function getClientEnvironment(publicUrl) {
// This should only be used as an escape hatch. Normally you would put // 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. // images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl, 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,
} }
); );
// Stringify all values so we can feed into Webpack DefinePlugin // Stringify all values so we can feed into webpack DefinePlugin
const stringified = { const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => { 'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]); env[key] = JSON.stringify(raw[key]);
return env; return env;
}, {}), }, {}),
}; };
return { raw, stringified }; return { raw, stringified };
} }
......
'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;
File mode changed from 100755 to 100644
'use strict'; 'use strict';
const path = require('path'); const path = require('path');
const camelcase = require('camelcase');
// This is a custom Jest transformer turning file imports into filenames. // This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html // http://facebook.github.io/jest/docs/en/webpack.html
...@@ -10,19 +11,27 @@ module.exports = { ...@@ -10,19 +11,27 @@ module.exports = {
const assetFilename = JSON.stringify(path.basename(filename)); const assetFilename = JSON.stringify(path.basename(filename));
if (filename.match(/\.svg$/)) { 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'); return `const React = require('react');
module.exports = { module.exports = {
__esModule: true, __esModule: true,
default: ${assetFilename}, default: ${assetFilename},
ReactComponent: React.forwardRef((props, ref) => ({ ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
$$typeof: Symbol.for('react.element'), return {
type: 'svg', $$typeof: Symbol.for('react.element'),
ref: ref, type: 'svg',
key: null, ref: ref,
props: Object.assign({}, props, { key: null,
children: ${assetFilename} props: Object.assign({}, props, {
}) children: ${assetFilename}
})), })
};
}),
};`; };`;
} }
......
'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;
// We need to explicitly check for null and undefined (and not a falsy value) because
// TypeScript treats an empty string as `.`.
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);
// 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();
...@@ -2,41 +2,24 @@ ...@@ -2,41 +2,24 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const url = require('url'); const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
// Make sure any symlinks in the project folder are resolved: // Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637 // https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd()); const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath); const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
const envPublicUrl = process.env.PUBLIC_URL;
function ensureSlash(inputPath, needsSlash) {
const hasSlash = inputPath.endsWith('/');
if (hasSlash && !needsSlash) {
return inputPath.substr(0, inputPath.length - 1);
} else if (!hasSlash && needsSlash) {
return `${inputPath}/`;
} else {
return inputPath;
}
}
const getPublicUrl = appPackageJson =>
envPublicUrl || require(appPackageJson).homepage;
// We use `PUBLIC_URL` environment variable or "homepage" field to infer // We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served. // "public path" at which the app is served.
// Webpack needs to know it to put the right <script> hrefs into HTML even in // 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. // 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 // 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. // like /todos/42/static/js/bundle.7289d.js. We have to know the root.
function getServedPath(appPackageJson) { const publicUrlOrPath = getPublicUrlOrPath(
const publicUrl = getPublicUrl(appPackageJson); process.env.NODE_ENV === 'development',
const servedUrl = require(resolveApp('package.json')).homepage,
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/'); process.env.PUBLIC_URL
return ensureSlash(servedUrl, true); );
}
const moduleFileExtensions = [ const moduleFileExtensions = [
'web.mjs', 'web.mjs',
...@@ -76,12 +59,12 @@ module.exports = { ...@@ -76,12 +59,12 @@ module.exports = {
appPackageJson: resolveApp('package.json'), appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'), appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'), appTsConfig: resolveApp('tsconfig.json'),
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'), yarnLockFile: resolveApp('yarn.lock'),
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'),
publicUrl: getPublicUrl(resolveApp('package.json')), publicUrlOrPath,
servedPath: getServedPath(resolveApp('package.json')),
}; };
......
'use strict';
const { resolveModuleName } = require('ts-pnp');
exports.resolveModuleName = (
typescript,
moduleName,
containingFile,
compilerOptions,
resolutionHost
) => {
return resolveModuleName(
moduleName,
containingFile,
compilerOptions,
resolutionHost,
typescript.resolveModuleName
);
};
exports.resolveTypeReferenceDirective = (
typescript,
moduleName,
containingFile,
compilerOptions,
resolutionHost
) => {
return resolveModuleName(
moduleName,
containingFile,
compilerOptions,
resolutionHost,
typescript.resolveTypeReferenceDirective
);
};
'use strict'; 'use strict'
const fs = require('fs'); const fs = require('fs')
const path = require('path'); const path = require('path')
const webpack = require('webpack'); const webpack = require('webpack')
const resolve = require('resolve'); const resolve = require('resolve')
const PnpWebpackPlugin = require('pnp-webpack-plugin'); const PnpWebpackPlugin = require('pnp-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin'); const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin')
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const safePostCssParser = require('postcss-safe-parser'); const safePostCssParser = require('postcss-safe-parser')
const ManifestPlugin = require('webpack-manifest-plugin'); const ManifestPlugin = require('webpack-manifest-plugin')
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin')
const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); 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 paths = require('./paths'); const paths = require('./paths')
const getClientEnvironment = require('./env'); const modules = require('./modules')
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin'); const getClientEnvironment = require('./env')
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin'); const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin')
const typescriptFormatter = require('react-dev-utils/typescriptFormatter'); const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin')
const typescriptFormatter = require('react-dev-utils/typescriptFormatter')
const postcssNormalize = require('postcss-normalize')
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'
// 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'
const isExtendingEslintConfig = process.env.EXTEND_ESLINT === 'true'
const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '10000')
// Check if TypeScript is setup // Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig); const useTypeScript = fs.existsSync(paths.appTsConfig)
const theme = require('../package.json').theme;
// 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)$/
// 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'
// Webpack uses `publicPath` to determine where the app is being served from. // Variable used for enabling profiling in Production
// It requires a trailing slash, or the file assets will get an incorrect path. // passed into alias object. Uses a flag if passed into the build command
// In development, we always serve from the root. This makes config easier. const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile')
const publicPath = isEnvProduction
? paths.servedPath
: isEnvDevelopment && '/';
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = publicPath === './';
// `publicUrl` is just like `publicPath`, but we will provide it to our app // We will provide `paths.publicUrlOrPath` to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. // 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. // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = isEnvProduction
? publicPath.slice(0, -1)
: isEnvDevelopment && '';
// Get environment variables to inject into our app. // Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl); const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1))
// common function to get style loaders // common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => { const getStyleLoaders = (cssOptions, preProcessor) => {
...@@ -72,10 +70,9 @@ module.exports = function(webpackEnv) { ...@@ -72,10 +70,9 @@ module.exports = function(webpackEnv) {
isEnvDevelopment && require.resolve('style-loader'), isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && { isEnvProduction && {
loader: MiniCssExtractPlugin.loader, loader: MiniCssExtractPlugin.loader,
options: Object.assign( // css is located in `mrstaticcss`, use '../../' to locate index.html folder
{}, // in production `paths.publicUrlOrPath` can be a relative path
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined options: paths.publicUrlOrPath.startsWith('.') ? { publicPath: '../../' } : {},
),
}, },
{ {
loader: require.resolve('css-loader'), loader: require.resolve('css-loader'),
...@@ -98,34 +95,38 @@ module.exports = function(webpackEnv) { ...@@ -98,34 +95,38 @@ module.exports = function(webpackEnv) {
}, },
stage: 3, stage: 3,
}), }),
require('postcss-px-to-viewport')({ require('postcss-px-to-viewport')({
viewportWidth: 375, viewportWidth: 375,
unitPrecision: 6, unitPrecision: 6,
selectorBlackList: ['skip-vw'] selectorBlackList: ['skip-vw'],
}) }),
// 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.
postcssNormalize(),
], ],
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
}, },
}, },
].filter(Boolean); ].filter(Boolean)
if (preProcessor) { if (preProcessor) {
loaders.push({ loaders.push(
loader: require.resolve(preProcessor), {
options: { loader: require.resolve('resolve-url-loader'),
sourceMap: isEnvProduction && shouldUseSourceMap, options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
},
}, },
}); {
if(preProcessor == 'sass-loader' && !cssOptions.modules){ loader: require.resolve(preProcessor),
loaders.push({
loader: require.resolve('sass-resources-loader'),
options: { options: {
resources: [require.resolve('../src/assets/css/variable.scss')] sourceMap: true,
} },
}) }
} )
} }
return loaders; return loaders
}; }
return { return {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development', mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
...@@ -149,8 +150,7 @@ module.exports = function(webpackEnv) { ...@@ -149,8 +150,7 @@ module.exports = function(webpackEnv) {
// 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 && isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('react-dev-utils/webpackHotDevClient'),
// 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
...@@ -164,24 +164,27 @@ module.exports = function(webpackEnv) { ...@@ -164,24 +164,27 @@ module.exports = function(webpackEnv) {
pathinfo: isEnvDevelopment, pathinfo: isEnvDevelopment,
// There will be one main bundle, and one file per asynchronous chunk. // There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files. // In development, it does not produce real files.
filename: isEnvProduction filename: isEnvProduction ? 'mrstaticjs/[name].[contenthash:8].js' : isEnvDevelopment && 'mrstaticjs/bundle.js',
? 'mrstatic/js/[name].[contenthash:8].js' // TODO: remove this when upgrading to webpack 5
: isEnvDevelopment && 'mrstatic/js/bundle.js', futureEmitAssets: true,
// There are also additional JS chunk files if you use code splitting. // There are also additional JS chunk files if you use code splitting.
chunkFilename: isEnvProduction chunkFilename: isEnvProduction
? 'mrstatic/js/[name].[contenthash:8].chunk.js' ? 'mrstaticjs/[name].[contenthash:8].chunk.js'
: isEnvDevelopment && 'mrstatic/js/[name].chunk.js', : isEnvDevelopment && 'mrstaticjs/[name].chunk.js',
// 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. // We inferred the "public path" (such as / or /my-project) from homepage.
// We use "/" in development. publicPath: paths.publicUrlOrPath,
publicPath: publicPath,
// Point sourcemap entries to original disk location (format as URL on Windows) // Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction devtoolModuleFilenameTemplate: isEnvProduction
? info => ? info => path.relative(paths.appSrc, info.absoluteResourcePath).replace(/\\/g, '/')
path : isEnvDevelopment && (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
.relative(paths.appSrc, info.absoluteResourcePath) // Prevents conflicts when multiple webpack runtimes (from different apps)
.replace(/\\/g, '/') // are used on the same page.
: isEnvDevelopment && jsonpFunction: `webpackJsonp${appPackageJson.name}`,
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), // this defaults to 'window', but by setting it to 'this' then
// module chunks which are built will work in web workers as well.
globalObject: 'this',
}, },
optimization: { optimization: {
minimize: isEnvProduction, minimize: isEnvProduction,
...@@ -190,8 +193,8 @@ module.exports = function(webpackEnv) { ...@@ -190,8 +193,8 @@ module.exports = function(webpackEnv) {
new TerserPlugin({ new TerserPlugin({
terserOptions: { terserOptions: {
parse: { parse: {
// we want terser to parse ecma 8 code. However, we don't want it // We want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code // to apply any minification steps that turns valid ecma 5 code
// into invalid ecma 5 code. This is why the 'compress' and 'output' // into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe // sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234 // https://github.com/facebook/create-react-app/pull/4234
...@@ -207,13 +210,16 @@ module.exports = function(webpackEnv) { ...@@ -207,13 +210,16 @@ module.exports = function(webpackEnv) {
comparisons: false, comparisons: false,
// Disabled because of an issue with Terser breaking valid code: // Disabled because of an issue with Terser breaking valid code:
// https://github.com/facebook/create-react-app/issues/5250 // https://github.com/facebook/create-react-app/issues/5250
// Pending futher investigation: // Pending further investigation:
// https://github.com/terser-js/terser/issues/120 // https://github.com/terser-js/terser/issues/120
inline: 2 inline: 2,
}, },
mangle: { mangle: {
safari10: true, safari10: true,
}, },
// Added for profiling in devtools
keep_classnames: isEnvProductionProfile,
keep_fnames: isEnvProductionProfile,
output: { output: {
ecma: 5, ecma: 5,
comments: false, comments: false,
...@@ -222,11 +228,6 @@ module.exports = function(webpackEnv) { ...@@ -222,11 +228,6 @@ module.exports = function(webpackEnv) {
ascii_only: true, ascii_only: true,
}, },
}, },
// Use multi-process parallel running to improve the build speed
// Default number of concurrent runs: os.cpus().length - 1
parallel: true,
// Enable file caching
cache: true,
sourceMap: shouldUseSourceMap, sourceMap: shouldUseSourceMap,
}), }),
// This is only used in production mode // This is only used in production mode
...@@ -244,6 +245,9 @@ module.exports = function(webpackEnv) { ...@@ -244,6 +245,9 @@ module.exports = function(webpackEnv) {
} }
: false, : false,
}, },
cssProcessorPluginOptions: {
preset: ['default', { minifyFontValues: { removeQuotes: false } }],
},
}), }),
], ],
// Automatically split vendor and commons // Automatically split vendor and commons
...@@ -255,34 +259,34 @@ module.exports = function(webpackEnv) { ...@@ -255,34 +259,34 @@ module.exports = function(webpackEnv) {
}, },
// Keep the runtime chunk separated to enable long term caching // Keep the runtime chunk separated to enable long term caching
// https://twitter.com/wSokra/status/969679223278505985 // https://twitter.com/wSokra/status/969679223278505985
runtimeChunk: true, // https://github.com/facebook/create-react-app/issues/5358
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`,
},
}, },
resolve: { resolve: {
// This allows you to set a fallback for where Webpack should look for modules. // 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" // We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism. // if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253 // https://github.com/facebook/create-react-app/issues/253
modules: ['node_modules'].concat( modules: ['node_modules', paths.appNodeModules].concat(modules.additionalModulePaths || []),
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem. // These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support // We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see: // some tools, although we do not recommend using it, see:
// https://github.com/facebook/create-react-app/issues/290 // https://github.com/facebook/create-react-app/issues/290
// `web` extension prefixes have been added for better support // `web` extension prefixes have been added for better support
// for React Native Web. // for React Native Web.
extensions: paths.moduleFileExtensions extensions: paths.moduleFileExtensions.map(ext => `.${ext}`).filter(ext => useTypeScript || !ext.includes('ts')),
.map(ext => `.${ext}`)
.filter(ext => useTypeScript || !ext.includes('ts')),
alias: { alias: {
// Support React Native Web // Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web', 'react-native': 'react-native-web',
'@': path.resolve(__dirname, '../src'), // Allows for better profiling with ReactDevTools
'@common': path.resolve(__dirname, '../src/common'), ...(isEnvProductionProfile && {
'@components': path.resolve(__dirname, '../src/components'), 'react-dom$': 'react-dom/profiling',
'@assets': path.resolve(__dirname, '../src/assets'), 'scheduler/tracing': 'scheduler/tracing-profiling',
}),
...(modules.webpackAliases || {}),
}, },
plugins: [ plugins: [
// Adds support for installing with Plug'n'Play, leading to faster installs and adding // Adds support for installing with Plug'n'Play, leading to faster installs and adding
...@@ -298,7 +302,7 @@ module.exports = function(webpackEnv) { ...@@ -298,7 +302,7 @@ module.exports = function(webpackEnv) {
}, },
resolveLoader: { resolveLoader: {
plugins: [ plugins: [
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders // Also related to Plug'n'Play, but this time it tells webpack to load its loaders
// from the current package. // from the current package.
PnpWebpackPlugin.moduleLoader(module), PnpWebpackPlugin.moduleLoader(module),
], ],
...@@ -312,14 +316,15 @@ module.exports = function(webpackEnv) { ...@@ -312,14 +316,15 @@ module.exports = function(webpackEnv) {
// First, run the linter. // First, run the linter.
// It's important to do this before Babel processes the JS. // It's important to do this before Babel processes the JS.
{ {
test: /\.(js|mjs|jsx)$/, test: /\.(js|mjs|jsx|ts|tsx)$/,
enforce: 'pre', enforce: 'pre',
use: [ use: [
{ {
options: { options: {
cache: true,
formatter: require.resolve('react-dev-utils/eslintFormatter'), formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'), eslintPath: require.resolve('eslint'),
resolvePluginsRelativeTo: __dirname,
}, },
loader: require.resolve('eslint-loader'), loader: require.resolve('eslint-loader'),
}, },
...@@ -338,8 +343,8 @@ module.exports = function(webpackEnv) { ...@@ -338,8 +343,8 @@ module.exports = function(webpackEnv) {
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'), loader: require.resolve('url-loader'),
options: { options: {
limit: 10000, limit: imageInlineSizeLimit,
name: 'mrstatic/media/[name].[hash:8].[ext]', name: 'mrstaticmedia/[name].[hash:8].[ext]',
}, },
}, },
// Process application JS with Babel. // Process application JS with Babel.
...@@ -349,17 +354,15 @@ module.exports = function(webpackEnv) { ...@@ -349,17 +354,15 @@ module.exports = function(webpackEnv) {
include: paths.appSrc, include: paths.appSrc,
loader: require.resolve('babel-loader'), loader: require.resolve('babel-loader'),
options: { options: {
customize: require.resolve( customize: require.resolve('babel-preset-react-app/webpack-overrides'),
'babel-preset-react-app/webpack-overrides'
),
plugins: [ plugins: [
[ [
require.resolve('babel-plugin-named-asset-import'), require.resolve('babel-plugin-named-asset-import'),
{ {
loaderMap: { loaderMap: {
svg: { svg: {
ReactComponent: '@svgr/webpack?-svgo,+ref![path]', ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]',
}, },
}, },
}, },
...@@ -369,7 +372,8 @@ module.exports = function(webpackEnv) { ...@@ -369,7 +372,8 @@ module.exports = function(webpackEnv) {
// 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.
cacheDirectory: true, cacheDirectory: true,
cacheCompression: isEnvProduction, // See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
compact: isEnvProduction, compact: isEnvProduction,
}, },
}, },
...@@ -383,20 +387,16 @@ module.exports = function(webpackEnv) { ...@@ -383,20 +387,16 @@ module.exports = function(webpackEnv) {
babelrc: false, babelrc: false,
configFile: false, configFile: false,
compact: false, compact: false,
presets: [ presets: [[require.resolve('babel-preset-react-app/dependencies'), { helpers: true }]],
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true, cacheDirectory: true,
cacheCompression: isEnvProduction, // See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
// If an error happens in a package, it's possible to be
// because it was compiled. Thus, we don't want the browser // Babel sourcemaps are needed for debugging into node_modules
// debugger to show the original code. Instead, the code // code. Without the options below, debuggers like VSCode
// being evaluated would be much more helpful. // show incorrect code and set breakpoints on the wrong lines.
sourceMaps: false, sourceMaps: shouldUseSourceMap,
inputSourceMap: shouldUseSourceMap,
}, },
}, },
// "postcss" loader applies autoprefixer to our CSS. // "postcss" loader applies autoprefixer to our CSS.
...@@ -426,8 +426,9 @@ module.exports = function(webpackEnv) { ...@@ -426,8 +426,9 @@ module.exports = function(webpackEnv) {
use: getStyleLoaders({ use: getStyleLoaders({
importLoaders: 1, importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true, modules: {
getLocalIdent: getCSSModuleLocalIdent, getLocalIdent: getCSSModuleLocalIdent,
},
}), }),
}, },
// Opt-in support for SASS (using .scss or .sass extensions). // Opt-in support for SASS (using .scss or .sass extensions).
...@@ -438,9 +439,8 @@ module.exports = function(webpackEnv) { ...@@ -438,9 +439,8 @@ module.exports = function(webpackEnv) {
exclude: sassModuleRegex, exclude: sassModuleRegex,
use: getStyleLoaders( use: getStyleLoaders(
{ {
importLoaders: 2, importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
modules: false
}, },
'sass-loader' 'sass-loader'
), ),
...@@ -456,29 +456,15 @@ module.exports = function(webpackEnv) { ...@@ -456,29 +456,15 @@ module.exports = function(webpackEnv) {
test: sassModuleRegex, test: sassModuleRegex,
use: getStyleLoaders( use: getStyleLoaders(
{ {
importLoaders: 2, importLoaders: 3,
sourceMap: isEnvProduction && shouldUseSourceMap, sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true, modules: {
getLocalIdent: getCSSModuleLocalIdent, getLocalIdent: getCSSModuleLocalIdent,
},
}, },
'sass-loader' 'sass-loader'
), ),
}, },
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{ loader: 'less-loader',
options: {
modifyVars: theme,
javascriptEnabled: true
}
},
],
include: /node_modules/,
},
// "file" loader makes sure those assets get served by WebpackDevServer. // "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename. // When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder. // In production, they would get copied to the `build` folder.
...@@ -492,7 +478,7 @@ module.exports = function(webpackEnv) { ...@@ -492,7 +478,7 @@ module.exports = function(webpackEnv) {
// by webpacks internal loaders. // by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/], exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: { options: {
name: 'mrstatic/media/[name].[hash:8].[ext]', name: 'mrstaticmedia/[name].[hash:8].[ext]',
}, },
}, },
// ** STOP ** Are you adding a new loader? // ** STOP ** Are you adding a new loader?
...@@ -530,15 +516,13 @@ module.exports = function(webpackEnv) { ...@@ -530,15 +516,13 @@ module.exports = function(webpackEnv) {
), ),
// Inlines the webpack runtime script. This script is too small to warrant // Inlines the webpack runtime script. This script is too small to warrant
// a network request. // a network request.
isEnvProduction && // https://github.com/facebook/create-react-app/issues/5358
shouldInlineRuntimeChunk && isEnvProduction && shouldInlineRuntimeChunk && new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html. // Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.: // The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> // <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage" // It will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL. // in `package.json`, in which case it will be the pathname of that URL.
// In development, this will be an empty string.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as // This gives some necessary context to module not found errors, such as
// the requesting resource. // the requesting resource.
...@@ -556,45 +540,61 @@ module.exports = function(webpackEnv) { ...@@ -556,45 +540,61 @@ module.exports = function(webpackEnv) {
// See https://github.com/facebook/create-react-app/issues/240 // See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(), isEnvDevelopment && new CaseSensitivePathsPlugin(),
// If you require a missing module and then `npm install` it, you still have // If you require a missing module and then `npm install` it, you still have
// to restart the development server for Webpack to discover it. This plugin // to restart the development server for webpack to discover it. This plugin
// makes the discovery automatic so you don't have to restart. // makes the discovery automatic so you don't have to restart.
// See https://github.com/facebook/create-react-app/issues/186 // See https://github.com/facebook/create-react-app/issues/186
isEnvDevelopment && isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction && isEnvProduction &&
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output // Options similar to the same options in webpackOptions.output
// both options are optional // both options are optional
filename: 'mrstatic/css/[name].[contenthash:8].css', filename: 'mrstaticcss/[name].[contenthash:8].css',
chunkFilename: 'mrstatic/css/[name].[contenthash:8].chunk.css', chunkFilename: 'mrstaticcss/[name].[contenthash:8].chunk.css',
}), }),
// Generate a manifest file which contains a mapping of all asset filenames // Generate an asset manifest file with the following content:
// to their corresponding output file so that tools can pick it up without // - "files" key: Mapping of all asset filenames to their corresponding
// having to parse `index.html`. // 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 ManifestPlugin({ new ManifestPlugin({
fileName: 'asset-manifest.json', fileName: 'asset-manifest.json',
publicPath: publicPath, 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 // 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 // by default due to how webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales. // solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js: // You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// 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({ new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true, clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/], exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn', importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html', navigateFallback: paths.publicUrlOrPath + 'index.html',
navigateFallbackBlacklist: [ navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call // Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'), new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in // Exclude any URLs whose last part seems to be a file extension
// public/ and not a SPA route // as they're likely a resource and not a SPA route.
new RegExp('/[^/]+\\.[^/]+$'), // 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
...@@ -606,28 +606,29 @@ module.exports = function(webpackEnv) { ...@@ -606,28 +606,29 @@ module.exports = function(webpackEnv) {
async: isEnvDevelopment, async: isEnvDevelopment,
useTypescriptIncrementalApi: true, useTypescriptIncrementalApi: true,
checkSyntacticErrors: true, checkSyntacticErrors: true,
resolveModuleNameModule: process.versions.pnp ? `${__dirname}/pnpTs.js` : undefined,
resolveTypeReferenceDirectiveModule: process.versions.pnp ? `${__dirname}/pnpTs.js` : undefined,
tsconfig: paths.appTsConfig, tsconfig: paths.appTsConfig,
reportFiles: [ reportFiles: [
'**', '**',
'!**/*.json',
'!**/__tests__/**', '!**/__tests__/**',
'!**/?(*.)(spec|test).*', '!**/?(*.)(spec|test).*',
'!**/src/setupProxy.*', '!**/src/setupProxy.*',
'!**/src/setupTests.*', '!**/src/setupTests.*',
], ],
watch: paths.appSrc,
silent: true, silent: true,
// 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,
}), }),
].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.
node: { node: {
module: 'empty', module: 'empty',
dgram: 'empty', dgram: 'empty',
dns: 'mock', dns: 'mock',
fs: 'empty', fs: 'empty',
http2: 'empty',
net: 'empty', net: 'empty',
tls: 'empty', tls: 'empty',
child_process: 'empty', child_process: 'empty',
...@@ -635,5 +636,5 @@ module.exports = function(webpackEnv) { ...@@ -635,5 +636,5 @@ module.exports = function(webpackEnv) {
// Turn off performance processing because we utilize // Turn off performance processing because we utilize
// our own hints via the FileSizeReporter // our own hints via the FileSizeReporter
performance: false, performance: false,
}; }
}; }
'use strict'; 'use strict';
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');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware'); const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles'); const ignoredFiles = require('react-dev-utils/ignoredFiles');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const paths = require('./paths'); const paths = require('./paths');
const fs = require('fs'); const getHttpsConfig = require('./getHttpsConfig');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const host = process.env.HOST || '0.0.0.0'; const host = process.env.HOST || '0.0.0.0';
const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT;
module.exports = function(proxy, allowedHost) { module.exports = function(proxy, allowedHost) {
return { return {
...@@ -43,24 +47,39 @@ module.exports = function(proxy, allowedHost) { ...@@ -43,24 +47,39 @@ module.exports = function(proxy, allowedHost) {
// Instead, we establish a convention that only files in `public` directory // Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder. // 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%: // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> // <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`. // 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 // 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 files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through Webpack. If you just want to // 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. // use an image, put it in `src` and `import` it from JavaScript instead.
contentBase: paths.appPublic, contentBase: paths.appPublic,
contentBasePublicPath: paths.publicUrlOrPath,
// By default files from `contentBase` will not trigger a page reload. // By default files from `contentBase` will not trigger a page reload.
watchContentBase: true, watchContentBase: true,
// Enable hot reloading server. It will provide /sockjs-node/ endpoint // Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
// for the WebpackDevServer client so it can learn when the files were // for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point // updated. The WebpackDevServer client is included as an entry point
// in the Webpack development configuration. Note that only changes // in the webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser. // to CSS are currently hot reloaded. JS changes will refresh the browser.
hot: true, hot: true,
// It is important to tell WebpackDevServer to use the same "root" path // Use 'ws' instead of 'sockjs-node' on server since we're using native
// as we specified in the config. In development, we always serve from /. // websockets in `webpackHotDevClient`.
publicPath: '/', transportMode: 'ws',
// Prevent a WS client from getting injected as we're already including
// `webpackHotDevClient`.
injectClient: false,
// 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.
sockHost,
sockPath,
sockPort,
// 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),
// WebpackDevServer is noisy by default so we emit custom message instead // WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.hooks[...].tap` calls above. // by listening to the compiler events with `compiler.hooks[...].tap` calls above.
quiet: true, quiet: true,
...@@ -71,34 +90,41 @@ module.exports = function(proxy, allowedHost) { ...@@ -71,34 +90,41 @@ module.exports = function(proxy, allowedHost) {
watchOptions: { watchOptions: {
ignored: ignoredFiles(paths.appSrc), ignored: ignoredFiles(paths.appSrc),
}, },
// Enable HTTPS if the HTTPS environment variable is set to 'true' https: getHttpsConfig(),
https: protocol === 'https',
host, host,
overlay: false, overlay: false,
historyApiFallback: { historyApiFallback: {
// Paths with dots should still use the history fallback. // Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387. // See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true, disableDotRule: true,
index: paths.publicUrlOrPath,
}, },
public: allowedHost, public: allowedHost,
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks
proxy, proxy,
before(app, server) { before(app, server) {
if (fs.existsSync(paths.proxySetup)) { // Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware`
// This registers user provided middleware for proxy reasons // middlewares before `redirectServedPath` otherwise will not have any effect
require(paths.proxySetup)(app);
}
// This lets us fetch source contents from webpack for the error overlay // This lets us fetch source contents from webpack for the error overlay
app.use(evalSourceMapMiddleware(server)); app.use(evalSourceMapMiddleware(server));
// This lets us open files from the runtime error overlay. // This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware()); app.use(errorOverlayMiddleware());
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(app);
}
},
after(app) {
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
app.use(redirectServedPath(paths.publicUrlOrPath));
// This service worker file is effectively a 'no-op' that will reset any // This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination. // previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if // We do this in development to avoid hitting the production cache if
// it used the same host and port. // it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432 // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware()); app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
}, },
}; };
}; };
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,69 +3,85 @@ ...@@ -3,69 +3,85 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@babel/core": "7.2.2", "@babel/core": "7.9.0",
"@babel/plugin-proposal-decorators": "^7.4.4", "@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/runtime": "^7.7.7", "@babel/runtime": "^7.7.7",
"@loadable/component": "^5.10.1", "@loadable/component": "^5.10.1",
"@svgr/webpack": "4.1.0", "@svgr/webpack": "4.3.3",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@types/jest": "^24.9.1",
"@types/node": "^12.12.53",
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"@types/react-router-dom": "^5.1.5",
"@types/redux-logger": "^3.0.8",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"antd-mobile": "^2.3.1", "antd-mobile": "^2.3.1",
"autoprefixer": "^9.6.0", "autoprefixer": "^9.6.0",
"axios": "^0.19.2", "axios": "^0.19.2",
"babel-core": "7.0.0-bridge.0", "babel-core": "7.0.0-bridge.0",
"babel-eslint": "9.0.0", "babel-eslint": "10.1.0",
"babel-jest": "23.6.0", "babel-jest": "^24.9.0",
"babel-loader": "8.0.5", "babel-loader": "8.1.0",
"babel-plugin-named-asset-import": "^0.3.1", "babel-plugin-named-asset-import": "^0.3.6",
"babel-preset-react-app": "^7.0.2", "babel-preset-react-app": "^9.1.2",
"bfj": "6.1.1", "bfj": "6.1.1",
"callapp-lib": "^2.1.8", "callapp-lib": "^2.1.8",
"case-sensitive-paths-webpack-plugin": "2.2.0", "camelcase": "^5.3.1",
"case-sensitive-paths-webpack-plugin": "2.3.0",
"crypto-js": "^3.1.9-1", "crypto-js": "^3.1.9-1",
"css-loader": "1.0.0", "css-loader": "3.4.2",
"date-fns": "^2.14.0", "date-fns": "^2.14.0",
"dotenv": "6.0.0", "dotenv": "8.2.0",
"dotenv-expand": "4.2.0", "dotenv-expand": "5.1.0",
"eslint": "5.12.0", "eslint": "^6.6.0",
"eslint-config-react-app": "^3.0.8", "eslint-config-react-app": "^5.2.1",
"eslint-loader": "2.1.1", "eslint-loader": "3.0.3",
"eslint-plugin-flowtype": "2.50.1", "eslint-plugin-flowtype": "4.6.0",
"eslint-plugin-import": "2.14.0", "eslint-plugin-import": "2.20.1",
"eslint-plugin-jsx-a11y": "6.1.2", "eslint-plugin-jsx-a11y": "6.2.3",
"eslint-plugin-react": "7.12.4", "eslint-plugin-react": "7.19.0",
"file-loader": "2.0.0", "eslint-plugin-react-hooks": "^1.6.1",
"file-loader": "4.3.0",
"formik": "^1.5.8", "formik": "^1.5.8",
"fs-extra": "7.0.1", "fs-extra": "^8.1.0",
"html-webpack-plugin": "4.0.0-alpha.2", "html-webpack-plugin": "4.0.0-beta.11",
"html2canvas": "^1.0.0-rc.5", "html2canvas": "^1.0.0-rc.5",
"http-proxy-middleware": "^0.19.1", "http-proxy-middleware": "^0.19.1",
"identity-obj-proxy": "3.0.0", "identity-obj-proxy": "3.0.0",
"jest": "23.6.0", "jest": "24.9.0",
"jest-environment-jsdom-fourteen": "1.0.1",
"jest-pnp-resolver": "1.0.2", "jest-pnp-resolver": "1.0.2",
"jest-resolve": "23.6.0", "jest-resolve": "24.9.0",
"jest-watch-typeahead": "^0.2.1", "jest-watch-typeahead": "0.4.2",
"js-base64": "^2.5.1", "js-base64": "^2.5.1",
"js-cookie": "^2.2.0", "js-cookie": "^2.2.0",
"json-stringify-safe": "^5.0.1", "json-stringify-safe": "^5.0.1",
"less": "^3.9.0", "less": "^3.9.0",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"mini-css-extract-plugin": "0.5.0", "mini-css-extract-plugin": "0.9.0",
"node-sass": "^4.13.0", "node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "5.0.1", "optimize-css-assets-webpack-plugin": "5.0.3",
"pnp-webpack-plugin": "1.2.1", "pnp-webpack-plugin": "1.6.4",
"postcss-flexbugs-fixes": "4.1.0", "postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0", "postcss-loader": "3.0.0",
"postcss-preset-env": "6.5.0", "postcss-normalize": "8.0.1",
"postcss-preset-env": "6.7.0",
"postcss-safe-parser": "4.0.1", "postcss-safe-parser": "4.0.1",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"qrcode": "^1.3.3", "qrcode": "^1.3.3",
"qs": "^6.7.0", "qs": "^6.7.0",
"react": "^16.8.6", "react": "^16.13.1",
"react-ace": "^8.0.0", "react-ace": "^8.0.0",
"react-app-polyfill": "^0.2.2", "react-app-polyfill": "^1.0.6",
"react-copy-to-clipboard": "^5.0.1", "react-copy-to-clipboard": "^5.0.1",
"react-dev-utils": "^8.0.0", "react-dev-utils": "^10.2.1",
"react-dom": "^16.8.6", "react-dom": "^16.13.1",
"react-infinite-scroller": "^1.2.4", "react-infinite-scroller": "^1.2.4",
"react-lazy-load": "^3.0.13", "react-lazy-load": "^3.0.13",
"react-mobile-swiper": "^1.1.4", "react-mobile-swiper": "^1.1.4",
...@@ -77,21 +93,25 @@ ...@@ -77,21 +93,25 @@
"redux-immutable": "^4.0.0", "redux-immutable": "^4.0.0",
"redux-logger": "^3.0.6", "redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0", "redux-thunk": "^2.3.0",
"resolve": "1.10.0", "resolve": "1.15.0",
"sass-loader": "^7.1.0", "resolve-url-loader": "3.1.1",
"sass-loader": "8.0.2",
"sass-resources-loader": "^2.0.0", "sass-resources-loader": "^2.0.0",
"semver": "6.3.0",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
"store2": "^2.11.2", "store2": "^2.11.2",
"style-loader": "0.23.1", "style-loader": "0.23.1",
"swiper": "^4.5.1", "swiper": "^4.5.1",
"terser-webpack-plugin": "1.2.2", "terser-webpack-plugin": "2.3.5",
"url-loader": "1.1.2", "ts-pnp": "1.1.6",
"typescript": "^3.7.5",
"url-loader": "2.3.0",
"video.js": "^7.6.5", "video.js": "^7.6.5",
"web-launch-app": "^2.1.9", "web-launch-app": "^2.1.9",
"webpack": "4.28.3", "webpack": "4.42.0",
"webpack-dev-server": "3.1.14", "webpack-dev-server": "3.10.3",
"webpack-manifest-plugin": "2.0.4", "webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "3.6.3" "workbox-webpack-plugin": "4.3.1"
}, },
"scripts": { "scripts": {
"start": "node scripts/start.js", "start": "node scripts/start.js",
......
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, compose } from 'redux' import {createStore, applyMiddleware, compose} from 'redux'
import { Provider } from 'react-redux' import {Provider} from 'react-redux'
import { BrowserRouter as Router } from 'react-router-dom' import {BrowserRouter as Router} from 'react-router-dom'
import thunk from 'redux-thunk' import thunk from 'redux-thunk'
import logger from 'redux-logger' import logger from 'redux-logger'
import rootReducers from './store' import rootReducers from './store'
...@@ -11,8 +11,8 @@ import App from './App' ...@@ -11,8 +11,8 @@ import App from './App'
const reduxDevToolOptions = process.env.REACT_APP_BUILD_ENV === 'production' ? {} : {trace: true, traceLimit: 25} const reduxDevToolOptions = process.env.REACT_APP_BUILD_ENV === 'production' ? {} : {trace: true, traceLimit: 25}
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(reduxDevToolOptions) || compose; (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__(reduxDevToolOptions) || compose;
const store = createStore( const store = createStore(
rootReducers, rootReducers,
...@@ -27,4 +27,5 @@ ReactDOM.render( ...@@ -27,4 +27,5 @@ ReactDOM.render(
<App/> <App/>
</Router> </Router>
</Provider>, </Provider>,
document.getElementById('root')); document.getElementById('root')
\ No newline at end of file );
\ No newline at end of file
import { combineReducers } from "redux" import { combineReducers } from "redux"
import myCourses from "@/components/study/myCourses/reducers" import myCourses from "src/components/study/myCourses/reducers"
import courseInfo from "@/components/detail/reducers" import courseInfo from "src/components/detail/reducers"
import user from "./userReducer" import user from "./userReducer"
import country from "@/components/country/countryRedux" import country from "src/components/country/countryRedux"
import intelligentRecommend from "@components/intelligent-recommend/store" import intelligentRecommend from "src/components/intelligent-recommend/store"
import anniversary2020Question from "@components/activity/2020-717/question/store/reducer" //2020周年庆活动答题页 import anniversary2020Question from "src/components/activity/2020-717/question/store/reducer" //2020周年庆活动答题页
import noTraceValidation from "./no-trace-validation/reducer" import noTraceValidation from "./no-trace-validation/reducer"
const reducer = combineReducers({ const reducer = combineReducers({
......
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment