上周的某一天,和一位同样是前端技术极度爱好的开发者朋友聊天,他在提出了一个问题,他写的vue程序为什么在dev模式运行良好,而在production模式就直接报错了。这让我感到惊讶,还有这么神奇的事情。今就把这个历险记道给大伙听听,看能从中学习到什么?

一、还原现场

朋友在看到我的惊讶后,分分就把他出错的demo发给了,本地运行,事故现场重现:

二、排查嫌疑对象

既然现象是必现,要么是自己的代码出了问题,要么就是vue有Bug(心里莫名的偷笑,大伙都懂的)。

2.1 代码文件结构和源码展示


从代码结构看,没有好说的。就是用vue-cli创建的模板开发项目,其保增加了service层而已。经过我多年来的经验,将嫌疑放到了service/index.js和components/HellowWorld.vue两个文件上。

  • service/index.js代码
let item = {};
item.result = 22222;
item.do = callBack => {
return callBack({ result: this.a.result });
}; export default item;
  • HelloWorld.vue代码(只展示了js代码部分)
import service from "@/service/index"
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
mounted () {
service.do(item => {
this.msg = item.result
})
}
}

简要逻辑说明:

  • HelloWorld.vue引用了service/index.js文件
  • service/index.js中定义了do方法,且接受一个callback参数(使用了es6的箭头函数)
  • HelloWorld.vue在mounted方法中调用了do方法,且传入了一个函数表达式(也使用了箭头函数)

2.2 报错位置侦查

通过运行结果对比图,可以看出production模式下的运行是有报错,在达里我们放大他的报错位置:

     看到这里,你是否有想破口大骂的冲动,怎么会this.a.result呢,这代码明显有错误吧。然后我迅速查阅了他给的demo代码,见service/index.js中的do方法,确实是怎么样写的。立刻,我略带鄙视的口吻质问我的那位朋友,你这个几年的代码白写了吧,居然能犯这么低级的错误。我直接把这个错误现场图扔给了他。

马上,他回了一个更为鄙视的表情,那为什么我的dev模式能正常运行呢。我立即无语且尴尬。因为确实他的dev模式运行是正常的,只有在production模式下才出的问题啊。

2.3 重点分析嫌疑对象

经过上述的分析和折腾,我们可以初步确定问题点就在service/index.js中do方法中和this上。也就是说在dev模式下这个this.a上是有result这个属性的,而在production模式下this连这个a属性都没有了。

作为老鸟的我,突然想到,dev模式和production模式都是运行在有sourcemap的的情况下的。这很不利用我们看编译后的代码。于是,我关闭了chrome浏览器的sourcemap功能,两种模式下代码如下:

  • dev模式下的运行代码:

    注意三个红框处的代码,webpack在dev模式下代码文件是没有合并成一个文件的,而是遵行commanJs规范,进行模式化加载的,而他对这个service/index.js这个模式导出时,用的名称正是a。也就是解释了在dev模式下this.a为什么会有效,他的this.a.result有值,则是因为他虽然是单文件模式化加载,但其文件中的js代码还是被bable做了转换,将箭头运算符转换为了es5可执行的代码。所以this.a.result是有值的。
  • production模式下的运行代码:

         看这段代码是否有些头大,其实从中我们只需要关心l这个变量的值,经测试发现,他的值不service/index.js中导出的对象,而是浏览器全局对象window。这就是为什么production模式下的代码不能正常运行的问题了。

三、我的推理和总结

通过上述分析,可以大致推理出webpack在dev模式下是按照commonJs模式将各个文件独立模式化加载和引用,而Build之后,各个文件模块被合并成了一个,且对servcie/index.js进行了直接导出。再中上箭头函数对this指向的处理,就造成了this.a无效了。
     在这个demo中就算把service/index.js中的this指向处理好了,但其值还是会正常显示,原因在于vue组件中的mounted方法中也用到了箭头函数,其this的指向在运行时也会不正确。具体解释如下:

    注意,不要在实例属性或者回调函数中(如 vm.$watch('a', newVal => this.myMethod()))使用箭头函数。因为箭头函数绑定父级上下文,所以 this 不会像预想的一样是 Vue 实例,而且 this.myMethod 是未被定义的。

vue官网说明地址:https://cn.vuejs.org/v2/guide/instance.html

3.1 原因总结

  • this.a为什么可以访问,是因为webpack的dev下编译是单个文件模式化引用导致的
  • vue组件的mounted中用不可使用箭头函数,这个vue的特性,官网可见。
  • 示例代码下载

