mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 01:20:24 +03:00
Updated coding styles and test configs
This commit is contained in:
parent
08488e9bad
commit
fac3edaea7
10 changed files with 188 additions and 88 deletions
|
@ -1,4 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
@ -7,7 +6,8 @@ const paths = require('./paths');
|
||||||
// Make sure that including paths.js after env.js will read .env variables.
|
// Make sure that including paths.js after env.js will read .env variables.
|
||||||
delete require.cache[require.resolve('./paths')];
|
delete require.cache[require.resolve('./paths')];
|
||||||
|
|
||||||
const NODE_ENV = process.env.NODE_ENV;
|
const { NODE_ENV } = process.env;
|
||||||
|
|
||||||
if (!NODE_ENV) {
|
if (!NODE_ENV) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The NODE_ENV environment variable is required but was not specified.'
|
'The NODE_ENV environment variable is required but was not specified.'
|
||||||
|
@ -18,6 +18,7 @@ if (!NODE_ENV) {
|
||||||
const 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
|
||||||
// since normally you expect tests to produce the same
|
// since normally you expect tests to produce the same
|
||||||
// results for everyone
|
// results for everyone
|
||||||
|
@ -30,7 +31,7 @@ const dotenvFiles = [
|
||||||
// that have already been set. Variable expansion is supported in .env files.
|
// that have already been set. Variable expansion is supported in .env files.
|
||||||
// https://github.com/motdotla/dotenv
|
// https://github.com/motdotla/dotenv
|
||||||
// https://github.com/motdotla/dotenv-expand
|
// https://github.com/motdotla/dotenv-expand
|
||||||
dotenvFiles.forEach(dotenvFile => {
|
dotenvFiles.forEach((dotenvFile) => {
|
||||||
if (fs.existsSync(dotenvFile)) {
|
if (fs.existsSync(dotenvFile)) {
|
||||||
require('dotenv-expand')(
|
require('dotenv-expand')(
|
||||||
require('dotenv').config({
|
require('dotenv').config({
|
||||||
|
@ -50,10 +51,11 @@ dotenvFiles.forEach(dotenvFile => {
|
||||||
// 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());
|
||||||
|
|
||||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||||
.split(path.delimiter)
|
.split(path.delimiter)
|
||||||
.filter(folder => folder && !path.isAbsolute(folder))
|
.filter((folder) => folder && !path.isAbsolute(folder))
|
||||||
.map(folder => path.resolve(appDirectory, folder))
|
.map((folder) => path.resolve(appDirectory, folder))
|
||||||
.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
|
||||||
|
@ -62,16 +64,19 @@ const REACT_APP = /^REACT_APP_/i;
|
||||||
|
|
||||||
function getClientEnvironment(publicUrl) {
|
function getClientEnvironment(publicUrl) {
|
||||||
const raw = Object.keys(process.env)
|
const raw = Object.keys(process.env)
|
||||||
.filter(key => REACT_APP.test(key))
|
.filter((key) => REACT_APP.test(key))
|
||||||
.reduce(
|
.reduce(
|
||||||
(env, key) => {
|
(env, key) => {
|
||||||
env[key] = process.env[key];
|
env[key] = process.env[key];
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
// Useful for determining whether we’re running in production mode.
|
// Useful for determining whether we’re running in production mode.
|
||||||
// Most importantly, it switches React into the correct mode.
|
// Most importantly, it switches React into the correct mode.
|
||||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||||
|
|
||||||
// Useful for resolving the correct path to static assets in `public`.
|
// Useful for resolving the correct path to static assets in `public`.
|
||||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||||
// 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
|
||||||
|
@ -79,10 +84,12 @@ function getClientEnvironment(publicUrl) {
|
||||||
PUBLIC_URL: publicUrl,
|
PUBLIC_URL: publicUrl,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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;
|
||||||
}, {}),
|
}, {}),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// This is a custom Jest transformer turning style imports into empty objects.
|
// This is a custom Jest transformer turning style imports into empty objects.
|
||||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
@ -7,22 +6,23 @@ const url = require('url');
|
||||||
// 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;
|
const envPublicUrl = process.env.PUBLIC_URL;
|
||||||
|
|
||||||
function ensureSlash(inputPath, needsSlash) {
|
function ensureSlash(inputPath, needsSlash) {
|
||||||
const hasSlash = inputPath.endsWith('/');
|
const hasSlash = inputPath.endsWith('/');
|
||||||
|
|
||||||
if (hasSlash && !needsSlash) {
|
if (hasSlash && !needsSlash) {
|
||||||
return inputPath.substr(0, inputPath.length - 1);
|
return inputPath.substr(0, inputPath.length - 1);
|
||||||
} else if (!hasSlash && needsSlash) {
|
} else if (!hasSlash && needsSlash) {
|
||||||
return `${inputPath}/`;
|
return `${inputPath}/`;
|
||||||
} else {
|
|
||||||
return inputPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return inputPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPublicUrl = appPackageJson =>
|
const getPublicUrl = (appPackageJson) =>
|
||||||
envPublicUrl || require(appPackageJson).homepage;
|
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
|
||||||
|
@ -35,6 +35,7 @@ function getServedPath(appPackageJson) {
|
||||||
const publicUrl = getPublicUrl(appPackageJson);
|
const publicUrl = getPublicUrl(appPackageJson);
|
||||||
const servedUrl =
|
const servedUrl =
|
||||||
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
|
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : '/');
|
||||||
|
|
||||||
return ensureSlash(servedUrl, true);
|
return ensureSlash(servedUrl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +55,8 @@ const moduleFileExtensions = [
|
||||||
|
|
||||||
// Resolve file paths in the same order as webpack
|
// Resolve file paths in the same order as webpack
|
||||||
const resolveModule = (resolveFn, filePath) => {
|
const resolveModule = (resolveFn, filePath) => {
|
||||||
const extension = moduleFileExtensions.find(extension =>
|
const extension = moduleFileExtensions.find((extension) =>
|
||||||
fs.existsSync(resolveFn(`${filePath}.${extension}`))
|
fs.existsSync(resolveFn(`${filePath}.${extension}`)));
|
||||||
);
|
|
||||||
|
|
||||||
if (extension) {
|
if (extension) {
|
||||||
return resolveFn(`${filePath}.${extension}`);
|
return resolveFn(`${filePath}.${extension}`);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
@ -18,15 +17,15 @@ 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 getClientEnvironment = require('./env');
|
|
||||||
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
||||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
|
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
|
||||||
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
||||||
|
const getClientEnvironment = require('./env');
|
||||||
|
const paths = require('./paths');
|
||||||
|
|
||||||
// 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';
|
||||||
|
@ -42,7 +41,8 @@ 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) {
|
/* eslint-disable complexity */
|
||||||
|
module.exports = (webpackEnv) => {
|
||||||
const isEnvDevelopment = webpackEnv === 'development';
|
const isEnvDevelopment = webpackEnv === 'development';
|
||||||
const isEnvProduction = webpackEnv === 'production';
|
const isEnvProduction = webpackEnv === 'production';
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ module.exports = function(webpackEnv) {
|
||||||
const publicPath = isEnvProduction
|
const publicPath = isEnvProduction
|
||||||
? paths.servedPath
|
? paths.servedPath
|
||||||
: isEnvDevelopment && '/';
|
: isEnvDevelopment && '/';
|
||||||
|
|
||||||
// Some apps do not use client-side routing with pushState.
|
// Some apps do not use client-side routing with pushState.
|
||||||
// For these, "homepage" can be set to "." to enable relative asset paths.
|
// For these, "homepage" can be set to "." to enable relative asset paths.
|
||||||
const shouldUseRelativeAssetPaths = publicPath === './';
|
const shouldUseRelativeAssetPaths = publicPath === './';
|
||||||
|
@ -62,6 +63,7 @@ module.exports = function(webpackEnv) {
|
||||||
const publicUrl = isEnvProduction
|
const publicUrl = isEnvProduction
|
||||||
? publicPath.slice(0, -1)
|
? publicPath.slice(0, -1)
|
||||||
: isEnvDevelopment && '';
|
: isEnvDevelopment && '';
|
||||||
|
|
||||||
// Get environment variables to inject into our app.
|
// Get environment variables to inject into our app.
|
||||||
const env = getClientEnvironment(publicUrl);
|
const env = getClientEnvironment(publicUrl);
|
||||||
|
|
||||||
|
@ -81,11 +83,13 @@ module.exports = function(webpackEnv) {
|
||||||
options: cssOptions,
|
options: cssOptions,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
// Options for PostCSS as we reference these options twice
|
// Options for PostCSS as we reference these options twice
|
||||||
// Adds vendor prefixing based on your specified browser support in
|
// Adds vendor prefixing based on your specified browser support in
|
||||||
// package.json
|
// package.json
|
||||||
loader: require.resolve('postcss-loader'),
|
loader: require.resolve('postcss-loader'),
|
||||||
options: {
|
options: {
|
||||||
|
|
||||||
// Necessary for external CSS imports to work
|
// Necessary for external CSS imports to work
|
||||||
// https://github.com/facebook/create-react-app/issues/2677
|
// https://github.com/facebook/create-react-app/issues/2677
|
||||||
ident: 'postcss',
|
ident: 'postcss',
|
||||||
|
@ -102,6 +106,7 @@ module.exports = function(webpackEnv) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
if (preProcessor) {
|
if (preProcessor) {
|
||||||
loaders.push({
|
loaders.push({
|
||||||
loader: require.resolve(preProcessor),
|
loader: require.resolve(preProcessor),
|
||||||
|
@ -110,11 +115,13 @@ module.exports = function(webpackEnv) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return loaders;
|
return loaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
|
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
|
||||||
|
|
||||||
// Stop compilation early in production
|
// Stop compilation early in production
|
||||||
bail: isEnvProduction,
|
bail: isEnvProduction,
|
||||||
devtool: isEnvProduction
|
devtool: isEnvProduction
|
||||||
|
@ -122,9 +129,11 @@ module.exports = function(webpackEnv) {
|
||||||
? 'source-map'
|
? 'source-map'
|
||||||
: false
|
: false
|
||||||
: 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: [
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -137,45 +146,55 @@ module.exports = function(webpackEnv) {
|
||||||
// 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
|
||||||
// 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),
|
].filter(Boolean),
|
||||||
output: {
|
output: {
|
||||||
|
|
||||||
// The build folder.
|
// The build folder.
|
||||||
path: isEnvProduction ? paths.appBuild : undefined,
|
path: isEnvProduction ? paths.appBuild : undefined,
|
||||||
|
|
||||||
// Add /* filename */ comments to generated require()s in the output.
|
// Add /* filename */ comments to generated require()s in the output.
|
||||||
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
|
||||||
? 'static/js/[name].[chunkhash:8].js'
|
? 'static/js/[name].[chunkhash:8].js'
|
||||||
: isEnvDevelopment && 'static/js/bundle.js',
|
: isEnvDevelopment && 'static/js/bundle.js',
|
||||||
|
|
||||||
// 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
|
||||||
? 'static/js/[name].[chunkhash:8].chunk.js'
|
? 'static/js/[name].[chunkhash:8].chunk.js'
|
||||||
: isEnvDevelopment && 'static/js/[name].chunk.js',
|
: isEnvDevelopment && 'static/js/[name].chunk.js',
|
||||||
|
|
||||||
// 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.
|
// We use "/" in development.
|
||||||
publicPath: 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
|
path
|
||||||
.relative(paths.appSrc, info.absoluteResourcePath)
|
.relative(paths.appSrc, info.absoluteResourcePath)
|
||||||
.replace(/\\/g, '/')
|
.replace(/\\/g, '/')
|
||||||
: isEnvDevelopment &&
|
: isEnvDevelopment &&
|
||||||
(info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
|
((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: isEnvProduction,
|
minimize: isEnvProduction,
|
||||||
minimizer: [
|
minimizer: [
|
||||||
|
|
||||||
// This is only used in production mode
|
// This is only used in production mode
|
||||||
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 minfication 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'
|
||||||
|
@ -186,11 +205,13 @@ module.exports = function(webpackEnv) {
|
||||||
compress: {
|
compress: {
|
||||||
ecma: 5,
|
ecma: 5,
|
||||||
warnings: false,
|
warnings: false,
|
||||||
|
|
||||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||||
// https://github.com/facebook/create-react-app/issues/2376
|
// https://github.com/facebook/create-react-app/issues/2376
|
||||||
// Pending further investigation:
|
// Pending further investigation:
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||||
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 futher investigation:
|
||||||
|
@ -203,35 +224,42 @@ module.exports = function(webpackEnv) {
|
||||||
output: {
|
output: {
|
||||||
ecma: 5,
|
ecma: 5,
|
||||||
comments: false,
|
comments: false,
|
||||||
|
|
||||||
// Turned on because emoji and regex is not minified properly using default
|
// Turned on because emoji and regex is not minified properly using default
|
||||||
// https://github.com/facebook/create-react-app/issues/2488
|
// https://github.com/facebook/create-react-app/issues/2488
|
||||||
ascii_only: true,
|
ascii_only: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use multi-process parallel running to improve the build speed
|
// Use multi-process parallel running to improve the build speed
|
||||||
// Default number of concurrent runs: os.cpus().length - 1
|
// Default number of concurrent runs: os.cpus().length - 1
|
||||||
parallel: true,
|
parallel: true,
|
||||||
|
|
||||||
// Enable file caching
|
// Enable file caching
|
||||||
cache: true,
|
cache: true,
|
||||||
sourceMap: shouldUseSourceMap,
|
sourceMap: shouldUseSourceMap,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// This is only used in production mode
|
// This is only used in production mode
|
||||||
new OptimizeCSSAssetsPlugin({
|
new OptimizeCSSAssetsPlugin({
|
||||||
cssProcessorOptions: {
|
cssProcessorOptions: {
|
||||||
parser: safePostCssParser,
|
parser: safePostCssParser,
|
||||||
map: shouldUseSourceMap
|
map: shouldUseSourceMap
|
||||||
? {
|
? {
|
||||||
// `inline: false` forces the sourcemap to be output into a
|
|
||||||
// separate file
|
// `inline: false` forces the sourcemap to be output into a
|
||||||
inline: false,
|
// separate file
|
||||||
// `annotation: true` appends the sourceMappingURL to the end of
|
inline: false,
|
||||||
// the css file, helping the browser find the sourcemap
|
|
||||||
annotation: true,
|
// `annotation: true` appends the sourceMappingURL to the end of
|
||||||
}
|
// the css file, helping the browser find the sourcemap
|
||||||
|
annotation: true,
|
||||||
|
}
|
||||||
: false,
|
: false,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Automatically split vendor and commons
|
// Automatically split vendor and commons
|
||||||
// https://twitter.com/wSokra/status/969633336732905474
|
// https://twitter.com/wSokra/status/969633336732905474
|
||||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||||
|
@ -239,19 +267,23 @@ module.exports = function(webpackEnv) {
|
||||||
chunks: 'all',
|
chunks: 'all',
|
||||||
name: false,
|
name: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 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,
|
runtimeChunk: true,
|
||||||
},
|
},
|
||||||
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' ].concat(
|
||||||
|
|
||||||
// It is guaranteed to exist because we tweak it in `env.js`
|
// It is guaranteed to exist because we tweak it in `env.js`
|
||||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
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:
|
||||||
|
@ -259,27 +291,31 @@ module.exports = function(webpackEnv) {
|
||||||
// `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}`)
|
.map((ext) => `.${ext}`)
|
||||||
.filter(ext => useTypeScript || !ext.includes('ts')),
|
.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',
|
||||||
},
|
},
|
||||||
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
|
||||||
// guards against forgotten dependencies and such.
|
// guards against forgotten dependencies and such.
|
||||||
PnpWebpackPlugin,
|
PnpWebpackPlugin,
|
||||||
|
|
||||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||||
// This often causes confusion because we only process files within src/ with babel.
|
// This often causes confusion because we only process files within src/ with babel.
|
||||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
// 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 ]),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
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),
|
||||||
|
@ -288,6 +324,7 @@ module.exports = function(webpackEnv) {
|
||||||
module: {
|
module: {
|
||||||
strictExportPresence: true,
|
strictExportPresence: true,
|
||||||
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 } },
|
||||||
|
|
||||||
|
@ -301,7 +338,7 @@ module.exports = function(webpackEnv) {
|
||||||
options: {
|
options: {
|
||||||
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
||||||
eslintPath: require.resolve('eslint'),
|
eslintPath: require.resolve('eslint'),
|
||||||
|
|
||||||
},
|
},
|
||||||
loader: require.resolve('eslint-loader'),
|
loader: require.resolve('eslint-loader'),
|
||||||
},
|
},
|
||||||
|
@ -309,21 +346,24 @@ module.exports = function(webpackEnv) {
|
||||||
include: paths.appSrc,
|
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: [
|
||||||
|
|
||||||
// "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.
|
||||||
{
|
{
|
||||||
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: 10000,
|
||||||
name: 'static/media/[name].[hash:8].[ext]',
|
name: 'static/media/[name].[hash:8].[ext]',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Process application JS with Babel.
|
// Process application JS with Babel.
|
||||||
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
|
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
|
||||||
{
|
{
|
||||||
|
@ -334,7 +374,7 @@ module.exports = function(webpackEnv) {
|
||||||
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'),
|
||||||
|
@ -348,6 +388,7 @@ module.exports = function(webpackEnv) {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -356,6 +397,7 @@ module.exports = function(webpackEnv) {
|
||||||
compact: isEnvProduction,
|
compact: isEnvProduction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Process any JS outside of the app with Babel.
|
// Process any JS outside of the app with Babel.
|
||||||
// Unlike the application JS, we only compile the standard ES features.
|
// Unlike the application JS, we only compile the standard ES features.
|
||||||
{
|
{
|
||||||
|
@ -374,7 +416,7 @@ module.exports = function(webpackEnv) {
|
||||||
],
|
],
|
||||||
cacheDirectory: true,
|
cacheDirectory: true,
|
||||||
cacheCompression: isEnvProduction,
|
cacheCompression: isEnvProduction,
|
||||||
|
|
||||||
// If an error happens in a package, it's possible to be
|
// If an error happens in a package, it's possible to be
|
||||||
// because it was compiled. Thus, we don't want the browser
|
// because it was compiled. Thus, we don't want the browser
|
||||||
// debugger to show the original code. Instead, the code
|
// debugger to show the original code. Instead, the code
|
||||||
|
@ -382,6 +424,7 @@ module.exports = function(webpackEnv) {
|
||||||
sourceMaps: false,
|
sourceMaps: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// "postcss" loader applies autoprefixer to our CSS.
|
// "postcss" loader applies autoprefixer to our CSS.
|
||||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||||
|
@ -396,12 +439,14 @@ module.exports = function(webpackEnv) {
|
||||||
importLoaders: 1,
|
importLoaders: 1,
|
||||||
sourceMap: isEnvProduction && shouldUseSourceMap,
|
sourceMap: isEnvProduction && shouldUseSourceMap,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 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.
|
||||||
// Remove this when webpack adds a warning or an error for this.
|
// Remove this when webpack adds a warning or an error for this.
|
||||||
// See https://github.com/webpack/webpack/issues/6571
|
// See https://github.com/webpack/webpack/issues/6571
|
||||||
sideEffects: true,
|
sideEffects: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||||
// using the extension .module.css
|
// using the extension .module.css
|
||||||
{
|
{
|
||||||
|
@ -413,6 +458,7 @@ module.exports = function(webpackEnv) {
|
||||||
getLocalIdent: getCSSModuleLocalIdent,
|
getLocalIdent: getCSSModuleLocalIdent,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
// Opt-in support for SASS (using .scss or .sass extensions).
|
// Opt-in support for SASS (using .scss or .sass extensions).
|
||||||
// By default we support SASS Modules with the
|
// By default we support SASS Modules with the
|
||||||
// extensions .module.scss or .module.sass
|
// extensions .module.scss or .module.sass
|
||||||
|
@ -426,12 +472,14 @@ module.exports = function(webpackEnv) {
|
||||||
},
|
},
|
||||||
'sass-loader'
|
'sass-loader'
|
||||||
),
|
),
|
||||||
|
|
||||||
// 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.
|
||||||
// Remove this when webpack adds a warning or an error for this.
|
// Remove this when webpack adds a warning or an error for this.
|
||||||
// See https://github.com/webpack/webpack/issues/6571
|
// See https://github.com/webpack/webpack/issues/6571
|
||||||
sideEffects: true,
|
sideEffects: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Adds support for CSS Modules, but using SASS
|
// Adds support for CSS Modules, but using SASS
|
||||||
// using the extension .module.scss or .module.sass
|
// using the extension .module.scss or .module.sass
|
||||||
{
|
{
|
||||||
|
@ -446,6 +494,7 @@ module.exports = function(webpackEnv) {
|
||||||
'sass-loader'
|
'sass-loader'
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
// "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.
|
||||||
|
@ -453,15 +502,17 @@ module.exports = function(webpackEnv) {
|
||||||
// that fall through the other loaders.
|
// that fall through the other loaders.
|
||||||
{
|
{
|
||||||
loader: require.resolve('file-loader'),
|
loader: require.resolve('file-loader'),
|
||||||
|
|
||||||
// Exclude `js` files to keep "css" loader working as it injects
|
// Exclude `js` files to keep "css" loader working as it injects
|
||||||
// its runtime that would otherwise be processed through "file" loader.
|
// its runtime that would otherwise be processed through "file" loader.
|
||||||
// Also exclude `html` and `json` extensions so they get processed
|
// Also exclude `html` and `json` extensions so they get processed
|
||||||
// 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: 'static/media/[name].[hash:8].[ext]',
|
name: 'static/media/[name].[hash:8].[ext]',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// ** STOP ** Are you adding a new loader?
|
// ** STOP ** Are you adding a new loader?
|
||||||
// Make sure to add the new loader(s) before the "file" loader.
|
// Make sure to add the new loader(s) before the "file" loader.
|
||||||
],
|
],
|
||||||
|
@ -469,6 +520,7 @@ module.exports = function(webpackEnv) {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
||||||
// Generates an `index.html` file with the <script> injected.
|
// Generates an `index.html` file with the <script> injected.
|
||||||
new HtmlWebpackPlugin(
|
new HtmlWebpackPlugin(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
|
@ -479,27 +531,29 @@ module.exports = function(webpackEnv) {
|
||||||
},
|
},
|
||||||
isEnvProduction
|
isEnvProduction
|
||||||
? {
|
? {
|
||||||
minify: {
|
minify: {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
removeRedundantAttributes: true,
|
removeRedundantAttributes: true,
|
||||||
useShortDoctype: true,
|
useShortDoctype: true,
|
||||||
removeEmptyAttributes: true,
|
removeEmptyAttributes: true,
|
||||||
removeStyleLinkTypeAttributes: true,
|
removeStyleLinkTypeAttributes: true,
|
||||||
keepClosingSlash: true,
|
keepClosingSlash: true,
|
||||||
minifyJS: true,
|
minifyJS: true,
|
||||||
minifyCSS: true,
|
minifyCSS: true,
|
||||||
minifyURLs: true,
|
minifyURLs: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
// 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 &&
|
isEnvProduction &&
|
||||||
shouldInlineRuntimeChunk &&
|
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="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||||
|
@ -507,21 +561,26 @@ module.exports = function(webpackEnv) {
|
||||||
// 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.
|
// 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.
|
||||||
new ModuleNotFoundPlugin(paths.appPath),
|
new ModuleNotFoundPlugin(paths.appPath),
|
||||||
|
|
||||||
// Makes some environment variables available to the JS code, for example:
|
// Makes some environment variables available to the JS code, for example:
|
||||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||||
// It is absolutely essential that NODE_ENV is set to production
|
// It is absolutely essential that NODE_ENV is set to production
|
||||||
// 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 (currently CSS only):
|
||||||
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
|
isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
|
||||||
|
|
||||||
// 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
|
||||||
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.
|
||||||
|
@ -530,40 +589,47 @@ module.exports = function(webpackEnv) {
|
||||||
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: 'static/css/[name].[contenthash:8].css',
|
filename: 'static/css/[name].[contenthash:8].css',
|
||||||
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Generate a manifest file which contains a mapping of all asset filenames
|
// Generate a manifest file which contains a mapping of all asset filenames
|
||||||
// to their corresponding output file so that tools can pick it up without
|
// to their corresponding output file so that tools can pick it up without
|
||||||
// having to parse `index.html`.
|
// having to parse `index.html`.
|
||||||
new ManifestPlugin({
|
new ManifestPlugin({
|
||||||
fileName: 'asset-manifest.json',
|
fileName: 'asset-manifest.json',
|
||||||
publicPath: publicPath,
|
publicPath,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 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: `${publicUrl}/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 URLs containing a dot, as they're likely a resource in
|
||||||
// public/ and not a SPA route
|
// public/ and not a SPA route
|
||||||
new RegExp('/[^/]+\\.[^/]+$'),
|
new RegExp('/[^/]+\\.[^/]+$'),
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// TypeScript type checking
|
// TypeScript type checking
|
||||||
useTypeScript &&
|
useTypeScript &&
|
||||||
new ForkTsCheckerWebpackPlugin({
|
new ForkTsCheckerWebpackPlugin({
|
||||||
|
@ -594,6 +660,7 @@ module.exports = function(webpackEnv) {
|
||||||
formatter: typescriptFormatter,
|
formatter: typescriptFormatter,
|
||||||
}),
|
}),
|
||||||
].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: {
|
||||||
|
@ -603,6 +670,7 @@ module.exports = function(webpackEnv) {
|
||||||
tls: 'empty',
|
tls: 'empty',
|
||||||
child_process: 'empty',
|
child_process: 'empty',
|
||||||
},
|
},
|
||||||
|
|
||||||
// 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,
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
'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 paths = require('./paths');
|
const paths = require('./paths');
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
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';
|
||||||
|
|
||||||
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:
|
||||||
// https://github.com/webpack/webpack-dev-server/issues/887
|
// https://github.com/webpack/webpack-dev-server/issues/887
|
||||||
|
@ -30,11 +30,14 @@ module.exports = function(proxy, allowedHost) {
|
||||||
// really know what you're doing with a special environment variable.
|
// really know what you're doing with a special environment variable.
|
||||||
disableHostCheck:
|
disableHostCheck:
|
||||||
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
|
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
|
||||||
|
|
||||||
// Enable gzip compression of generated files.
|
// Enable gzip compression of generated files.
|
||||||
compress: true,
|
compress: true,
|
||||||
|
|
||||||
// Silence WebpackDevServer's own logs since they're generally not useful.
|
// Silence WebpackDevServer's own logs since they're generally not useful.
|
||||||
// It will still show compile warnings and errors with this setting.
|
// It will still show compile warnings and errors with this setting.
|
||||||
clientLogLevel: 'none',
|
clientLogLevel: 'none',
|
||||||
|
|
||||||
// By default WebpackDevServer serves physical files from current directory
|
// By default WebpackDevServer serves physical files from current directory
|
||||||
// in addition to all the virtual build products that it serves from memory.
|
// in addition to all the virtual build products that it serves from memory.
|
||||||
// This is confusing because those files won’t automatically be available in
|
// This is confusing because those files won’t automatically be available in
|
||||||
|
@ -50,20 +53,25 @@ module.exports = function(proxy, allowedHost) {
|
||||||
// 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,
|
||||||
|
|
||||||
// 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 /sockjs-node/ 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
|
// It is important to tell WebpackDevServer to use the same "root" path
|
||||||
// as we specified in the config. In development, we always serve from /.
|
// as we specified in the config. In development, we always serve from /.
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
|
|
||||||
// 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,
|
||||||
|
|
||||||
// Reportedly, this avoids CPU overload on some systems.
|
// Reportedly, this avoids CPU overload on some systems.
|
||||||
// https://github.com/facebook/create-react-app/issues/293
|
// https://github.com/facebook/create-react-app/issues/293
|
||||||
// src/node_modules is not ignored to support absolute imports
|
// src/node_modules is not ignored to support absolute imports
|
||||||
|
@ -71,11 +79,13 @@ 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'
|
// Enable HTTPS if the HTTPS environment variable is set to 'true'
|
||||||
https: protocol === 'https',
|
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,
|
||||||
|
@ -90,6 +100,7 @@ module.exports = function(proxy, allowedHost) {
|
||||||
|
|
||||||
// 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());
|
||||||
|
|
||||||
|
|
|
@ -8,29 +8,37 @@ module.exports = {
|
||||||
'!src/**/provideServices.js',
|
'!src/**/provideServices.js',
|
||||||
'!src/container/*.js',
|
'!src/container/*.js',
|
||||||
],
|
],
|
||||||
|
resolver: 'jest-pnp-resolver',
|
||||||
setupFiles: [
|
setupFiles: [
|
||||||
'<rootDir>/config/polyfills.js',
|
'react-app-polyfill/jsdom',
|
||||||
'<rootDir>/config/setupEnzyme.js',
|
'<rootDir>/config/setupEnzyme.js',
|
||||||
],
|
],
|
||||||
testMatch: [ '<rootDir>/test/**/*.test.{js,jsx,mjs}' ],
|
testMatch: [ '<rootDir>/test/**/*.test.{js,jsx,ts,tsx}' ],
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'jsdom',
|
||||||
testURL: 'http://localhost',
|
testURL: 'http://localhost',
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.(js|jsx|mjs)$': '<rootDir>/node_modules/babel-jest',
|
'^.+\\.(js|jsx|mjs)$': '<rootDir>/node_modules/babel-jest',
|
||||||
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
|
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
|
||||||
'^(?!.*\\.(js|jsx|mjs|css|json)$)': '<rootDir>/config/jest/fileTransform.js',
|
'^(?!.*\\.(js|jsx|mjs|css|json)$)': '<rootDir>/config/jest/fileTransform.js',
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: [ '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$' ],
|
transformIgnorePatterns: [
|
||||||
|
'[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$',
|
||||||
|
'^.+\\.module\\.(css|sass|scss)$',
|
||||||
|
],
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^react-native$': 'react-native-web',
|
'^react-native$': 'react-native-web',
|
||||||
|
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
|
||||||
},
|
},
|
||||||
moduleFileExtensions: [
|
moduleFileExtensions: [
|
||||||
'web.js',
|
'web.js',
|
||||||
'js',
|
'js',
|
||||||
|
'web.ts',
|
||||||
|
'ts',
|
||||||
|
'web.tsx',
|
||||||
|
'tsx',
|
||||||
'json',
|
'json',
|
||||||
'web.jsx',
|
'web.jsx',
|
||||||
'jsx',
|
'jsx',
|
||||||
'node',
|
'node',
|
||||||
'mjs',
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
'use strict';
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
// 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';
|
||||||
|
@ -7,14 +7,13 @@ process.env.NODE_ENV = 'development';
|
||||||
// Makes the script crash on unhandled rejections instead of silently
|
// Makes the script crash on unhandled rejections instead of silently
|
||||||
// ignoring them. In the future, promise rejections that are not handled will
|
// ignoring them. In the future, promise rejections that are not handled will
|
||||||
// terminate the Node.js process with a non-zero exit code.
|
// terminate the Node.js process with a non-zero exit code.
|
||||||
process.on('unhandledRejection', err => {
|
process.on('unhandledRejection', (err) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ensure environment variables are read.
|
// Ensure environment variables are read.
|
||||||
require('../config/env');
|
require('../config/env');
|
||||||
|
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
@ -28,6 +27,7 @@ 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 { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||||
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');
|
||||||
|
@ -36,12 +36,13 @@ const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||||
const isInteractive = process.stdout.isTTY;
|
const isInteractive = process.stdout.isTTY;
|
||||||
|
|
||||||
// Warn and crash if required files are missing
|
// Warn and crash if required files are missing
|
||||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
if (!checkRequiredFiles([ paths.appHtml, paths.appIndexJs ])) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tools like Cloud9 rely on this.
|
// Tools like Cloud9 rely on this.
|
||||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
const DEFAULT_PORT = 3000;
|
||||||
|
const PORT = parseInt(process.env.PORT) || DEFAULT_PORT;
|
||||||
const HOST = process.env.HOST || '0.0.0.0';
|
const HOST = process.env.HOST || '0.0.0.0';
|
||||||
|
|
||||||
if (process.env.HOST) {
|
if (process.env.HOST) {
|
||||||
|
@ -53,7 +54,7 @@ if (process.env.HOST) {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
`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('http://bit.ly/CRA-advanced-config')}`
|
`Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`
|
||||||
|
@ -61,57 +62,64 @@ if (process.env.HOST) {
|
||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We require that you explictly set browsers and do not fall back to
|
|
||||||
// browserslist defaults.
|
|
||||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
|
||||||
checkBrowsers(paths.appPath, isInteractive)
|
checkBrowsers(paths.appPath, isInteractive)
|
||||||
.then(() => {
|
.then(() =>
|
||||||
|
|
||||||
// We attempt to use the default port but if it is busy, we offer the user to
|
// We attempt to use the default port but if it is busy, we offer the user to
|
||||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||||
return choosePort(HOST, DEFAULT_PORT);
|
choosePort(HOST, PORT))
|
||||||
})
|
.then((port) => {
|
||||||
.then(port => {
|
if (port === null) {
|
||||||
if (port == null) {
|
|
||||||
// We have not found a port.
|
// We have not found a port.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 urls = prepareUrls(protocol, HOST, port);
|
const urls = prepareUrls(protocol, HOST, port);
|
||||||
|
|
||||||
// Create a webpack compiler that is configured with custom messages.
|
// Create a webpack compiler that is configured with custom messages.
|
||||||
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
|
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
|
||||||
|
|
||||||
// Load proxy config
|
// Load proxy config
|
||||||
const proxySetting = require(paths.appPackageJson).proxy;
|
const proxySetting = require(paths.appPackageJson).proxy;
|
||||||
|
|
||||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
||||||
|
|
||||||
// Serve webpack assets generated by the compiler over a web server.
|
// Serve webpack assets generated by the compiler over a web server.
|
||||||
const serverConfig = createDevServerConfig(
|
const serverConfig = createDevServerConfig(
|
||||||
proxyConfig,
|
proxyConfig,
|
||||||
urls.lanUrlForConfig
|
urls.lanUrlForConfig
|
||||||
);
|
);
|
||||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
const devServer = new WebpackDevServer(compiler, serverConfig);
|
||||||
|
|
||||||
// Launch WebpackDevServer.
|
// Launch WebpackDevServer.
|
||||||
devServer.listen(port, HOST, err => {
|
devServer.listen(port, HOST, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return console.log(err);
|
return console.log(err);
|
||||||
}
|
}
|
||||||
if (isInteractive) {
|
if (isInteractive) {
|
||||||
clearConsole();
|
clearConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(chalk.cyan('Starting the development server...\n'));
|
console.log(chalk.cyan('Starting the development server...\n'));
|
||||||
openBrowser(urls.localUrlForBrowser);
|
|
||||||
|
return openBrowser(urls.localUrlForBrowser);
|
||||||
});
|
});
|
||||||
|
|
||||||
['SIGINT', 'SIGTERM'].forEach(function(sig) {
|
[ 'SIGINT', 'SIGTERM' ].forEach((sig) => {
|
||||||
process.on(sig, function() {
|
process.on(sig, () => {
|
||||||
devServer.close();
|
devServer.close();
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
if (err && err.message) {
|
if (err && err.message) {
|
||||||
console.log(err.message);
|
console.log(err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import DateInput from '../../src/utils/DateInput';
|
import DateInput from '../../src/utils/DateInput';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { DropdownItem } from 'reactstrap';
|
import { DropdownItem } from 'reactstrap';
|
||||||
import { identity, values } from 'ramda';
|
import { identity, values } from 'ramda';
|
||||||
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import caretDownIcon from '@fortawesome/fontawesome-free-solid/faSortAmountDown';
|
import caretDownIcon from '@fortawesome/fontawesome-free-solid/faSortAmountDown';
|
||||||
import * as sinon from 'sinon';
|
import * as sinon from 'sinon';
|
||||||
import SortingDropdown from '../../src/utils/SortingDropdown';
|
import SortingDropdown from '../../src/utils/SortingDropdown';
|
||||||
|
|
Loading…
Reference in a new issue