构建CRA项目时只显示第一个错误

Est*_*ask 5 webpack react-scripts create-react-app

在默认的基于 TypeScript 的create-react-app项目中,在构建项目时只显示第一个 TS 错误,react-scripts但在运行时会显示所有错误tsc。

项目初始化为create-react-app foo --typescript,仅src/index.tsx在初始化后修改:

源代码/索引.tsx 源代码 /索引.tsx

console.log(typeof nonExistentVar);
    console.log(typeof nonExistentVar);
console.log(typeof nonExistentVar2);
    console.log(typeof nonExistentVar2);
export {};
Run Code Online (Sandbox Code Playgroud)

包.json

export {};
{


  "name": "foo",

  "version": "0.1.0",

  "private": true,

  "dependencies": {

    "@types/jest": "24.0.15",

    "@types/node": "12.6.8",

    "@types/react": "16.8.23",

    "@types/react-dom": "16.8.5",

    "react": "^16.8.6",

    "react-dom": "^16.8.6",

    "react-scripts": "3.0.1",

    "typescript": "3.5.3"

  },

  "scripts": {

    "start": "react-scripts start",

    "build": "react-scripts build",

    "test": "react-scripts test",

    "eject": "react-scripts eject"

  },

  "browserslist": {

    "production": [

      ">0.2%",

      "not dead",

      "not op_mini all"

    ],

    "development": [

      "last 1 chrome version",

      "last 1 firefox version",

      "last 1 safari version"

    ]

  }

}
Run Code Online (Sandbox Code Playgroud)

配置文件

{

  "compilerOptions": {

    "target": "es5",

    "lib": [

      "dom",

      "dom.iterable",

      "esnext"

    ],

    "allowJs": true,

    "skipLibCheck": true,

    "esModuleInterop": true,

    "allowSyntheticDefaultImports": true,

    "strict": true,

    "forceConsistentCasingInFileNames": true,

    "module": "esnext",

    "moduleResolution": "node",

    "resolveJsonModule": true,

    "isolatedModules": true,

    "noEmit": true,

    "jsx": "preserve"

  },

  "include": [

    "src"

  ]

}
Run Code Online (Sandbox Code Playgroud)

npm start 只显示第一个错误:

Failed to compile.

C:/foo/src/index.tsx
TypeScript error in C:/foo/src/index.tsx(1,20):
Cannot find name 'nonExistentVar'.  TS2304

  > 1 | console.log(typeof nonExistentVar);
      |                    ^
    2 | console.log(typeof nonExistentVar2);
    3 | export {};
Run Code Online (Sandbox Code Playgroud)

并tsc一次显示所有错误:

src/index.tsx:1:20 - error TS2304: Cannot find name 'nonExistentVar'.

1 console.log(typeof nonExistentVar);
                     ~~~~~~~~~~~~~~

src/index.tsx:2:20 - error TS2304: Cannot find name 'nonExistentVar2'.

2 console.log(typeof nonExistentVar2);
                     ~~~~~~~~~~~~~~~


Found 2 errors.
Run Code Online (Sandbox Code Playgroud)

如何强制start和build脚本显示所有错误?

zhi*_*rzh 5

问题?

这是真正发生的事情。当fork-ts-checker-webpack-plugin在您的代码中发现“类型错误”时,它会将它们添加到 webpack 的编译错误中以进行进一步处理和/或记录。

当执行包中的start脚本时react-scripts,相同的错误数组被修剪为长度 1。然后显示第一个错误(唯一的错误)并停止进程。

当build脚本运行时,它在内部react-dev-utils/WebpackDevServerUtils做同样的事情。


解决方案?

正如@amankkg指出的那样,“您必须弹出并调整scripts/build.js文件”,构建过程将按照您希望的方式工作。

真正的问题是启动一个开发服务器,因为react-dev-utils/WebpackDevServerUtils它是 node_modules 的一部分,在本地调整它不是一个长期的修复。最好的办法是在 github 上 fork 存储库,进行所需的更改并在您的项目中使用您的 fork 版本。


编辑 1

此外,如果您只使用 运行 webpack 配置webpack-cli,您会看到两个错误(以及已完成的构建)。

只需弹出代码,修改 webpack 的配置文件设置webpackEnv为NODE_ENV:

module.exports = function(webpackEnv) {
  webpackEnv = webpackEnv || process.env.NODE_ENV    //// add this line
  const isEnvDevelopment = webpackEnv === 'development';
  const isEnvProduction = webpackEnv === 'production';
Run Code Online (Sandbox Code Playgroud)

并运行以下命令:

npm i -g webpack-cli
NODE_ENV=development webpack --config config/webpack.config.js
Run Code Online (Sandbox Code Playgroud)

这是示例输出:

...

Entrypoint main = static/js/bundle.js ...

ERROR in /foo/src/index.tsx
ERROR in /foo/src/index.tsx(14,20):
TS2304: Cannot find name 'nonExistentVar'.

ERROR in /foo/src/index.tsx
ERROR in /foo/src/index.tsx(15,20):
TS2304: Cannot find name 'nonExistentVar2'.

...
Run Code Online (Sandbox Code Playgroud)

编辑 2

还有一件事你可以尝试。有这个节点包patch-package允许在本地修补 node_modules 代码并将所述补丁提交到您的存储库。我没有使用过它,但文档很好地解释了这个过程。你一定要检查一下。


Zaw*_*zor 1

找到了更好的解决方案。无需分叉或弹出。您可以编写一个非常简单的插件来fork-ts-checker-webpack-plugin获取所有错误并打印它们。编辑craco.config.js以在我的示例中创建插件类,我将其称为PrintAllWebpackErrorsPlugin. 然后在 的webpack部分实例化该类module.exports。不要忘记重置craco start以应用更改。该craco.config.js文件应如下所示:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
// This plugin uses a hook on the ForkTSCheckedWebpackPlugin to extract the errors and print them to console
class PrintAllWebpackErrorsPlugin {
    apply(compiler) {
        const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
        hooks.done.tap("PrintAllWebpackErrorsPlugin", function(errors) {
            errors.forEach(err => {
                console.log(err.file)
                console.log(`Typescript error in ${err.file}(${err.line},${err.character})`)
                console.log(`${err.message} TS${err.code}`)
            })
        })
    }
}

module.exports = {
    reactScriptsVersion: "react-scripts" /* (default value) */,
    style: {
        modules: {
            localIdentName: ""
        },
        css: {
            loaderOptions: { /* Any css-loader configuration options: https://github.com/webpack-contrib/css-loader. */ },
            loaderOptions: (cssLoaderOptions, { env, paths }) => { return cssLoaderOptions; }
        },
        sass: {
            loaderOptions: { /* Any sass-loader configuration options: https://github.com/webpack-contrib/sass-loader. */ },
            loaderOptions: (sassLoaderOptions, { env, paths }) => { return sassLoaderOptions; }
        },
        postcss: {
        }
    },
    eslint: {
        enable: false /* (default value) */,
        mode: "extends" /* (default value) */ || "file",
        configure: { /* Any eslint configuration options: https://eslint.org/docs/user-guide/configuring */ },
        configure: (eslintConfig, { env, paths }) => { return eslintConfig; },
        pluginOptions: { /* Any eslint plugin configuration options: https://github.com/webpack-contrib/eslint-webpack-plugin#options. */ },
        pluginOptions: (eslintOptions, { env, paths }) => { return eslintOptions; }
    },
    babel: {
        presets: [],
        plugins: [],
        loaderOptions: { /* Any babel-loader configuration options: https://github.com/babel/babel-loader. */ },
        loaderOptions: (babelLoaderOptions, { env, paths }) => { return babelLoaderOptions; }
    },
    typescript: {
        enableTypeChecking: true /* (default value)  */
    },
    webpack: {
        alias: {},
        plugins: {
            add: [
                // Notice I'm instantiating the plugin here to include it.
                new PrintAllWebpackErrorsPlugin(),
            ], /* An array of plugins */
            remove: [],  /* An array of plugin constructor's names (i.e. "StyleLintPlugin", "ESLintWebpackPlugin" ) */
        },
        configure: { /* Any webpack configuration options: https://webpack.js.org/configuration */ },
        configure: (webpackConfig, { env, paths }) => { return webpackConfig; }
    },
    jest: {
        babel: {
            addPresets: true, /* (default value) */
            addPlugins: true  /* (default value) */
        },
        configure: { /* Any Jest configuration options: https://jestjs.io/docs/en/configuration */ },
        configure: (jestConfig, { env, paths, resolve, rootDir }) => { return jestConfig; }
    },
    devServer: { /* Any devServer configuration options: https://webpack.js.org/configuration/dev-server/#devserver */ },
    devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => { return devServerConfig; },
    plugins: [
        {
            plugin: {
                overrideCracoConfig: ({ cracoConfig, pluginOptions, context: { env, paths } }) => { return cracoConfig; },
                overrideWebpackConfig: ({ webpackConfig, cracoConfig, pluginOptions, context: { env, paths } }) => { return webpackConfig; },
                overrideDevServerConfig: ({ devServerConfig, cracoConfig, pluginOptions, context: { env, paths, proxy, allowedHost } }) => { return devServerConfig; },
                overrideJestConfig: ({ jestConfig, cracoConfig, pluginOptions, context: { env, paths, resolve, rootDir } }) => { return jestConfig },
            },
            options: {}
        }
    ]
};
Run Code Online (Sandbox Code Playgroud)