【问题标题】:eslint: howto lint only touched fileseslint:如何对仅接触过的文件进行 lint
【发布时间】:2020-08-18 18:39:04
【问题描述】:

我最近在一个从未使用 linter 解析过的代码库中添加了 eslint,作为 webpack 加载器。

显然触发的错误是无穷无尽的:有没有机会配置 eslint 只解析被触摸的文件?我希望 linter 解析开发人员进行更改的每个文件,并且仅限于这些文件。

这是我目前使用的加载器(以防万一),非常标准的配置:

{test: /\.(jsx|js)$/, loader: "eslint-loader?{cache: true}", exclude: /node_modules/}

谢谢

【问题讨论】:

  • 嗯,“开发人员做出改变”的概念非常广泛。 eslint 没有任何内置的源代码版本控制概念,因此很难理解哪些文件已更改,哪些文件未更改
  • 我不认为有办法直接用 eslint 来做,但我想到的第一件事可能是创建一个脚本,它使用 git 和 eslint 创建一个 eslintignore 文件跨度>
  • @Mazzy 你说的很有道理。当你说 git 时,我想到了提交时的 linter 解析; Makefile 可以节省时间。这两个有趣的选项,目前我都无法弄清楚哪个对我来说听起来更好。
  • 是的,您可以从 Makefile 或 npm 脚本运行 lint。通常将 eslint 放在 npm 脚本中并在执行测试之前运行它或作为 git 的 prehook 是很常见的
  • 我认为 Makefile 将依赖于每次保存文件时运行make:所以这可能是一个编辑器配置。我不喜欢依赖编辑器设置的想法,我更喜欢系统设置:所以在我看来,对于这种特定情况,git hook 胜过 make。我也在考虑一个观察者,检查哪些文件正在发生变化,并从那里运行一个 linter。像这样的东西:npmjs.com/package/watch

标签: javascript webpack eslint


【解决方案1】:

我通过使用观察者来完成它;这是详细的解决方案:

Webpack 配置的依赖项:

var logger = require('reliable-logger');
var watch = require('watch');
var CLIEngine =  require('eslint').CLIEngine

watcher 和 linter 配置和启动;我将它与所有待办事项一起粘贴,原样:

var configureLinterAndWatchFiles = function() {
var changedFiles = [];
var formatter;
var report;
var SEPARATOR = "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////";

// TODO I got the feeling that one of those settings is breaking the
//   linter (probably the path resolving?)
var linter =  new CLIEngine({
    // TODO do I need this? Looks like I don't...
    // envs: ["node"],
    // TODO what is the default?
    useEslintrc: true,
    // TODO I find weird that I get no error with this: configFile: "../.eslintrc1111"
    //  make sure that the configuration file is correctly picked up
    configFile: ".eslintrc",
    // TODO useless if your root is src
    // ignorePath: "node_modules"
    // TODO probably both useless... the first I still don't get it,
    //   the second you are enforcing the filtering yourself by checks
    // cache: false,
    // extensions: [".js", ".jsx"]
});

var fileUpdatedFn = function(f) {
    // TODO I would prefer much more to get the list of changed files from
    //   git status (how to?). Here I am building my own
    // resetting the array only for debug purpose
    // changedFiles = [];
    if(/.js$/.test(f) || /.jsx$/.test(f)) {
        changedFiles.push(f);
        logger.info(SEPARATOR);
        report = linter.executeOnFiles(changedFiles);
        logger.info(formatter(report.results));
    }
};

// get the default formatter
formatter = linter.getFormatter();

watch.watchTree('src', function(f, curr, prev) {
    if (typeof f == "object" && prev === null && curr === null) {
    // Finished walking the tree
    } else if (prev === null) {
    // f is a new file
    } else if (curr.nlink === 0) {
    // f was removed
    } else {
        // f was changed
        fileUpdatedFn(f);
    }
});

};

在 module.exports 中,最后一行:

module.exports = function(callback, options){
  // ... more code ...
  configureLinterAndWatchFiles();
}

应该是这样的。正如我在评论中指出的那样:

不过,我想知道缓存标志 (eslint.org/docs/developer-guide/nodejs-api#cliengine) 是否最适合用于解决问题。从这里(github.com/adametry/gulp-eslint/issues/...):“--cache 标志将跳过任何在上次运行中没有问题的文件,除非它们已被修改”:不确定这是否是我的情况但很有趣。

【讨论】:

    【解决方案2】:

    当然,我参加聚会有点晚了,但我今天遇到了同样的问题,而且似乎仍然没有通用的解决方案。

    我最终用这个猴子修补了 webpack 的 devServer

      const { exec } = require('child_process');
      
      // ...
      
      devServer: {
        hot: false,
        inline: false,
        publicPath: '/',
        historyApiFallback: true,
        disableHostCheck: true,
        after: (app, server, compiler) => {
          compiler.hooks.watchRun.tap(
            'EsLint-upon-save',
            () => {
              // This should only work in dev environment
              if (process.env.NODE_ENV !== 'development') {
                return;
              }
            
              // Credits to:
              // https://stackoverflow.com/a/43149576/9430588
              const filesChanged = Object.keys(compiler.watchFileSystem.watcher.mtimes);
              
              // Might be empty
              if (!filesChanged.length) {
                return;
              }
    
              filesChanged.forEach((changedFileAbsolutePath) => {
                const extension = changedFileAbsolutePath.split('.').pop();
    
                if (extension === 'js' || extension === 'jsx') {
                  exec(`npx eslint --fix --fix-type suggestion,layout ${changedFileAbsolutePath}`); 
                }
              });
            }
          );
        }
      },
    

    这肯定是一种非常快速和肮脏的解决方案,但它似乎与eslint@7.7.0 一起工作。

    【讨论】:

      猜你喜欢
      • 2019-06-05
      • 2015-11-10
      • 2019-06-09
      • 1970-01-01
      • 2013-11-18
      • 2020-09-23
      • 2019-10-29
      • 2019-07-23
      • 1970-01-01
      相关资源
      最近更新 更多