当模板包含自定义标签时,将自定义加载器添加到 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.
删除其中一个
CustomLoader
<docs>
标签
解决问题。
谁能告诉我问题出在哪里?
在深入研究 vue-loader 的源代码后,我自己找到了答案。从广义上讲,vue-loader 检查是否存在另一个 vue 文件加载器。如果没有其他加载程序,则它会丢弃自定义块的内容。否则,它将 return 内容,期望其他加载器知道如何处理它。这就是为什么添加另一个加载程序,即使是什么都不做的加载程序,也会导致构建失败。
如果您想更好地了解发生了什么,请查看 vue-loader 源代码,特别是:
- https://github.com/vuejs/vue-loader/blob/master/lib/index.js
- https://github.com/vuejs/vue-loader/blob/master/lib/loaders/pitcher.js
要了解如何解决这个问题,您必须首先了解 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>
标签而不是空字符串。
我有一个 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.
删除其中一个
CustomLoader
<docs>
标签 解决问题。
谁能告诉我问题出在哪里?
在深入研究 vue-loader 的源代码后,我自己找到了答案。从广义上讲,vue-loader 检查是否存在另一个 vue 文件加载器。如果没有其他加载程序,则它会丢弃自定义块的内容。否则,它将 return 内容,期望其他加载器知道如何处理它。这就是为什么添加另一个加载程序,即使是什么都不做的加载程序,也会导致构建失败。
如果您想更好地了解发生了什么,请查看 vue-loader 源代码,特别是:
- https://github.com/vuejs/vue-loader/blob/master/lib/index.js
- https://github.com/vuejs/vue-loader/blob/master/lib/loaders/pitcher.js
要了解如何解决这个问题,您必须首先了解 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>
标签而不是空字符串。