vue-loader加载错误问题

问题描述

主要记录一下开发过程中遇到的一次vue-loader加载异常问题。问题描述:

当前有A、B、C 3个.vue文件,其中在A里面局部注册了B组件。B 和 C 无论是文件内容、文件命名还是文件存储位置都没有半毛线关系。然而实际页面渲染的时候,将B组件渲染成了C。应用里其他用到B组件的地方也全部变成了C。

查看对应组件的js文件发现:

((typeof self !== 'undefined' ? self : this)["webpackJsonp"] = (typeof self !== 'undefined' ? self : this)["webpackJsonp"] || []).push([[15], {

    /***/
    "./node_modules/cache-loader/dist/cjs.js?{\"cacheDirectory\":\"node_modules/.cache/vue-loader\",\"cacheIdentifier\":\"433a206b-vue-loader-template\"}!./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/B/index.vue?vue&type=template&id=72514296&scoped=true&": /*!***********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"433a206b-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/B/index.vue?vue&type=template&id=72514296&scoped=true& ***!
  \***********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
    /*! exports provided: render, staticRenderFns */
    /***/
    (function(module, __webpack_exports__, __webpack_require__) {

        "use strict";
        eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function() {\n  var _vm = this\n  var _h = _vm.$createElement\n  var _c = _vm._self._c || _h\n  return _c(\"div\",...));

        /***/
    }
    ),

}]);

发现其内部虽然指示了B组件,但是生成的render函数是C组件,所以最终渲染的也是C组件。

而上一段的render函数是在vue-loader的输出产物中依然发生了错误,所以我们需要查找vue-loader中可能造成该结果的地方。

问题排查

查找vue-loader源码,查看到以下这段代码

function parse(options) {
    const { source, filename = '', compiler, compilerParseOptions = { pad: 'line' }, sourceRoot = '', needMap = true } = options;
    const cacheKey = hash(filename + source + JSON.stringify(compilerParseOptions));
    let output = cache.get(cacheKey);
    if (output)
        return output;
    output = compiler.parseComponent(source, compilerParseOptions);
    if (needMap) {
        if (output.script && !output.script.src) {
            output.script.map = generateSourceMap(filename, source, output.script.content, sourceRoot, compilerParseOptions.pad);
        }
        if (output.styles) {
            output.styles.forEach(style => {
                if (!style.src) {
                    style.map = generateSourceMap(filename, source, style.content, sourceRoot, compilerParseOptions.pad);
                }
            });
        }
    }
    cache.set(cacheKey, output);
    return output;
}

在上面的parse函数中,有一步缓存动作,该段代码是将文件名filename,文件内容source以及编译配置compilerParseOptions一起生成一个hash值,理论上是想保证同一文件在同一编译配置下只编译一次。将编译后的结果存储在cache中,后续如果命中缓存,就存缓存中读取,提升编译效率。

但是问题就发生在了这一步缓存上,理论上不同文件对应的hash肯定不同。但是神奇的是,这俩文件B和C对应的hash是一样的,这就导致编译的时候先编译了C,后面再遇到B时,由于hash相同,直接从缓存cache中取出C的编译结果,导致B渲染成了C。这种概率真的算是很难装上了吧,大概堪比中彩票了。

解决问题

找到原因以后,问题就比较好解决了。由于是hash值撞了,只要修改文件内容或者文件名称,就能改变该文件对应的hash值。所以修改B或者C中任意一文件,随便加点什么注释空格啥的,就解决了该问题。

虽然问题不难解决,但是定位问题的过程还是挺麻烦的,还是请教了其他同事,才定位到vue-loader的parse函数的。不然真是一团乱,毕竟也没认真读过vue-loader的源码,简直毫无头绪。仅此记录,以供参考。虽然概率很低,万一有人遇到了,也不失一种借鉴

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值