webpack + vue 在dev和production模式下的小小区别的更多相关文章

  1. 基于 Vue.js 之 iView UI 框架非工程化实践记要 使用 Newtonsoft.Json 操作 JSON 字符串 基于.net core实现项目自动编译、并生成nuget包 webpack + vue 在dev和production模式下的小小区别 这样入门asp.net core 之 静态文件 这样入门asp.net core,如何

    基于 Vue.js 之 iView UI 框架非工程化实践记要   像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引 ...

  2. 066——VUE中vue-router之rewrite模式下配置404页面

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 【HTML&CSS】 第二章:标准模式下的页面与怪异模式下的页面区别

    盒模型 前面提到,盒模型(box mode)是浏览器 Quirks Mode 和 Standards Mode 的主要区别. 描述 对于“盒模型”一词并没有明确的文档定义,它是开发人员描述 CSS 中 ...

  4. Vue 路由知识二(工程模式下路由的配置)

    vue-router是一个插件包,所以我们还是需要用npm/cnpm来进行安装的:npm/cnpm install vue-router --save-dev. 在路由的核心文件:src/router ...

  5. Video.js + HLS 在production环境下webpack打包后出错的解决方案

    Video.js是一个非常强大的视频播放库,能在微信下完美提供inline小窗口播放模式,但当涉及到hls格式视频播放时就比较麻烦,出现的数种现象都不好解决. 错误现象:  1.  PC Chrome ...

  6. webpack中Development和Production模式的区分打包

    当我们在开发一个项目的时候,我们一般用development这个环境进行项目的开发,在这个环境下,webpack使用dev-server,帮我们启用一个服务器,然后这个服务器里面还集成了一些,比如hm ...

  7. VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示

    VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示: “事件”引起变量值的变化,系统引擎自动根据变量值的变化刷新页面 在VUE Nod ...

  8. Vue项目history模式下微信分享总结

    原文 : http://justyeh.top/post/39/ 2019-07-02 Vue微信分享 每回遇到微信分享都是一个坑,目前的商城项目使用Vue开发,采用history的路由模式,配置微信 ...

  9. 解决IE报错[vue router]Failed to resolve async component default:strict 模式下不允许分配到只读属性

    之前遇到过一个奇怪的问题,在其他浏览器下一切正常,但在万恶的IE下,却一直不行. 具体问题场景就是:比如orderDetail页面出现问题,那么只要是路由跳转的,点第1次无法跳转,必须得点第2次才可以 ...

随机推荐

  1. Visual studio2010和Modelsim配置SystemC开发(转)

    本文转自一博文. 一.编译System库 1. 下载SystemC library source code, 到http://www.systemc.org注册会员账号后,即可下载SystemC li ...

  2. 【Django】 gunicorn部署纪要

    使用Gunicorn 来部署Django应用, 没有一步一步写怎么操作,简单记录下重要的点,方面以后查阅. 主要的方式还是Nginx反向代理到Gunicorn, Gunicorn wsgi来启动Dja ...

  3. LeetCode之旅(13)-Valid Anagram

    题目介绍: Given two strings s and t, write a function to determine if t is an anagram of s. For example, ...

  4. HTML 5核心内容

    demo飞象 HTML 5 系列文章索引:http://www.cnblogs.com/webabcd/archive/2012/05/27/2520567.html demo飞象HTML 5 (11 ...

  5. volatile的适用场景

    volatile保证线程间的数据是可见的(共享的),但不保证数据同步 volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有 ...

  6. quicksort(java版)

    相信大家都知道几种排序算法,比如说冒泡排序,选择排序,插入排序等等,这些个算法都不是很难,自己多多理解理解就能掌握了,而今天我们要谈的就是重头戏就是快速排序. 引用大牛的思想来对排序算法解释一下.(文 ...

  7. Application "org.eclipse.ui.ide.workbench" could not be found in the registry.问题的解决

    今天升级Eclipse,升级完Restart,碰到启动不了让看日志,日志里主要错误信息即是Application "org.eclipse.ui.ide.workbench" co ...

  8. Java经验杂谈(2.对Java多态的理解)

    多态是面向对象的重要特性之一,我试着用最简单的方式解释Java多态: 要正确理解多态,我们需要明确如下概念:・定义类型和实际类型・重载和重写・编译和运行 其中实际类型为new关键字后面的类型. 重载发 ...

  9. Scala编程入门---面向对象编程之Trait高级知识

    trait调用链 Scala中支持让类继承多个Trait后,依次调用多个Trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可 类中调用多个trait中都有这个 ...

  10. C#高级编程笔记之第一章:.NET体系结构

    1.1 C#与.NET的关系 C#不能孤立地使用,必须与.NET Framework一起使用一起考虑. (1)C#的体系结构和方法论反映了.NET基础方法论. (2)多数情况下,C#的特定语言功能取决 ...