当模板包含自定义标签时,将自定义加载器添加到 vue-loader 会中断

Prepending custom loader to vue-loader breaks when template includes custom tags

我有一个 vue2 组件,如下所示:

<template>
  <p>Hello world</p>
</template>

<script>
export default { name: 'Example' };
</script>

<docs>
Some documentation...
</docs>

我还想为我的 vue 文件使用一个额外的加载器,所以我的 webpack 配置如下所示:

module.exports = {
  module: {
    rules: [{
      test: /\.vue$/,
      use: [{
        loader: 'vue-loader',
      }, {
        loader: path.resolve(__dirname, 'CustomLoader.js'),
      }],
    }],
  },
};

// CustomLoader.js
module.exports = function(source) {
  return source;
}

运行 webpack bundle 抛出一个错误,它缺少 <docs> 块的加载程序,即使 CustomLoader returns 源代码未更改。大致如下:

Error in path/to/component.vue?vue&type=custom&index=0&blockType=docs
Module parse failed: Unexpected token
File was processed with these loaders:
* ./node_modules/vue-loader/lib.index.js
* ./CustomLoader.js
You may need an additional loader to handle the result of these loaders.

删除其中一个

谁能告诉我问题出在哪里?

在深入研究 vue-loader 的源代码后,我自己找到了答案。从广义上讲,vue-loader 检查是否存在另一个 vue 文件加载器。如果没有其他加载程序,则它会丢弃自定义块的内容。否则,它将 return 内容,期望其他加载器知道如何处理它。这就是为什么添加另一个加载程序,即使是什么都不做的加载程序,也会导致构建失败。

如果您想更好地了解发生了什么,请查看 vue-loader 源代码,特别是:

要了解如何解决这个问题,您必须首先了解 vue-loader 如何解析模板。它用导入语句和内联加载程序链替换每个块。所以这个

<template>
  <!-- ... -->
</template>

<script>
// ...
</script>

<docs>
// ...
</docs>

变成这样

import render from 'custom-loader!vue-loader!source.vue?vue&type=template'
import script from 'custom-loader!vue-loader!source.vue?vue&type=script'
import 'custom-loader!vue-loader!source.vue?vue&type=custom&blockType=docs'

因此,从本质上讲,自定义加载程序将针对每个 .vue 文件多次调用。第一次通过一次,然后对扩展的每个块再次进行一次。

我的解决方法是检查加载程序中的 resourceQuery。如果它指向自定义块,我只是 return 一个空模板。像这样:

// CustomLoader.js
module.exports = function(source) {
  if (this.resourceQuery.includes('type=custom')) {
    return '<custom></custom>';
  }
  return source;
}

重要的是你 return vue-loader(使用 vue 模板编译器)能够解析的东西。因此 <custom> 标签而不是空字符串。