问题描述
<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
返回源代码不变。类似的东西:
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 文件的加载器。如果没有其他加载器,则它会丢弃自定义块的内容。否则,它将返回内容,期望其他加载程序知道如何处理它。这就是为什么添加另一个加载程序,即使是一个什么都不做的加载程序,也会导致构建失败。
如果您想更好地了解发生了什么,请查看 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 是如何解析模板的。它用导入语句和内联加载器链替换每个块。所以这个
fs.readFile(TOKEN_PATH,(err,token) => {
if (err) return getNewToken(oAuth2Client,callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
fs.readFile('credentials.json',content) => {
if (err) return console.log('Error loading client secret file:',err);
// Authorize a client with credentials,then call the Google Sheets API.
authorize(JSON.parse(content),listMajors);
});
变成这样
<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
重要的是您返回 vue-loader(使用 vue 模板编译器)能够解析的内容。因此,// CustomLoader.js
module.exports = function(source) {
if (this.resourceQuery.includes('type=custom')) {
return '<custom></custom>';
}
return source;
}
标记而不是空字符串。