webpack + vue 在dev和production模式下的小小區別

来源:https://www.cnblogs.com/cqhaibin/archive/2018/04/21/8902139.html
-Advertisement-
Play Games

上周的某一天,和一位同樣是前端技術極度愛好的開發者朋友聊天,他在提出了一個問題,他寫的vue程式為什麼在dev模式運行良好,而在production模式就直接報錯了。這讓我感到驚訝,還有這麼神奇的事情。今就把這個歷險記道給大伙聽聽,看能從中學習到什麼? 一、還原現場 朋友在看到我的驚訝後,分分就把他 ...


     上周的某一天,和一位同樣是前端技術極度愛好的開發者朋友聊天,他在提出了一個問題,他寫的vue程式為什麼在dev模式運行良好,而在production模式就直接報錯了。這讓我感到驚訝,還有這麼神奇的事情。今就把這個歷險記道給大伙聽聽,看能從中學習到什麼?

一、還原現場

朋友在看到我的驚訝後,分分就把他出錯的demo發給了,本地運行,事故現場重現: image

二、排查嫌疑對象

既然現象是必現,要麼是自己的代碼出了問題,要麼就是vue有Bug(心裡莫名的偷笑,大伙都懂的)。

2.1 代碼文件結構和源碼展示

image
從代碼結構看,沒有好說的。就是用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模式下的運行是有報錯,在達里我們放大他的報錯位置:
image
     看到這裡,你是否有想破口大罵的衝動,怎麼會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模式下的運行代碼:
    image
    註意三個紅框處的代碼,webpack在dev模式下代碼文件是沒有合併成一個文件的,而是遵行commanJs規範,進行模式化載入的,而他對這個service/index.js這個模式導出時,用的名稱正是a。也就是解釋了在dev模式下this.a為什麼會有效,他的this.a.result有值,則是因為他雖然是單文件模式化載入,但其文件中的js代碼還是被bable做了轉換,將箭頭運算符轉換為了es5可執行的代碼。所以this.a.result是有值的。

 

  • production模式下的運行代碼:
    image
         看這段代碼是否有些頭大,其實從中我們只需要關心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的特性,官網可見。
  • 示例代碼下載

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • npm作為下載node附送的大禮包,大家一定不會陌生。 然而關於npm,估計大量的只是用到npm install XXX以及npm run XXX。 其實這裡邊還有很多有意思的命令&參數。關於npm,大概有兩個作用: 下載相關的操作 下載主要就是圍繞著install這一個命令來的。 install ...
  • 建議儘量都使用 ,原因如下: 一致性:使用==對一致性沒有任何好處,那麼為什麼不避免使用呢。 簡單和性能:一般來說, 是最簡單的操作符,因為它不用進行類型轉換。JavaScript引擎的性能參差不齊,但是在大部分瀏覽器中 比==速度更快。 即使會自動轉換,但並不總是按你需要的方式轉換:比如7+“3” ...
  • ``` /* * 需求:給圖片的src地址前面增加為assets * * 1. 將需要匹配的內容原封不動的寫入正則表達式 * 2. 將改變的內容替換為.*? * 3. 將.*?添加(),目的是為了能夠將src中的內容單獨匹配一次作為匹配結果 * 4.通過replace將內容替換 * content.... ...
  • undefined和null與任何有意義的值比較返回的都是false,但是null與undefined之間互相比較返回的是true。 console.log(null == false); //false console.log(null == true); //false console.log( ...
  • 在做這個功能時,圖片被擋住了。。 解決辦法 在這個圖片的css裡加上z-index:數字;(數字可以為正也可以為負數) z-index:1肯定在z-index:-1的上面 用這個屬性來給div分層 是個不錯的選擇 ...
  • 運用摺疊面板後 可以讓頁面更加整潔 有什麼不懂的可以留言 代碼放到底部 需要引入的文件 JQuery代碼: html代碼 <div class="layui-colla-item"> <div class="layui-colla-title" style="background-color: #e ...
  • 以往 HTML 的 input 輸入框,無法即時(實時)反映使用者(用戶)的輸入內容。現在 HTML5 新增的 input 事件,可達成此一需求。 ...
  • input輸入框<div id="top-title" style="position: relative"> <img class="img-responsive center-block" alt="" src="" style="float:left;z-index: 999;position ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...