webpack + vue 在dev和production模式下的小小区别
上周的某一天,和一位同样是前端技术极度爱好的开发者朋友聊天,他在提出了一个问题,他写的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模式下的小小区别的更多相关文章
- 基于 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 时代,包括其插件在需要时就引 ...
- 066——VUE中vue-router之rewrite模式下配置404页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【HTML&CSS】 第二章:标准模式下的页面与怪异模式下的页面区别
盒模型 前面提到,盒模型(box mode)是浏览器 Quirks Mode 和 Standards Mode 的主要区别. 描述 对于“盒模型”一词并没有明确的文档定义,它是开发人员描述 CSS 中 ...
- Vue 路由知识二(工程模式下路由的配置)
vue-router是一个插件包,所以我们还是需要用npm/cnpm来进行安装的:npm/cnpm install vue-router --save-dev. 在路由的核心文件:src/router ...
- Video.js + HLS 在production环境下webpack打包后出错的解决方案
Video.js是一个非常强大的视频播放库,能在微信下完美提供inline小窗口播放模式,但当涉及到hls格式视频播放时就比较麻烦,出现的数种现象都不好解决. 错误现象: 1. PC Chrome ...
- webpack中Development和Production模式的区分打包
当我们在开发一个项目的时候,我们一般用development这个环境进行项目的开发,在这个环境下,webpack使用dev-server,帮我们启用一个服务器,然后这个服务器里面还集成了一些,比如hm ...
- VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示
VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示: “事件”引起变量值的变化,系统引擎自动根据变量值的变化刷新页面 在VUE Nod ...
- Vue项目history模式下微信分享总结
原文 : http://justyeh.top/post/39/ 2019-07-02 Vue微信分享 每回遇到微信分享都是一个坑,目前的商城项目使用Vue开发,采用history的路由模式,配置微信 ...
- 解决IE报错[vue router]Failed to resolve async component default:strict 模式下不允许分配到只读属性
之前遇到过一个奇怪的问题,在其他浏览器下一切正常,但在万恶的IE下,却一直不行. 具体问题场景就是:比如orderDetail页面出现问题,那么只要是路由跳转的,点第1次无法跳转,必须得点第2次才可以 ...
随机推荐
- Visual studio2010和Modelsim配置SystemC开发(转)
本文转自一博文. 一.编译System库 1. 下载SystemC library source code, 到http://www.systemc.org注册会员账号后,即可下载SystemC li ...
- 【Django】 gunicorn部署纪要
使用Gunicorn 来部署Django应用, 没有一步一步写怎么操作,简单记录下重要的点,方面以后查阅. 主要的方式还是Nginx反向代理到Gunicorn, Gunicorn wsgi来启动Dja ...
- LeetCode之旅(13)-Valid Anagram
题目介绍: Given two strings s and t, write a function to determine if t is an anagram of s. For example, ...
- HTML 5核心内容
demo飞象 HTML 5 系列文章索引:http://www.cnblogs.com/webabcd/archive/2012/05/27/2520567.html demo飞象HTML 5 (11 ...
- volatile的适用场景
volatile保证线程间的数据是可见的(共享的),但不保证数据同步 volatile相当于synchronized的弱实现,也就是说volatile实现了类似synchronized的语义,却又没有 ...
- quicksort(java版)
相信大家都知道几种排序算法,比如说冒泡排序,选择排序,插入排序等等,这些个算法都不是很难,自己多多理解理解就能掌握了,而今天我们要谈的就是重头戏就是快速排序. 引用大牛的思想来对排序算法解释一下.(文 ...
- Application "org.eclipse.ui.ide.workbench" could not be found in the registry.问题的解决
今天升级Eclipse,升级完Restart,碰到启动不了让看日志,日志里主要错误信息即是Application "org.eclipse.ui.ide.workbench" co ...
- Java经验杂谈(2.对Java多态的理解)
多态是面向对象的重要特性之一,我试着用最简单的方式解释Java多态: 要正确理解多态,我们需要明确如下概念:・定义类型和实际类型・重载和重写・编译和运行 其中实际类型为new关键字后面的类型. 重载发 ...
- Scala编程入门---面向对象编程之Trait高级知识
trait调用链 Scala中支持让类继承多个Trait后,依次调用多个Trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可 类中调用多个trait中都有这个 ...
- C#高级编程笔记之第一章:.NET体系结构
1.1 C#与.NET的关系 C#不能孤立地使用,必须与.NET Framework一起使用一起考虑. (1)C#的体系结构和方法论反映了.NET基础方法论. (2)多数情况下,C#的特定语言功能取决 ...