├── .DS_Store ├── .eslintcache ├── .gitignore ├── .yarnrc.yml ├── DebugReact.code-workspace ├── README.md ├── build ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── config ├── .DS_Store ├── env.js ├── getHttpsConfig.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── modules.js ├── paths.js ├── pnpTs.js ├── webpack.config.js └── webpackDevServer.config.js ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── scripts ├── build.js ├── start.js └── test.js ├── src ├── .DS_Store ├── RootRouter.jsx ├── components │ ├── .DS_Store │ ├── Button.js │ ├── MySlowList.js │ ├── Num.js │ └── User.js ├── index.css ├── index.js ├── pages │ ├── .DS_Store │ ├── AboutThisPage.js │ ├── ActionPage.jsx │ ├── ClassFunctionComponent.jsx │ ├── CloneElementPage.js │ ├── CommentListPage.jsx │ ├── ContextPage.jsx │ ├── ContextPage2.jsx │ ├── DiffPage.jsx │ ├── ErrorBoundaryPage.js │ ├── ExamplePage.jsx │ ├── FunctionComponent.jsx │ ├── FunctionComponentForceUpdate.js │ ├── LifeCyclePage.jsx │ ├── NewHookApi.js │ ├── OptimizingPage.js │ ├── PureComponentPage.jsx │ ├── ReactMemoPage.jsx │ ├── RefPage.jsx │ ├── RefPage19.jsx │ ├── ServerComponentWithoutServer.jsx │ ├── SetStatePage.jsx │ ├── SuspensePage.js │ ├── TransitionPage.js │ ├── TransitionPage2.js │ ├── UseActionStatePage.jsx │ ├── UseCallbackPage.jsx │ ├── UseDeferredValuePage.js │ ├── UseFormStatusPage.jsx │ ├── UseMemoPage.jsx │ ├── UseOptimisticPage copy.jsx │ ├── UseOptimisticPage.jsx │ ├── UseOptimisticPage2.jsx │ └── UsePage.jsx ├── store │ ├── createStore.js │ └── index.js ├── utils.js └── whichReact.js ├── yarn.lock └── 那些我回答了800遍的问题.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bubucuo/DebugReact/b25db1deda39e2cdd176a0ed45bd72d189b62ad4/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | react-/ 3 | # react/ 4 | 5 | .yarn/* 6 | 7 | src/-react* 8 | 9 | *.zip -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /DebugReact.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": ".", 5 | }, 6 | ], 7 | "settings": { 8 | "better-comments.tags": [ 9 | { 10 | "tag": "sy-", 11 | "color": "yellow", 12 | "strikethrough": false, 13 | "underline": false, 14 | "backgroundColor": "#000", 15 | "bold": false, 16 | "italic": false, 17 | }, 18 | { 19 | "tag": "!", 20 | "color": "#cf40c2", 21 | "strikethrough": false, 22 | "underline": false, 23 | "backgroundColor": "transparent", 24 | "bold": false, 25 | "italic": false, 26 | }, 27 | { 28 | "tag": "?", 29 | "color": "#cf6640", 30 | "strikethrough": false, 31 | "underline": false, 32 | "backgroundColor": "transparent", 33 | "bold": false, 34 | "italic": false, 35 | }, 36 | { 37 | "tag": "//", 38 | "color": "#474747", 39 | "strikethrough": true, 40 | "underline": false, 41 | "backgroundColor": "transparent", 42 | "bold": false, 43 | "italic": false, 44 | }, 45 | { 46 | "tag": "todo", 47 | "color": "#FF8C00", 48 | "strikethrough": false, 49 | "underline": false, 50 | "backgroundColor": "transparent", 51 | "bold": false, 52 | "italic": false, 53 | }, 54 | { 55 | "tag": "*", 56 | "color": "green", //"#9c27b0", 57 | "strikethrough": false, 58 | "underline": false, 59 | "backgroundColor": "transparent", 60 | "bold": false, 61 | "italic": false, 62 | }, 63 | ], 64 | "editor.cursorWidth": 2, 65 | }, 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React 源码学习指南 2 | 3 | 1. 本项目属于课程资源,已购买课程学员可以联系我「微信: bubucuo_sy」,获取完整版~ 4 | 5 | 2. 更多资源,关注公众号|b站|YouTube:bubucuo 6 | 7 | ## 前言 8 | 9 | 本项目用于调试源码,即修改配置使得项目中引用的 react 包来自 src/react,使得我们可以在 src/react 下 debug 和打 log 调试。 10 | 11 | ## 使用步骤 12 | 13 | 1. 在根目录下安装: yarn add 14 | 2. 下载 react 包到 src 下,并按照下面的修改配置步骤修改 react 中的文件。 15 | 3. 在根目录下启动: yarn start 16 | 17 | # 自己从 github 下载 react 包并修改配置 18 | 19 | 1. /src/react/packages/scheduler/index.js 20 | 21 | ```jsx 22 | "use strict"; 23 | 24 | export * from "./src/forks/Scheduler"; 25 | 26 | // sy- 添加以下 27 | export { 28 | log, 29 | unstable_flushAllWithoutAsserting, 30 | unstable_flushNumberOfYields, 31 | unstable_flushExpired, 32 | unstable_flushUntilNextPaint, 33 | unstable_flushAll, 34 | unstable_advanceTime, 35 | unstable_setDisableYieldValue, 36 | } from "./src/forks/SchedulerMock"; 37 | ``` 38 | 39 | 2. /src/react/packages/react-reconciler/src/ReactFiberConfig.js 40 | 41 | ```jsx 42 | // throw new Error('This module must be shimmed by a specific renderer.'); 43 | 44 | // sy- 45 | export * from "./forks/ReactFiberConfig.dom"; 46 | export { bindToConsole } from "../../react-client/src/ReactClientConsoleConfigBrowser"; 47 | ``` 48 | 49 | 3. src/react/packages/react-reconciler/src/forks/ReactFiberConfig.dom.js 50 | 51 | ```js 52 | // export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; 53 | // export * from 'react-client/src/ReactClientConsoleConfigBrowser'; 54 | // sy-- 55 | export * from "../../../react-dom-bindings/src/client/ReactFiberConfigDOM"; 56 | export * from "../../../react-client/src/ReactClientConsoleConfigBrowser"; 57 | ``` 58 | 59 | 4. /src/react/packages/shared/ReactSharedInternals.js 60 | 61 | ```jsx 62 | // import * as React from 'react'; 63 | 64 | // const ReactSharedInternals = 65 | // React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; 66 | 67 | // sy 68 | import ReactSharedInternals from "../react/src/ReactSharedInternalsClient"; 69 | 70 | export default ReactSharedInternals; 71 | ``` 72 | 73 | 5. src/react/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js 74 | 75 | ```js 76 | // 在export type ViewTransitionInstance = { 前面增加以下代码 77 | // sy- 78 | type Animatable = any; 79 | type Keyframe = any; 80 | type PropertyIndexedKeyframes = any; 81 | type KeyframeAnimationOptions = any; 82 | type GetAnimationsOptions = any; 83 | type EventListenerOptionsOrUseCapture = any; 84 | type FocusOptions = any; 85 | ``` 86 | 87 | 6. src/react/packages/react-reconciler/src/ReactFiberDevToolsHook.js 88 | 89 | ```js 90 | // declare const __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void; 91 | // sy- 92 | var __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void; 93 | ``` 94 | 95 | 7. src/react/.eslintrc.js 96 | 97 | 我修改后的文件如下: 98 | 99 | ```js 100 | 'use strict'; 101 | 102 | const { 103 | es5Paths, 104 | esNextPaths, 105 | } = require('./scripts/shared/pathsByLanguageVersion'); 106 | 107 | const restrictedGlobals = require('confusing-browser-globals'); 108 | 109 | const OFF = 0; 110 | const WARNING = 1; 111 | const ERROR = 2; 112 | 113 | module.exports = { 114 | extends: ['plugin:jest/recommended'], 115 | 116 | // Stop ESLint from looking for a configuration file in parent folders 117 | root: true, 118 | 119 | reportUnusedDisableDirectives: false, //true, 120 | 121 | plugins: [ 122 | // 'babel', 123 | 'ft-flow', 124 | 'jest', 125 | 'es', 126 | 'no-for-of-loops', 127 | 'no-function-declare-after-return', 128 | 'react', 129 | 'react-internal', 130 | ], 131 | 132 | parser: 'hermes-eslint', 133 | parserOptions: { 134 | ecmaVersion: 9, 135 | sourceType: 'script', 136 | }, 137 | 138 | // We're stricter than the default config, mostly. We'll override a few rules 139 | // and then enable some React specific ones. 140 | rules: { 141 | 'ft-flow/array-style-complex-type': [OFF, 'verbose'], 142 | 'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING 143 | 'ft-flow/boolean-style': ERROR, 144 | 'ft-flow/no-dupe-keys': ERROR, 145 | 'ft-flow/no-primitive-constructor-types': ERROR, 146 | 'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR 147 | 'ft-flow/no-unused-expressions': ERROR, 148 | // 'ft-flow/no-weak-types': WARNING, 149 | // 'ft-flow/require-valid-file-annotation': ERROR, 150 | 'es/no-optional-chaining': ERROR, 151 | 'no-cond-assign': OFF, 152 | 'no-constant-condition': OFF, 153 | 'no-control-regex': OFF, 154 | 'no-debugger': OFF, 155 | 'no-dupe-args': ERROR, 156 | 'no-dupe-keys': ERROR, 157 | 'no-duplicate-case': WARNING, 158 | 'no-empty-character-class': WARNING, 159 | 'no-empty': OFF, 160 | 'no-ex-assign': WARNING, 161 | 'no-extra-boolean-cast': WARNING, 162 | 'no-func-assign': ERROR, 163 | 'no-invalid-regexp': WARNING, 164 | 'no-irregular-whitespace': WARNING, 165 | 'no-negated-in-lhs': ERROR, 166 | 'no-obj-calls': ERROR, 167 | 'no-regex-spaces': WARNING, 168 | 'no-sparse-arrays': ERROR, 169 | 'no-unreachable': ERROR, 170 | 'use-isnan': ERROR, 171 | 'valid-jsdoc': OFF, 172 | 'block-scoped-var': OFF, 173 | complexity: OFF, 174 | 'default-case': OFF, 175 | 'guard-for-in': OFF, 176 | 'no-alert': OFF, 177 | 'no-caller': ERROR, 178 | 'no-case-declarations': OFF, 179 | 'no-div-regex': OFF, 180 | 'no-else-return': OFF, 181 | 'no-empty-pattern': WARNING, 182 | 'no-eq-null': OFF, 183 | 'no-eval': ERROR, 184 | 'no-extend-native': WARNING, 185 | 'no-extra-bind': WARNING, 186 | 'no-fallthrough': WARNING, 187 | 'no-implicit-coercion': OFF, 188 | 'no-implied-eval': ERROR, 189 | 'no-invalid-this': OFF, 190 | 'no-iterator': OFF, 191 | 'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}], 192 | 'no-lone-blocks': WARNING, 193 | 'no-loop-func': OFF, 194 | 'no-magic-numbers': OFF, 195 | 'no-multi-str': ERROR, 196 | 'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}], 197 | 'no-new-func': ERROR, 198 | 'no-new': WARNING, 199 | 'no-new-wrappers': WARNING, 200 | 'no-octal-escape': WARNING, 201 | 'no-octal': WARNING, 202 | 'no-param-reassign': OFF, 203 | 'no-process-env': OFF, 204 | 'no-proto': ERROR, 205 | 'no-redeclare': OFF, // TODO should be WARNING? 206 | 'no-return-assign': OFF, 207 | 'no-script-url': ERROR, 208 | 'no-self-compare': WARNING, 209 | 'no-sequences': WARNING, 210 | 'no-throw-literal': ERROR, 211 | 'no-useless-call': WARNING, 212 | 'no-void': OFF, 213 | 'no-warning-comments': OFF, 214 | 'no-with': OFF, 215 | radix: WARNING, 216 | 'vars-on-top': OFF, 217 | yoda: OFF, 218 | 'init-declarations': OFF, 219 | 'no-catch-shadow': ERROR, 220 | 'no-delete-var': ERROR, 221 | 'no-label-var': WARNING, 222 | 'no-shadow-restricted-names': WARNING, 223 | 'no-undef-init': OFF, 224 | 'no-undef': OFF, 225 | 'no-undefined': OFF, 226 | 'callback-return': OFF, 227 | 'global-require': OFF, 228 | 'handle-callback-err': OFF, 229 | 'no-mixed-requires': OFF, 230 | 'no-new-require': OFF, 231 | 'no-path-concat': OFF, 232 | 'no-process-exit': OFF, 233 | 'no-restricted-modules': OFF, 234 | 'no-sync': OFF, 235 | camelcase: [OFF, {properties: 'always'}], 236 | 'consistent-this': [OFF, 'self'], 237 | 'func-names': OFF, 238 | 'func-style': [OFF, 'declaration'], 239 | 'id-length': OFF, 240 | 'id-match': OFF, 241 | 'max-depth': OFF, 242 | 'max-nested-callbacks': OFF, 243 | 'max-params': OFF, 244 | 'max-statements': OFF, 245 | 'new-cap': OFF, 246 | 'newline-after-var': OFF, 247 | 'no-array-constructor': ERROR, 248 | 'no-continue': OFF, 249 | 'no-inline-comments': OFF, 250 | 'no-lonely-if': OFF, 251 | 'no-negated-condition': OFF, 252 | 'no-nested-ternary': OFF, 253 | 'no-new-object': WARNING, 254 | 'no-plusplus': OFF, 255 | 'no-ternary': OFF, 256 | 'no-underscore-dangle': OFF, 257 | 'no-unneeded-ternary': WARNING, 258 | 'one-var': [WARNING, {initialized: 'never'}], 259 | 'operator-assignment': [WARNING, 'always'], 260 | 'require-jsdoc': OFF, 261 | 'sort-vars': OFF, 262 | 'spaced-comment': [ 263 | OFF, 264 | 'always', 265 | {exceptions: ['jshint', 'jslint', 'eslint', 'global']}, 266 | ], 267 | 'constructor-super': ERROR, 268 | 'no-class-assign': WARNING, 269 | 'no-const-assign': ERROR, 270 | 'no-dupe-class-members': ERROR, 271 | 'no-this-before-super': ERROR, 272 | 'object-shorthand': OFF, 273 | 'prefer-const': OFF, 274 | 'prefer-spread': OFF, 275 | 'prefer-reflect': OFF, 276 | 'prefer-template': OFF, 277 | 'require-yield': OFF, 278 | 'babel/generator-star-spacing': OFF, 279 | 'babel/new-cap': OFF, 280 | 'babel/array-bracket-spacing': OFF, 281 | 'babel/object-curly-spacing': OFF, 282 | 'babel/object-shorthand': OFF, 283 | 'babel/arrow-parens': OFF, 284 | 'babel/no-await-in-loop': OFF, 285 | 'babel/flow-object-type': OFF, 286 | 'react/display-name': OFF, 287 | 'react/forbid-prop-types': OFF, 288 | 'react/jsx-closing-bracket-location': OFF, 289 | 'react/jsx-curly-spacing': OFF, 290 | 'react/jsx-equals-spacing': WARNING, 291 | 'react/jsx-filename-extension': OFF, 292 | 'react/jsx-first-prop-new-line': OFF, 293 | 'react/jsx-handler-names': OFF, 294 | 'react/jsx-indent': OFF, 295 | 'react/jsx-indent-props': OFF, 296 | 'react/jsx-key': OFF, 297 | 'react/jsx-max-props-per-line': OFF, 298 | 'react/jsx-no-bind': OFF, 299 | 'react/jsx-no-duplicate-props': ERROR, 300 | 'react/jsx-no-literals': OFF, 301 | 'react/jsx-no-target-blank': OFF, 302 | 'react/jsx-pascal-case': OFF, 303 | 'react/jsx-sort-props': OFF, 304 | 'react/jsx-uses-vars': OFF, 305 | 'react/no-comment-textnodes': OFF, 306 | 'react/no-danger': OFF, 307 | 'react/no-deprecated': OFF, 308 | 'react/no-did-mount-set-state': OFF, 309 | 'react/no-did-update-set-state': OFF, 310 | 'react/no-direct-mutation-state': OFF, 311 | 'react/no-multi-comp': OFF, 312 | 'react/no-render-return-value': OFF, 313 | 'react/no-set-state': OFF, 314 | 'react/no-string-refs': OFF, 315 | 'react/no-unknown-property': OFF, 316 | 'react/prefer-es6-class': OFF, 317 | 'react/prefer-stateless-function': OFF, 318 | 'react/prop-types': OFF, 319 | 'react/require-extension': OFF, 320 | 'react/require-optimization': OFF, 321 | 'react/require-render-return': OFF, 322 | 'react/sort-comp': OFF, 323 | 'react/sort-prop-types': OFF, 324 | 325 | 'accessor-pairs': OFF, 326 | 'brace-style': [ERROR, '1tbs'], 327 | 'consistent-return': OFF, 328 | 'dot-location': [ERROR, 'property'], 329 | // We use console['error']() as a signal to not transform it: 330 | 'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}], 331 | 'eol-last': ERROR, 332 | eqeqeq: [ERROR, 'allow-null'], 333 | indent: OFF, 334 | 'jsx-quotes': [ERROR, 'prefer-double'], 335 | 'keyword-spacing': [ERROR, {after: true, before: true}], 336 | 'no-bitwise': OFF, 337 | 'no-console': OFF, 338 | 'no-inner-declarations': [ERROR, 'functions'], 339 | 'no-multi-spaces': ERROR, 340 | 'no-restricted-globals': [ERROR].concat(restrictedGlobals), 341 | 'no-restricted-syntax': [ 342 | ERROR, 343 | 'WithStatement', 344 | { 345 | selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]', 346 | message: 'Prefer string.slice() over .substring() and .substr().', 347 | }, 348 | ], 349 | 'no-shadow': ERROR, 350 | 'no-unused-vars': OFF, //[ERROR, {args: 'none', ignoreRestSiblings: true}], 351 | 'no-use-before-define': OFF, 352 | 'no-useless-concat': OFF, 353 | quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}], 354 | 'space-before-blocks': ERROR, 355 | 'space-before-function-paren': OFF, 356 | 'valid-typeof': [ERROR, {requireStringLiterals: true}], 357 | // Flow fails with non-string literal keys 358 | 'no-useless-computed-key': OFF, 359 | 360 | // We apply these settings to files that should run on Node. 361 | // They can't use JSX or ES6 modules, and must be in strict mode. 362 | // They can, however, use other ES6 features. 363 | // (Note these rules are overridden later for source files.) 364 | 'no-var': ERROR, 365 | strict: ERROR, 366 | 367 | // Enforced by Prettier 368 | // TODO: Prettier doesn't handle long strings or long comments. Not a big 369 | // deal. But I turned it off because loading the plugin causes some obscure 370 | // syntax error and it didn't seem worth investigating. 371 | 'max-len': OFF, 372 | 373 | // React & JSX 374 | // Our transforms set this automatically 375 | 'react/jsx-boolean-value': [ERROR, 'always'], 376 | 'react/jsx-no-undef': OFF, //ERROR, 377 | // We don't care to do this 378 | 'react/jsx-sort-prop-types': OFF, 379 | 'react/jsx-space-before-closing': ERROR, 380 | 'react/jsx-uses-react': ERROR, 381 | 'react/no-is-mounted': OFF, 382 | // This isn't useful in our test code 383 | 'react/react-in-jsx-scope': ERROR, 384 | 'react/self-closing-comp': ERROR, 385 | // We don't care to do this 386 | 'react/jsx-wrap-multilines': [ 387 | ERROR, 388 | {declaration: false, assignment: false}, 389 | ], 390 | 391 | // Prevent for...of loops because they require a Symbol polyfill. 392 | // You can disable this rule for code that isn't shipped (e.g. build scripts and tests). 393 | 'no-for-of-loops/no-for-of-loops': ERROR, 394 | 395 | // Prevent function declarations after return statements 396 | 'no-function-declare-after-return/no-function-declare-after-return': ERROR, 397 | 398 | // CUSTOM RULES 399 | // the second argument of warning/invariant should be a literal string 400 | 'react-internal/no-primitive-constructors': ERROR, 401 | 'react-internal/safe-string-coercion': [ 402 | ERROR, 403 | {isProductionUserAppCode: true}, 404 | ], 405 | 'react-internal/warning-args': ERROR, 406 | 'react-internal/no-production-logging': OFF, 407 | }, 408 | 409 | overrides: [ 410 | { 411 | // By default, anything error message that appears the packages directory 412 | // must have a corresponding error code. The exceptions are defined 413 | // in the next override entry. 414 | files: ['packages/**/*.js'], 415 | rules: { 416 | 'react-internal/prod-error-codes': ERROR, 417 | }, 418 | }, 419 | { 420 | // These are files where it's OK to have unminified error messages. These 421 | // are environments where bundle size isn't a concern, like tests 422 | // or Node. 423 | files: [ 424 | 'packages/react-dom/src/test-utils/**/*.js', 425 | 'packages/react-devtools-shared/**/*.js', 426 | 'packages/react-noop-renderer/**/*.js', 427 | 'packages/react-refresh/**/*.js', 428 | 'packages/react-server-dom-esm/**/*.js', 429 | 'packages/react-server-dom-webpack/**/*.js', 430 | 'packages/react-server-dom-turbopack/**/*.js', 431 | 'packages/react-server-dom-parcel/**/*.js', 432 | 'packages/react-server-dom-fb/**/*.js', 433 | 'packages/react-test-renderer/**/*.js', 434 | 'packages/react-debug-tools/**/*.js', 435 | 'packages/react-devtools-extensions/**/*.js', 436 | 'packages/react-devtools-timeline/**/*.js', 437 | 'packages/react-native-renderer/**/*.js', 438 | 'packages/eslint-plugin-react-hooks/**/*.js', 439 | 'packages/jest-react/**/*.js', 440 | 'packages/internal-test-utils/**/*.js', 441 | 'packages/**/__tests__/*.js', 442 | 'packages/**/npm/*.js', 443 | ], 444 | rules: { 445 | 'react-internal/prod-error-codes': OFF, 446 | }, 447 | }, 448 | { 449 | // We apply these settings to files that we ship through npm. 450 | // They must be ES5. 451 | files: es5Paths, 452 | parser: 'espree', 453 | parserOptions: { 454 | ecmaVersion: 5, 455 | sourceType: 'script', 456 | }, 457 | rules: { 458 | 'no-var': OFF, 459 | strict: ERROR, 460 | }, 461 | }, 462 | { 463 | // We apply these settings to the source files that get compiled. 464 | // They can use all features including JSX (but shouldn't use `var`). 465 | files: esNextPaths, 466 | parser: 'hermes-eslint', 467 | parserOptions: { 468 | ecmaVersion: 8, 469 | sourceType: 'module', 470 | }, 471 | rules: { 472 | 'no-var': OFF, 473 | 'prefer-const': OFF, 474 | strict: OFF, 475 | }, 476 | }, 477 | { 478 | files: ['**/__tests__/*.js'], 479 | rules: { 480 | // https://github.com/jest-community/eslint-plugin-jest 481 | // Meh, who cares. 482 | 'jest/consistent-test-it': OFF, 483 | // Meh, we have a lot of these, who cares. 484 | 'jest/no-alias-methods': OFF, 485 | // We do conditions based on feature flags. 486 | 'jest/no-conditional-expect': OFF, 487 | // We have our own assertion helpers. 488 | 'jest/expect-expect': OFF, 489 | // Lame rule that fires in itRender helpers or in render methods. 490 | 'jest/no-standalone-expect': OFF, 491 | }, 492 | }, 493 | { 494 | // Rules specific to test setup helper files. 495 | files: [ 496 | '**/setupTests.js', 497 | '**/setupEnv.js', 498 | '**/jest/TestFlags.js', 499 | '**/dom-event-testing-library/testHelpers.js', 500 | '**/utils/ReactDOMServerIntegrationTestUtils.js', 501 | '**/babel/transform-react-version-pragma.js', 502 | '**/babel/transform-test-gate-pragma.js', 503 | ], 504 | rules: { 505 | // Some helpers intentionally focus tests. 506 | 'jest/no-focused-tests': OFF, 507 | // Test fn helpers don't use static text names. 508 | 'jest/valid-title': OFF, 509 | // We have our own assertion helpers. 510 | 'jest/expect-expect': OFF, 511 | // Some helpers intentionally disable tests. 512 | 'jest/no-disabled-tests': OFF, 513 | // Helpers export text function helpers. 514 | 'jest/no-export': OFF, 515 | // The examples in comments trigger false errors. 516 | 'jest/no-commented-out-tests': OFF, 517 | }, 518 | }, 519 | { 520 | files: ['**/jest/TestFlags.js'], 521 | rules: { 522 | // The examples in comments trigger false errors. 523 | 'jest/no-commented-out-tests': OFF, 524 | }, 525 | }, 526 | { 527 | files: [ 528 | '**/__tests__/**/*.js', 529 | 'scripts/**/*.js', 530 | 'packages/*/npm/**/*.js', 531 | 'packages/dom-event-testing-library/**/*.js', 532 | 'packages/react-devtools*/**/*.js', 533 | 'dangerfile.js', 534 | 'fixtures', 535 | 'packages/react-dom/src/test-utils/*.js', 536 | ], 537 | rules: { 538 | 'es/no-optional-chaining': OFF, 539 | 'react-internal/no-production-logging': OFF, 540 | 'react-internal/warning-args': OFF, 541 | 'react-internal/safe-string-coercion': [ 542 | ERROR, 543 | {isProductionUserAppCode: false}, 544 | ], 545 | }, 546 | }, 547 | { 548 | files: ['scripts/eslint-rules/*.js'], 549 | plugins: ['eslint-plugin'], 550 | rules: { 551 | 'eslint-plugin/prefer-object-rule': ERROR, 552 | 'eslint-plugin/require-meta-fixable': [ 553 | ERROR, 554 | {catchNoFixerButFixableProperty: true}, 555 | ], 556 | 'eslint-plugin/require-meta-has-suggestions': ERROR, 557 | }, 558 | }, 559 | { 560 | files: ['packages/react-native-renderer/**/*.js'], 561 | globals: { 562 | nativeFabricUIManager: 'readonly', 563 | RN$enableMicrotasksInReact: 'readonly', 564 | }, 565 | }, 566 | { 567 | files: ['packages/react-server-dom-webpack/**/*.js'], 568 | globals: { 569 | __webpack_chunk_load__: 'readonly', 570 | __webpack_require__: 'readonly', 571 | }, 572 | }, 573 | { 574 | files: ['packages/react-server-dom-turbopack/**/*.js'], 575 | globals: { 576 | __turbopack_load__: 'readonly', 577 | __turbopack_require__: 'readonly', 578 | }, 579 | }, 580 | { 581 | files: ['packages/react-server-dom-parcel/**/*.js'], 582 | globals: { 583 | parcelRequire: 'readonly', 584 | }, 585 | }, 586 | { 587 | files: ['packages/scheduler/**/*.js'], 588 | globals: { 589 | TaskController: 'readonly', 590 | }, 591 | }, 592 | { 593 | files: [ 594 | 'packages/react-devtools-extensions/**/*.js', 595 | 'packages/react-devtools-shared/src/devtools/views/**/*.js', 596 | 'packages/react-devtools-shared/src/hook.js', 597 | 'packages/react-devtools-shared/src/backend/console.js', 598 | 'packages/react-devtools-shared/src/backend/shared/DevToolsComponentStackFrame.js', 599 | 'packages/react-devtools-shared/src/frontend/utils/withPermissionsCheck.js', 600 | ], 601 | globals: { 602 | __IS_CHROME__: 'readonly', 603 | __IS_FIREFOX__: 'readonly', 604 | __IS_EDGE__: 'readonly', 605 | __IS_NATIVE__: 'readonly', 606 | __IS_INTERNAL_VERSION__: 'readonly', 607 | chrome: 'readonly', 608 | }, 609 | }, 610 | { 611 | files: ['packages/react-devtools-shared/**/*.js'], 612 | globals: { 613 | __IS_INTERNAL_VERSION__: 'readonly', 614 | }, 615 | }, 616 | { 617 | files: ['packages/eslint-plugin-react-hooks/src/**/*'], 618 | extends: ['plugin:@typescript-eslint/recommended'], 619 | parser: '@typescript-eslint/parser', 620 | plugins: ['@typescript-eslint', 'eslint-plugin'], 621 | rules: { 622 | '@typescript-eslint/no-explicit-any': OFF, 623 | '@typescript-eslint/no-non-null-assertion': OFF, 624 | '@typescript-eslint/array-type': [ERROR, {default: 'generic'}], 625 | 626 | 'es/no-optional-chaining': OFF, 627 | 628 | 'eslint-plugin/prefer-object-rule': ERROR, 629 | 'eslint-plugin/require-meta-fixable': [ 630 | ERROR, 631 | {catchNoFixerButFixableProperty: true}, 632 | ], 633 | 'eslint-plugin/require-meta-has-suggestions': ERROR, 634 | }, 635 | }, 636 | ], 637 | 638 | env: { 639 | browser: true, 640 | es6: true, 641 | node: true, 642 | jest: true, 643 | }, 644 | 645 | globals: { 646 | $Call: 'readonly', 647 | $ElementType: 'readonly', 648 | $Flow$ModuleRef: 'readonly', 649 | $FlowFixMe: 'readonly', 650 | $Keys: 'readonly', 651 | $NonMaybeType: 'readonly', 652 | $PropertyType: 'readonly', 653 | $ReadOnly: 'readonly', 654 | $ReadOnlyArray: 'readonly', 655 | $ArrayBufferView: 'readonly', 656 | $Shape: 'readonly', 657 | CallSite: 'readonly', 658 | ConsoleTask: 'readonly', // TOOD: Figure out what the official name of this will be. 659 | ReturnType: 'readonly', 660 | AnimationFrameID: 'readonly', 661 | // For Flow type annotation. Only `BigInt` is valid at runtime. 662 | bigint: 'readonly', 663 | BigInt: 'readonly', 664 | BigInt64Array: 'readonly', 665 | BigUint64Array: 'readonly', 666 | Class: 'readonly', 667 | ClientRect: 'readonly', 668 | CopyInspectedElementPath: 'readonly', 669 | DOMHighResTimeStamp: 'readonly', 670 | EventListener: 'readonly', 671 | Iterable: 'readonly', 672 | AsyncIterable: 'readonly', 673 | $AsyncIterable: 'readonly', 674 | $AsyncIterator: 'readonly', 675 | Iterator: 'readonly', 676 | AsyncIterator: 'readonly', 677 | IteratorResult: 'readonly', 678 | JSONValue: 'readonly', 679 | JSResourceReference: 'readonly', 680 | MouseEventHandler: 'readonly', 681 | PropagationPhases: 'readonly', 682 | PropertyDescriptor: 'readonly', 683 | React$AbstractComponent: 'readonly', 684 | React$Component: 'readonly', 685 | React$ComponentType: 'readonly', 686 | React$Config: 'readonly', 687 | React$Context: 'readonly', 688 | React$Element: 'readonly', 689 | React$ElementConfig: 'readonly', 690 | React$ElementProps: 'readonly', 691 | React$ElementRef: 'readonly', 692 | React$ElementType: 'readonly', 693 | React$Key: 'readonly', 694 | React$Node: 'readonly', 695 | React$Portal: 'readonly', 696 | React$Ref: 'readonly', 697 | React$RefSetter: 'readonly', 698 | ReadableStreamController: 'readonly', 699 | ReadableStreamReader: 'readonly', 700 | RequestInfo: 'readonly', 701 | RequestOptions: 'readonly', 702 | StoreAsGlobal: 'readonly', 703 | symbol: 'readonly', 704 | SyntheticEvent: 'readonly', 705 | SyntheticMouseEvent: 'readonly', 706 | Thenable: 'readonly', 707 | TimeoutID: 'readonly', 708 | WheelEventHandler: 'readonly', 709 | FinalizationRegistry: 'readonly', 710 | Omit: 'readonly', 711 | Keyframe: 'readonly', 712 | PropertyIndexedKeyframes: 'readonly', 713 | KeyframeAnimationOptions: 'readonly', 714 | GetAnimationsOptions: 'readonly', 715 | Animatable: 'readonly', 716 | ScrollTimeline: 'readonly', 717 | EventListenerOptionsOrUseCapture: 'readonly', 718 | FocusOptions: 'readonly', 719 | 720 | spyOnDev: 'readonly', 721 | spyOnDevAndProd: 'readonly', 722 | spyOnProd: 'readonly', 723 | __DEV__: 'readonly', 724 | __EXPERIMENTAL__: 'readonly', 725 | __EXTENSION__: 'readonly', 726 | __PROFILE__: 'readonly', 727 | __TEST__: 'readonly', 728 | __VARIANT__: 'readonly', 729 | __unmockReact: 'readonly', 730 | gate: 'readonly', 731 | trustedTypes: 'readonly', 732 | IS_REACT_ACT_ENVIRONMENT: 'readonly', 733 | AsyncLocalStorage: 'readonly', 734 | async_hooks: 'readonly', 735 | globalThis: 'readonly', 736 | }, 737 | }; 738 | ``` 739 | 740 | 8. `yarn start`启动项目,此时可能依然有报错,这时候可以根据控制台此时的错误提示,再酌情修改。 741 | -------------------------------------------------------------------------------- /build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bubucuo/DebugReact/b25db1deda39e2cdd176a0ed45bd72d189b62ad4/build/favicon.ico -------------------------------------------------------------------------------- /build/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bubucuo/DebugReact/b25db1deda39e2cdd176a0ed45bd72d189b62ad4/build/logo192.png -------------------------------------------------------------------------------- /build/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bubucuo/DebugReact/b25db1deda39e2cdd176a0ed45bd72d189b62ad4/build/logo512.png -------------------------------------------------------------------------------- /build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /build/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /config/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bubucuo/DebugReact/b25db1deda39e2cdd176a0ed45bd72d189b62ad4/config/.DS_Store -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const paths = require("./paths"); 6 | 7 | // Make sure that including paths.js after env.js will read .env variables. 8 | delete require.cache[require.resolve("./paths")]; 9 | 10 | const NODE_ENV = process.env.NODE_ENV; 11 | if (!NODE_ENV) { 12 | throw new Error( 13 | "The NODE_ENV environment variable is required but was not specified." 14 | ); 15 | } 16 | 17 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 18 | const dotenvFiles = [ 19 | `${paths.dotenv}.${NODE_ENV}.local`, 20 | // Don't include `.env.local` for `test` environment 21 | // since normally you expect tests to produce the same 22 | // results for everyone 23 | NODE_ENV !== "test" && `${paths.dotenv}.local`, 24 | `${paths.dotenv}.${NODE_ENV}`, 25 | paths.dotenv, 26 | ].filter(Boolean); 27 | 28 | // Load environment variables from .env* files. Suppress warnings using silent 29 | // if this file is missing. dotenv will never modify any environment variables 30 | // that have already been set. Variable expansion is supported in .env files. 31 | // https://github.com/motdotla/dotenv 32 | // https://github.com/motdotla/dotenv-expand 33 | dotenvFiles.forEach((dotenvFile) => { 34 | if (fs.existsSync(dotenvFile)) { 35 | require("dotenv-expand")( 36 | require("dotenv").config({ 37 | path: dotenvFile, 38 | }) 39 | ); 40 | } 41 | }); 42 | 43 | // We support resolving modules according to `NODE_PATH`. 44 | // This lets you use absolute paths in imports inside large monorepos: 45 | // https://github.com/facebook/create-react-app/issues/253. 46 | // It works similar to `NODE_PATH` in Node itself: 47 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 48 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 49 | // Otherwise, we risk importing Node.js core modules into an app instead of webpack shims. 50 | // https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 51 | // We also resolve them to make sure all tools using them work consistently. 52 | const appDirectory = fs.realpathSync(process.cwd()); 53 | process.env.NODE_PATH = (process.env.NODE_PATH || "") 54 | .split(path.delimiter) 55 | .filter((folder) => folder && !path.isAbsolute(folder)) 56 | .map((folder) => path.resolve(appDirectory, folder)) 57 | .join(path.delimiter); 58 | 59 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 60 | // injected into the application via DefinePlugin in webpack configuration. 61 | const REACT_APP = /^REACT_APP_/i; 62 | 63 | function getClientEnvironment(publicUrl) { 64 | const raw = Object.keys(process.env) 65 | .filter((key) => REACT_APP.test(key)) 66 | .reduce( 67 | (env, key) => { 68 | env[key] = process.env[key]; 69 | return env; 70 | }, 71 | { 72 | // Useful for determining whether we’re running in production mode. 73 | // Most importantly, it switches React into the correct mode. 74 | NODE_ENV: process.env.NODE_ENV || "development", 75 | // Useful for resolving the correct path to static assets in `public`. 76 | // For example, . 77 | // This should only be used as an escape hatch. Normally you would put 78 | // images into the `src` and `import` them in code to get their paths. 79 | PUBLIC_URL: publicUrl, 80 | // We support configuring the sockjs pathname during development. 81 | // These settings let a developer run multiple simultaneous projects. 82 | // They are used as the connection `hostname`, `pathname` and `port` 83 | // in webpackHotDevClient. They are used as the `sockHost`, `sockPath` 84 | // and `sockPort` options in webpack-dev-server. 85 | WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST, 86 | WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH, 87 | WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT, 88 | // Whether or not react-refresh is enabled. 89 | // react-refresh is not 100% stable at this time, 90 | // which is why it's disabled by default. 91 | // It is defined here so it is available in the webpackHotDevClient. 92 | FAST_REFRESH: process.env.FAST_REFRESH !== "false", 93 | } 94 | ); 95 | // Stringify all values so we can feed into webpack DefinePlugin 96 | const stringified = { 97 | "process.env": Object.keys(raw).reduce((env, key) => { 98 | env[key] = JSON.stringify(raw[key]); 99 | return env; 100 | }, {}), 101 | __DEV__: true, 102 | 103 | __PROFILE__: true, 104 | 105 | __UMD__: true, 106 | 107 | __EXPERIMENTAL__: false, 108 | 109 | __VARIANT__: false, 110 | }; 111 | 112 | return { raw, stringified }; 113 | } 114 | 115 | module.exports = getClientEnvironment; 116 | -------------------------------------------------------------------------------- /config/getHttpsConfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const crypto = require('crypto'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const paths = require('./paths'); 8 | 9 | // Ensure the certificate and key provided are valid and if not 10 | // throw an easy to debug error 11 | function validateKeyAndCerts({ cert, key, keyFile, crtFile }) { 12 | let encrypted; 13 | try { 14 | // publicEncrypt will throw an error with an invalid cert 15 | encrypted = crypto.publicEncrypt(cert, Buffer.from('test')); 16 | } catch (err) { 17 | throw new Error( 18 | `The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}` 19 | ); 20 | } 21 | 22 | try { 23 | // privateDecrypt will throw an error with an invalid key 24 | crypto.privateDecrypt(key, encrypted); 25 | } catch (err) { 26 | throw new Error( 27 | `The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${ 28 | err.message 29 | }` 30 | ); 31 | } 32 | } 33 | 34 | // Read file and throw an error if it doesn't exist 35 | function readEnvFile(file, type) { 36 | if (!fs.existsSync(file)) { 37 | throw new Error( 38 | `You specified ${chalk.cyan( 39 | type 40 | )} in your env, but the file "${chalk.yellow(file)}" can't be found.` 41 | ); 42 | } 43 | return fs.readFileSync(file); 44 | } 45 | 46 | // Get the https config 47 | // Return cert files if provided in env, otherwise just true or false 48 | function getHttpsConfig() { 49 | const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env; 50 | const isHttps = HTTPS === 'true'; 51 | 52 | if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) { 53 | const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE); 54 | const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE); 55 | const config = { 56 | cert: readEnvFile(crtFile, 'SSL_CRT_FILE'), 57 | key: readEnvFile(keyFile, 'SSL_KEY_FILE'), 58 | }; 59 | 60 | validateKeyAndCerts({ ...config, keyFile, crtFile }); 61 | return config; 62 | } 63 | return isHttps; 64 | } 65 | 66 | module.exports = getHttpsConfig; 67 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /config/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const resolve = require('resolve'); 8 | 9 | /** 10 | * Get additional module paths based on the baseUrl of a compilerOptions object. 11 | * 12 | * @param {Object} options 13 | */ 14 | function getAdditionalModulePaths(options = {}) { 15 | const baseUrl = options.baseUrl; 16 | 17 | if (!baseUrl) { 18 | return ''; 19 | } 20 | 21 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 22 | 23 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is 24 | // the default behavior. 25 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { 26 | return null; 27 | } 28 | 29 | // Allow the user set the `baseUrl` to `appSrc`. 30 | if (path.relative(paths.appSrc, baseUrlResolved) === '') { 31 | return [paths.appSrc]; 32 | } 33 | 34 | // If the path is equal to the root directory we ignore it here. 35 | // We don't want to allow importing from the root directly as source files are 36 | // not transpiled outside of `src`. We do allow importing them with the 37 | // absolute path (e.g. `src/Components/Button.js`) but we set that up with 38 | // an alias. 39 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 40 | return null; 41 | } 42 | 43 | // Otherwise, throw an error. 44 | throw new Error( 45 | chalk.red.bold( 46 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." + 47 | ' Create React App does not support other values at this time.' 48 | ) 49 | ); 50 | } 51 | 52 | /** 53 | * Get webpack aliases based on the baseUrl of a compilerOptions object. 54 | * 55 | * @param {*} options 56 | */ 57 | function getWebpackAliases(options = {}) { 58 | const baseUrl = options.baseUrl; 59 | 60 | if (!baseUrl) { 61 | return {}; 62 | } 63 | 64 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 65 | 66 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 67 | return { 68 | src: paths.appSrc, 69 | }; 70 | } 71 | } 72 | 73 | /** 74 | * Get jest aliases based on the baseUrl of a compilerOptions object. 75 | * 76 | * @param {*} options 77 | */ 78 | function getJestAliases(options = {}) { 79 | const baseUrl = options.baseUrl; 80 | 81 | if (!baseUrl) { 82 | return {}; 83 | } 84 | 85 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 86 | 87 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 88 | return { 89 | '^src/(.*)$': '/src/$1', 90 | }; 91 | } 92 | } 93 | 94 | function getModules() { 95 | // Check if TypeScript is setup 96 | const hasTsConfig = fs.existsSync(paths.appTsConfig); 97 | const hasJsConfig = fs.existsSync(paths.appJsConfig); 98 | 99 | if (hasTsConfig && hasJsConfig) { 100 | throw new Error( 101 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' 102 | ); 103 | } 104 | 105 | let config; 106 | 107 | // If there's a tsconfig.json we assume it's a 108 | // TypeScript project and set up the config 109 | // based on tsconfig.json 110 | if (hasTsConfig) { 111 | const ts = require(resolve.sync('typescript', { 112 | basedir: paths.appNodeModules, 113 | })); 114 | config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; 115 | // Otherwise we'll check if there is jsconfig.json 116 | // for non TS projects. 117 | } else if (hasJsConfig) { 118 | config = require(paths.appJsConfig); 119 | } 120 | 121 | config = config || {}; 122 | const options = config.compilerOptions || {}; 123 | 124 | const additionalModulePaths = getAdditionalModulePaths(options); 125 | 126 | return { 127 | additionalModulePaths: additionalModulePaths, 128 | webpackAliases: getWebpackAliases(options), 129 | jestAliases: getJestAliases(options), 130 | hasTsConfig, 131 | }; 132 | } 133 | 134 | module.exports = getModules(); 135 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 13 | // "public path" at which the app is served. 14 | // webpack needs to know it to put the right