├── .gitignore ├── .npmignore ├── README.md ├── bin └── react-scripts-ts-antd.js ├── config ├── env.js ├── jest │ ├── babelTransform.js │ ├── cssTransform.js │ ├── fileTransform.js │ └── typescriptTransform.js ├── loaders.js ├── paths.js ├── polyfills.js ├── webpack.config.dev.js ├── webpack.config.prod.js └── webpackDevServer.config.js ├── eslintrc ├── fixtures └── kitchensink │ ├── .babelrc │ ├── .env │ ├── .env.development │ ├── .env.local │ ├── .env.production │ ├── .flowconfig │ ├── .template.dependencies.json │ ├── README.md │ ├── gitignore │ ├── integration │ ├── env.test.js │ ├── initDOM.js │ ├── syntax.test.js │ └── webpack.test.js │ ├── public │ ├── favicon.ico │ └── index.html │ └── src │ ├── App.js │ ├── absoluteLoad.js │ ├── features │ ├── env │ │ ├── ExpandEnvVariables.js │ │ ├── ExpandEnvVariables.test.js │ │ ├── FileEnvVariables.js │ │ ├── FileEnvVariables.test.js │ │ ├── NodePath.js │ │ ├── NodePath.test.js │ │ ├── PublicUrl.js │ │ ├── PublicUrl.test.js │ │ ├── ShellEnvVariables.js │ │ └── ShellEnvVariables.test.js │ ├── syntax │ │ ├── ArrayDestructuring.js │ │ ├── ArrayDestructuring.test.js │ │ ├── ArraySpread.js │ │ ├── ArraySpread.test.js │ │ ├── AsyncAwait.js │ │ ├── AsyncAwait.test.js │ │ ├── ClassProperties.js │ │ ├── ClassProperties.test.js │ │ ├── ComputedProperties.js │ │ ├── ComputedProperties.test.js │ │ ├── CustomInterpolation.js │ │ ├── CustomInterpolation.test.js │ │ ├── DefaultParameters.js │ │ ├── DefaultParameters.test.js │ │ ├── DestructuringAndAwait.js │ │ ├── DestructuringAndAwait.test.js │ │ ├── Generators.js │ │ ├── Generators.test.js │ │ ├── ObjectDestructuring.js │ │ ├── ObjectDestructuring.test.js │ │ ├── ObjectSpread.js │ │ ├── ObjectSpread.test.js │ │ ├── Promises.js │ │ ├── Promises.test.js │ │ ├── RestAndDefault.js │ │ ├── RestAndDefault.test.js │ │ ├── RestParameters.js │ │ ├── RestParameters.test.js │ │ ├── TemplateInterpolation.js │ │ └── TemplateInterpolation.test.js │ └── webpack │ │ ├── CssInclusion.js │ │ ├── CssInclusion.test.js │ │ ├── ImageInclusion.js │ │ ├── ImageInclusion.test.js │ │ ├── JsonInclusion.js │ │ ├── JsonInclusion.test.js │ │ ├── LinkedModules.js │ │ ├── LinkedModules.test.js │ │ ├── NoExtInclusion.js │ │ ├── NoExtInclusion.test.js │ │ ├── SvgInclusion.js │ │ ├── SvgInclusion.test.js │ │ ├── UnknownExtInclusion.js │ │ ├── UnknownExtInclusion.test.js │ │ └── assets │ │ ├── aFileWithExt.unknown │ │ ├── aFileWithoutExt │ │ ├── abstract.json │ │ ├── logo.svg │ │ ├── style.css │ │ └── tiniest-cat.jpg │ ├── index.js │ └── subfolder │ └── lol.js ├── index.js ├── package.json ├── scripts ├── build.js ├── eject.js ├── init.js ├── start.js ├── test.js └── utils │ └── createJestConfig.js └── template ├── README.md ├── config-overrides.js ├── gitignore ├── images.d.ts ├── public ├── favicon.ico ├── index.html └── manifest.json ├── src ├── App.scss ├── App.test.tsx ├── App.tsx ├── index.scss ├── index.tsx ├── logo.svg └── registerServiceWorker.ts ├── tsconfig.json ├── tsconfig.prod.json ├── tsconfig.test.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | node_modules/ 4 | build 5 | .DS_Store 6 | *.tgz 7 | my-app* 8 | template/src/__tests__/__snapshots__/ 9 | lerna-debug.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | /.changelog 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /fixtures 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create React apps (with Typescript and antd) with no build configuration. 2 | base on [react-scripts-ts@2.17.0](https://github.com/wmonk/create-react-app-typescript) 3 | 4 | ## Usage 5 | create a new project with [create-react-app](https://github.com/facebook/create-react-app) 6 | ``` 7 | create-react-app myapp --scripts-version=react-scripts-ts-antd 8 | ``` 9 | 10 | ## Features 11 | ### Include [ts-import-plugin](https://github.com/Brooooooklyn/ts-import-plugin) for importing components on demand. 12 | ``` 13 | // source 14 | import { Card } from 'antd'; 15 | 16 | // output 17 | import Card from 'antd/lib/card'; 18 | import Card from 'antd/lib/card/style/index.less'; 19 | ``` 20 | 21 | ### Include [react-app-rewired](https://github.com/timarney/react-app-rewired) 22 | You can rewire your webpack configurations without eject. 23 | ``` 24 | // You can get all default loads 25 | const { loaders } = require('react-scripts-ts-antd'); 26 | ``` 27 | 28 | ### Support `scss` and `less` 29 | - use `less-loader` for `less`. 30 | - use [precss](https://github.com/jonathantneal/precss) for `scss`. 31 | 32 | 33 | 34 | ### Turn on some options of compileOptions in `tsconfig.json`. 35 | ``` 36 | // tsconfig.json 37 | { 38 | "allowSyntheticDefaultImports": "true", 39 | "experimentalDecorators": "true" 40 | } 41 | ``` 42 | 43 | ## Tips 44 | 45 | ### How to avoid importing styles twice 46 | If you want to customize theme by [overriding less variables](https://ant.design/docs/react/customize-theme) like below. 47 | 48 | ``` 49 | // index.less 50 | @import "~antd/dist/antd.less"; 51 | @primary-color: #000; 52 | 53 | ``` 54 | 55 | You have imported all styles and `ts-import-plugin` will import styles again. So you need to reset `ts-loader` options by modifying `config-overrides.js` to avoid importing styles twice. 56 | ``` 57 | // config-overrides.js 58 | const { getLoader } = require("react-app-rewired"); 59 | const tsImportPluginFactory = require('ts-import-plugin'); 60 | 61 | module.exports = function override(config, env) { 62 | 63 | // get tsloader 64 | const tsloader = getLoader( 65 | config.module.rules, 66 | rule => String(rule.test) == String(/\.(ts|tsx)$/) 67 | ); 68 | 69 | // set new options 70 | tsloader.options = { 71 | transpileOnly: true, 72 | getCustomTransformers: () => ({ 73 | before: [ 74 | tsImportPluginFactory([ 75 | { 76 | libraryName: 'antd', 77 | libraryDirectory: 'lib', 78 | }, 79 | { 80 | libraryName: 'antd-mobile', 81 | libraryDirectory: 'lib', 82 | } 83 | ]) 84 | ] 85 | }) 86 | } 87 | return config; 88 | }; 89 | 90 | ``` 91 | 92 | ### `antd` package will be installed automatically.If you need `antd-mobile`, install it manually. 93 | 94 | ## react-scripts 95 | This package includes scripts and configuration used by [Create React App](https://github.com/facebookincubator/create-react-app).
96 | Please refer to its documentation: 97 | 98 | * [Getting Started](https://github.com/facebookincubator/create-react-app/blob/master/README.md#getting-started) – How to create a new app. 99 | * [User Guide](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md) – How to develop apps bootstrapped with Create React App. 100 | -------------------------------------------------------------------------------- /bin/react-scripts-ts-antd.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Copyright (c) 2015-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | const fs = require('fs'); 12 | const { appPath } = require('../config/paths'); 13 | const spawn = require('react-dev-utils/crossSpawn'); 14 | const args = process.argv.slice(2); 15 | const myName = require('../package.json').name; 16 | 17 | const scriptIndex = args.findIndex( 18 | x => x === 'build' || x === 'eject' || x === 'start' || x === 'test' 19 | ); 20 | const script = scriptIndex === -1 ? args[0] : args[scriptIndex]; 21 | const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : []; 22 | 23 | switch (script) { 24 | case 'build': 25 | case 'eject': 26 | case 'start': 27 | case 'test': { 28 | let result; 29 | if (script !== 'eject' && fs.existsSync(appPath + '/config-overrides.js')) { 30 | result = spawn.sync( 31 | 'node', 32 | nodeArgs 33 | .concat(require.resolve('react-app-rewired/scripts/' + script)) 34 | .concat(['--scripts-version', myName]) 35 | .concat(args.slice(scriptIndex + 1)), 36 | { stdio: 'inherit' } 37 | ); 38 | } else { 39 | result = spawn.sync( 40 | 'node', 41 | nodeArgs 42 | .concat(require.resolve('../scripts/' + script)) 43 | .concat(args.slice(scriptIndex + 1)), 44 | { stdio: 'inherit' } 45 | ); 46 | } 47 | if (result.signal) { 48 | if (result.signal === 'SIGKILL') { 49 | console.log( 50 | 'The build failed because the process exited too early. ' + 51 | 'This probably means the system ran out of memory or someone called ' + 52 | '`kill -9` on the process.' 53 | ); 54 | } else if (result.signal === 'SIGTERM') { 55 | console.log( 56 | 'The build failed because the process exited too early. ' + 57 | 'Someone might have called `kill` or `killall`, or the system could ' + 58 | 'be shutting down.' 59 | ); 60 | } 61 | process.exit(1); 62 | } 63 | process.exit(result.status); 64 | break; 65 | } 66 | default: 67 | console.log('Unknown script "' + script + '".'); 68 | console.log('Perhaps you need to update react-scripts-ts-antd?'); 69 | break; 70 | } 71 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | // @remove-on-eject-begin 2 | /** 3 | * Copyright (c) 2015-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | // @remove-on-eject-end 9 | 'use strict'; 10 | 11 | const fs = require('fs'); 12 | const path = require('path'); 13 | const paths = require('./paths'); 14 | 15 | // Make sure that including paths.js after env.js will read .env variables. 16 | delete require.cache[require.resolve('./paths')]; 17 | 18 | const NODE_ENV = process.env.NODE_ENV; 19 | if (!NODE_ENV) { 20 | throw new Error( 21 | 'The NODE_ENV environment variable is required but was not specified.' 22 | ); 23 | } 24 | 25 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 26 | var dotenvFiles = [ 27 | `${paths.dotenv}.${NODE_ENV}.local`, 28 | `${paths.dotenv}.${NODE_ENV}`, 29 | // Don't include `.env.local` for `test` environment 30 | // since normally you expect tests to produce the same 31 | // results for everyone 32 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 33 | paths.dotenv, 34 | ].filter(Boolean); 35 | 36 | // Load environment variables from .env* files. Suppress warnings using silent 37 | // if this file is missing. dotenv will never modify any environment variables 38 | // that have already been set. Variable expansion is supported in .env files. 39 | // https://github.com/motdotla/dotenv 40 | // https://github.com/motdotla/dotenv-expand 41 | dotenvFiles.forEach(dotenvFile => { 42 | if (fs.existsSync(dotenvFile)) { 43 | require('dotenv-expand')( 44 | require('dotenv').config({ 45 | path: dotenvFile, 46 | }) 47 | ); 48 | } 49 | }); 50 | 51 | // We support resolving modules according to `NODE_PATH`. 52 | // This lets you use absolute paths in imports inside large monorepos: 53 | // https://github.com/facebookincubator/create-react-app/issues/253. 54 | // It works similar to `NODE_PATH` in Node itself: 55 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 56 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 57 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 58 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 59 | // We also resolve them to make sure all tools using them work consistently. 60 | const appDirectory = fs.realpathSync(process.cwd()); 61 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 62 | .split(path.delimiter) 63 | .filter(folder => folder && !path.isAbsolute(folder)) 64 | .map(folder => path.resolve(appDirectory, folder)) 65 | .join(path.delimiter); 66 | 67 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 68 | // injected into the application via DefinePlugin in Webpack configuration. 69 | const REACT_APP = /^REACT_APP_/i; 70 | 71 | function getClientEnvironment(publicUrl) { 72 | const raw = Object.keys(process.env) 73 | .filter(key => REACT_APP.test(key)) 74 | .reduce( 75 | (env, key) => { 76 | env[key] = process.env[key]; 77 | return env; 78 | }, 79 | { 80 | // Useful for determining whether we’re running in production mode. 81 | // Most importantly, it switches React into the correct mode. 82 | NODE_ENV: process.env.NODE_ENV || 'development', 83 | // Useful for resolving the correct path to static assets in `public`. 84 | // For example, . 85 | // This should only be used as an escape hatch. Normally you would put 86 | // images into the `src` and `import` them in code to get their paths. 87 | PUBLIC_URL: publicUrl, 88 | } 89 | ); 90 | // Stringify all values so we can feed into Webpack DefinePlugin 91 | const stringified = { 92 | 'process.env': Object.keys(raw).reduce( 93 | (env, key) => { 94 | env[key] = JSON.stringify(raw[key]); 95 | return env; 96 | }, 97 | {} 98 | ), 99 | }; 100 | 101 | return { raw, stringified }; 102 | } 103 | 104 | module.exports = getClientEnvironment; 105 | -------------------------------------------------------------------------------- /config/jest/babelTransform.js: -------------------------------------------------------------------------------- 1 | // @remove-file-on-eject 2 | /** 3 | * Copyright (c) 2014-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 'use strict'; 9 | 10 | const babelJest = require('babel-jest'); 11 | 12 | module.exports = babelJest.createTransformer({ 13 | presets: [require.resolve('babel-preset-react-app')], 14 | babelrc: false, 15 | }); 16 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | // @remove-on-eject-begin 2 | /** 3 | * Copyright (c) 2014-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | // @remove-on-eject-end 9 | 'use strict'; 10 | 11 | // This is a custom Jest transformer turning style imports into empty objects. 12 | // http://facebook.github.io/jest/docs/en/webpack.html 13 | 14 | module.exports = { 15 | process() { 16 | return 'module.exports = {};'; 17 | }, 18 | getCacheKey() { 19 | // The output is always the same. 20 | return 'cssTransform'; 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | // @remove-on-eject-begin 2 | /** 3 | * Copyright (c) 2014-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | // @remove-on-eject-end 9 | 'use strict'; 10 | 11 | const path = require('path'); 12 | 13 | // This is a custom Jest transformer turning file imports into filenames. 14 | // http://facebook.github.io/jest/docs/en/webpack.html 15 | 16 | module.exports = { 17 | process(src, filename) { 18 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /config/jest/typescriptTransform.js: -------------------------------------------------------------------------------- 1 | // Copyright 2004-present Facebook. All Rights Reserved. 2 | 3 | 'use strict'; 4 | 5 | const tsJestPreprocessor = require('ts-jest/preprocessor'); 6 | 7 | module.exports = tsJestPreprocessor; 8 | -------------------------------------------------------------------------------- /config/loaders.js: -------------------------------------------------------------------------------- 1 | const paths = require('./paths'); 2 | const tsImportPluginFactory = require('ts-import-plugin'); 3 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | 5 | const autoprefixer = require('autoprefixer')({ 6 | browsers: [ 7 | '>1%', 8 | 'last 4 versions', 9 | 'Firefox ESR', 10 | 'not ie < 9', // React doesn't support IE8 anyway 11 | ], 12 | flexbox: 'no-2009', 13 | }); 14 | 15 | const precss = require('precss')(); 16 | const flexBugFixes = require('postcss-flexbugs-fixes')(); 17 | 18 | // Webpack uses `publicPath` to determine where the app is being served from. 19 | // It requires a trailing slash, or the file assets will get an incorrect path. 20 | const publicPath = paths.servedPath; 21 | // Some apps do not use client-side routing with pushState. 22 | // For these, "homepage" can be set to "." to enable relative asset paths. 23 | const shouldUseRelativeAssetPaths = publicPath === './'; 24 | // Source maps are resource heavy and can cause out of memory issue for large source files. 25 | const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; 26 | 27 | // Note: defined here because it will be used more than once. 28 | const cssFilename = 'static/css/[name].[contenthash:8].css'; 29 | 30 | // ExtractTextPlugin expects the build output to be flat. 31 | // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27) 32 | // However, our output is structured with css, js and media folders. 33 | // To have this structure working with relative paths, we have to use custom options. 34 | const extractTextPluginOptions = shouldUseRelativeAssetPaths 35 | ? // Making sure that the publicPath goes back to to build folder. 36 | { publicPath: Array(cssFilename.split('/').length).join('../') } 37 | : {}; 38 | 39 | 40 | // "url" loader works like "file" loader except that it embeds assets 41 | // smaller than specified limit in bytes as data URLs to avoid requests. 42 | // A missing `test` is equivalent to a match. 43 | const urlLoader = { 44 | test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], 45 | loader: require.resolve('url-loader'), 46 | options: { 47 | limit: 10000, 48 | name: 'static/media/[name].[hash:8].[ext]', 49 | }, 50 | }; 51 | 52 | const importPluginOption = [ 53 | { 54 | libraryName: 'antd', 55 | libraryDirectory: 'lib', 56 | style: 'css' 57 | }, 58 | { 59 | libraryName: 'antd-mobile', 60 | libraryDirectory: 'lib', 61 | style: 'css', 62 | } 63 | ]; 64 | 65 | // js loader 66 | const jsLoader = { 67 | test: /\.(js|jsx|mjs)$/, 68 | include: paths.appSrc, 69 | loader: require.resolve('babel-loader'), 70 | options: { 71 | // @remove-on-eject-begin 72 | babelrc: false, 73 | presets: [require.resolve('babel-preset-react-app')], 74 | plugins: [['babel-plugin-import', importPluginOption]], 75 | // @remove-on-eject-end 76 | compact: true, 77 | }, 78 | }; 79 | 80 | 81 | // ts loader 82 | const tsLoader = { 83 | test: /\.(ts|tsx)$/, 84 | include: paths.appSrc, 85 | use: [ 86 | { 87 | loader: require.resolve('ts-loader'), 88 | options: { 89 | transpileOnly: true, 90 | getCustomTransformers: () => ({ 91 | before: [tsImportPluginFactory(importPluginOption)] 92 | }) 93 | } 94 | } 95 | ] 96 | }; 97 | 98 | const postcssLoader = { 99 | loader: require.resolve('postcss-loader'), 100 | options: { 101 | // Necessary for external CSS imports to work 102 | // https://github.com/facebookincubator/create-react-app/issues/2677 103 | // don't need now 104 | // ident: 'postcss', 105 | plugins: () => [ 106 | flexBugFixes, 107 | autoprefixer 108 | ], 109 | }, 110 | }; 111 | 112 | const precssLoader = { 113 | loader: require.resolve('postcss-loader'), 114 | options: { 115 | // Necessary for external CSS imports to work 116 | // https://github.com/facebookincubator/create-react-app/issues/2677 117 | // don't need now 118 | // ident: 'postcss', 119 | plugins: () => [ 120 | precss, 121 | flexBugFixes, 122 | autoprefixer 123 | ], 124 | }, 125 | }; 126 | 127 | const rawCssLoaderDev = { 128 | loader: require.resolve('css-loader'), 129 | options: { 130 | importLoaders: 1, 131 | }, 132 | }; 133 | 134 | const rawCssLoaderProd = { 135 | loader: require.resolve('css-loader'), 136 | options: { 137 | importLoaders: 1, 138 | minimize: true, 139 | sourceMap: shouldUseSourceMap, 140 | }, 141 | }; 142 | 143 | const cssLoaderDev = { 144 | test: /\.css$/, 145 | use: [ 146 | require.resolve('style-loader'), 147 | rawCssLoaderDev, 148 | postcssLoader, 149 | ], 150 | }; 151 | 152 | const cssLoaderProd = { 153 | test: /\.css$/, 154 | loader: ExtractTextPlugin.extract( 155 | Object.assign( 156 | { 157 | fallback: require.resolve('style-loader'), 158 | use: [ 159 | rawCssLoaderProd, 160 | postcssLoader, 161 | ], 162 | }, 163 | extractTextPluginOptions 164 | ) 165 | ), 166 | // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. 167 | }; 168 | 169 | // scss loader 170 | const scssLoaderDev = { 171 | test: /\.scss$/, 172 | use: [ 173 | require.resolve('style-loader'), 174 | rawCssLoaderDev, 175 | precssLoader, 176 | ], 177 | }; 178 | 179 | const scssLoaderProd = { 180 | test: /\.scss$/, 181 | loader: ExtractTextPlugin.extract( 182 | Object.assign( 183 | { 184 | fallback: require.resolve('style-loader'), 185 | use: [ 186 | rawCssLoaderProd, 187 | precssLoader, 188 | ], 189 | }, 190 | extractTextPluginOptions 191 | ) 192 | ) 193 | }; 194 | 195 | // less loader 196 | const lessLoaderDev = { 197 | test: /\.less$/, 198 | use: [ 199 | require.resolve('style-loader'), 200 | rawCssLoaderDev, 201 | postcssLoader, 202 | require.resolve('less-loader') 203 | ], 204 | }; 205 | 206 | const lessLoaderProd = { 207 | test: /\.less$/, 208 | loader: ExtractTextPlugin.extract( 209 | Object.assign( 210 | { 211 | fallback: require.resolve('style-loader'), 212 | use: [ 213 | rawCssLoaderProd, 214 | postcssLoader, 215 | require.resolve('less-loader') 216 | ], 217 | }, 218 | extractTextPluginOptions 219 | ) 220 | ) 221 | }; 222 | 223 | // Exclude `js` files to keep "css" loader working as it injects 224 | // it's runtime that would otherwise processed through "file" loader. 225 | // Also exclude `html` and `json` extensions so they get processed 226 | // by webpacks internal loaders. 227 | const fileLoader = { 228 | loader: require.resolve('file-loader'), 229 | // Exclude `js` files to keep "css" loader working as it injects 230 | // it's runtime that would otherwise processed through "file" loader. 231 | // Also exclude `html` and `json` extensions so they get processed 232 | // by webpacks internal loaders. 233 | exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/], 234 | options: { 235 | name: 'static/media/[name].[hash:8].[ext]', 236 | }, 237 | }; 238 | 239 | module.exports = { 240 | urlLoader, 241 | jsLoader, 242 | tsLoader, 243 | cssLoaderDev, 244 | cssLoaderProd, 245 | scssLoaderDev, 246 | scssLoaderProd, 247 | lessLoaderDev, 248 | lessLoaderProd, 249 | fileLoader, 250 | postcssLoader 251 | }; 252 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | // @remove-on-eject-begin 2 | /** 3 | * Copyright (c) 2015-present, Facebook, Inc. 4 | * 5 | * This source code is licensed under the MIT license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | // @remove-on-eject-end 9 | 'use strict'; 10 | 11 | const path = require('path'); 12 | const fs = require('fs'); 13 | const url = require('url'); 14 | 15 | // Make sure any symlinks in the project folder are resolved: 16 | // https://github.com/facebookincubator/create-react-app/issues/637 17 | const appDirectory = fs.realpathSync(process.cwd()); 18 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 19 | 20 | const envPublicUrl = process.env.PUBLIC_URL; 21 | 22 | function ensureSlash(path, needsSlash) { 23 | const hasSlash = path.endsWith('/'); 24 | if (hasSlash && !needsSlash) { 25 | return path.substr(path, path.length - 1); 26 | } else if (!hasSlash && needsSlash) { 27 | return `${path}/`; 28 | } else { 29 | return path; 30 | } 31 | } 32 | 33 | const getPublicUrl = appPackageJson => 34 | envPublicUrl || require(appPackageJson).homepage; 35 | 36 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 37 | // "public path" at which the app is served. 38 | // Webpack needs to know it to put the right