eslint-loader无法检查vue-loader编译的js部分的代码

宋博易
2023-12-01

eslint-loader无法检查vue-loader编译的js部分的代码

在使用webpack+vue开发时,一般使用vue-loader对.vue文件进行处理。

// webpack.config.js
// ...
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.export = {
	//...
	module:{
		rules: [
			// ...
			{
				test: /\.vue$/,
				use: 'vue-loader'
			}
		]
	},
	plugins: [
		new VueLoaderPlugin()
	]
}

vue-loader

vue-loader加载器可以解析处理vue单文件组件(SFC)。

它可以将vue组件解析的每个部分使用对应的loader,例如sytle标签使用sass,template标签使用pub。

具体过程:

  1. 通过编译器,将vue中template、script、style标签中的内容提取,转化为导入导出的方式,用type参数区分使用的loader

    // source.vue会被处理为:
     
    // import the <template> block
    import render from 'source.vue?vue&type=template'
    // import the <script> block
    import script from 'source.vue?vue&type=script'
    export * from 'source.vue?vue&type=script'
    // import <style> blocks
    import 'source.vue?vue&type=style&index=1'
     
    script.render = render
    export default script
    
  2. VueLoaderPlugin插件会克隆webpack中的rules,并根据type去执行对应的rules。例如:

    // webpack中配置了babel-loader
    // import script from 'source.vue?vue&type=script'
    // 会被扩展为:
    import script from 'babel-loader!vue-loader!source.vue?vue&type=script'
    

它还提供vue的HMR热替换功能。(需要webpack开启HMR)

问题重现

根据上面的介绍,vue-loader会使用插件拷贝rules中的规则,然后对从.vue文件提取的js文件使用响应的js rule。

于是我在项目中使用了下面的rule

{
  test: '/\.js$/',
  exclude: /node_modules/,
  use: [
    'babel-loader',
    'eslint-loader'
  ]
},
{
  test: /\.vue$/,
    use: [
      'vue-loader',
    ]
}

理论上eslint-loader应该可以校验vue-loader处理vue文件获得的js代码。

但是结果并没有。又采取了以下方案:

  1. 去掉exclude(虽然babel编译报错,但eslint还是没有校验)

  2. 为eslint-loader单独写一个rule,依然无效(代码中exclude和enforce写不写都无效)

    {
      test: /\.js$/,
      use: [
        'eslint-loader',
      ],
      // exclude: /node_modules/,
      // enforce: 'pre',
    },
    

最终没有找到原因,老老实实的给vue匹配加了个rule

{
  test: /\.(js|vue)$/,
  use: [
    'eslint-loader',
  ],
  enforce: 'pre' // 保证编译前执行
},

真相

VueLoaderPlugin插件的源码中,选择性的忽略了eslint-loader。。。。。。。。。。。。。。。。

const dedupeESLintLoader = loaders => {
  const res = []
  let seen = false
  loaders.forEach(l => {
    if (!isESLintLoader(l)) {
      res.push(l)
    } else if (!seen) {
      seen = true
      res.push(l)
    }
  })
  return res
}
 类似资料: