摘要:選擇性編譯是指根據打包是環境的不同,選擇性地讓特定的語句有效,讓特定的語句無效。選擇性編譯是筆者自己瞎想出來的名詞,不知道用的對不對。檢測時,還沒有被替換掉。
背景
程序在開發的過程中,少不了打印調試用的日志,測試流程時偽造的數據。這些代碼是不能出現在生產環境上的。
這意味著在程序打包前,需要把相關代碼剔除掉。
這些事情用人手去做很麻煩,很容易疏漏。而且打包出來測試時遇到了bug,又得重新把測試代碼添加回去。重復整個繁瑣的過程。
既然人工做這么麻煩而且容易出錯,那能不能用程序幫我們完成這些事情呢?
當然可以,用選擇性編譯技術就行,本文就介紹在webpack下解決這一問題的方法。
其實這個方法在webpack官網就有提到,本文只是提供相關示例及做一些延伸。
選擇性編譯是指根據打包是環境的不同,選擇性地讓特定的語句有效,讓特定的語句無效。實踐過程 首先,先讓我們看一個選擇性打印日志的示例。
最簡單的例子,在開發環境中,我們打印日志,但在生產環境中,我們讓所有打印日志的語句無效(讓程序不運行打印的語句,甚至讓打包出來的文件根本就不包含打印日志的語句)。
選擇性編譯是筆者自己瞎想出來的名詞,不知道用的對不對。
新建一個vue項目
打開build/webpack.dev.conf.js文件(項目處于開發環境時使用到的webpack打包配置,運行npm run dev,這個文件就會被執行)
添加如下代碼
new webpack.DefinePlugin({
"process.env": config.dev.env,
IS_DEV: JSON.stringify(true),
}),
打開build/webpack.prod.conf.js文件(項目打包生產環境時使用到的webpack打包配置,運行npm run build,這個文件就會被執行)
添加如下代碼
new webpack.DefinePlugin({
"process.env": config.dev.env,
IS_DEV: JSON.stringify(false),
}),
打開src/main.js文件(項目入口文件,運行項目時被執行)
添加如下代碼
if (IS_DEV) {
console.log("this is dev env");
} else {
console.log("this is prod env");
}
分別在開發環境和生產環境運行程序,查看控制臺。我們發現,在開發環境下,打印了this is dev env。在生產環境下運行打印了this is prod env。
打開打包出來的文件/dist/static/js/app.xxx.js.map,搜索this is prod env。我們發現IS_DEV變成了false。
同理,我們在開發環境下,查看chrome開發者工具,找到相應的app.xxx.js文件。我們發現IS_DEV變成了true。
由此我們可以知道選擇性編譯本質上是字符串的替換,先經過DefinePlugin對代碼中的特定字符串進行替換。再對替換后的代碼進行編譯打包。
需要替換的變量需要分別在webpack.dev.conf.js和webpack.prod.conf.js中指定其轉換后的意義。
為什么在mian.js中使用IS_DEV,程序不會報"IS_DEV is not defined"的錯誤?
因為瀏覽器在運行代碼時,拿到的文件里面IS_DEV已經被替換成了true或者false,已經不存在IS_DEV這個變量。所以不會報錯。
DefinePlugin的使用說明除了替換成簡單的布爾值,還可以替換成字符串,數值,數組,對象等。
如TEST_DATA: JSON.stringify({name:"momo",age:18}),
為什么需要進行JSON.stringify替換?
另外還可以替換成某個段代碼的值(代碼內容直接使用""包裹即可)。
如:TWO: "1+1",TOW將被替換成這段代碼的結果,即2。
ESLint沖突處理ESLint是一個用來識別 ECMAScript 并且按照規則給出報告的代碼檢測工具,使用它可以避免低級錯誤和統一代碼的風格。
配置了eslint的項目在使用選擇性編譯功能時,可能會報出這樣的錯誤。
http://exlint.org/docs/rules/no-undef "IS_DEV" is not defined
正如報錯信息所說的,這是由于eslint檢測代碼時,發現IS_DEV沒有定義(這側面說明了eslint是先于條件編譯執行的。ESLint檢測時,IS_DEV還沒有被替換掉)。解決這個問題有以下三種方法:
簡單粗暴的方法,修改eslint的配置,將error改為warn唄,先打包了再說。具體操作為修改eslintrc.js文件,如果配置文件里面已有第一條語句"eslint":"recommended"(這是引用默認配置)。則往rules里面添加一條規則"no_undef":"warn",以覆蓋掉默認配置。
如果已經存在"no-undef"的配置,則直接改為"warn"就行。
上面的方法影響太大,直接修改了規則。能不能局部修改規則,只在特定語句中忽略掉該規則呢?可以的,使用備注包裹需要忽略的語句就行。
但是上面的方法需要在每個用到的地方都多寫兩條語句,略麻。,有沒有更簡單的,一勞永逸的方法呢?有有有~~ 修改eslintrc.js,將IS_DEV配置成一個全局變量,之后eslint就不會認為IS_DEV是未定義的變量了。
選擇性編輯技術的應用場景API接口的環境替換
賬號信息的模擬,數據模擬
日志打印等
彩蛋 更優的去除log的方法用if邏輯判斷來輸出log可能略顯繁瑣。其實對于控制臺輸出的日志,我們可以通過UglifyJs在打包時來剔除。
具體操作:
打開build/webpack.prod.conf.js文件,添加如下語句
compress: {
warnings: false, // 去除warning警告
drop_debugger: true, // 發布時去除debugger語句
drop_console: true // 發布時去除console語句
},
如果想只去除console.log,同時保留console.error等錯誤提示。可以指定去除特定的函數
compress: {
warnings: false, // 去除warning警告
pure_funcs: ["console.log"], // 配置發布時,不被打包的函數
// drop_debugger: true, // 發布時去除debugger
// drop_console: true // 發布時去除console
}
注意,添加了這個配置以后,console.log在打包出來的文件就不存在了。所以前面測試用的this is dev env也會消失不見
什么叫不可達代碼?就是無論什么情況下都不會被運行的代碼。
例如我們在條件編譯打包出來的代碼中
if (false) {
console.log("this is dev env");
} else {
console.log("this is prod env");
}
```console.log("this is dev env");```就是不可達代碼。
我們同樣可以使用UglifyJs的功能把這部分無用代碼去除掉。讓條件編譯不留痕跡。
具體配置如下:
```
compress: {
warnings: false, // 去除warning警告
dead_code: true, // 去除不可達代碼
}, sourceMap: true
```

UglifyJs的更多功能
UglifyJs還用很多強大的功能,如代碼混淆,壓縮,重拍版等。這里附上UglifyJs官方網址。
英文不好的同學還可以查看對應的中文文檔(其實這才是重點#機智臉)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/89020.html
摘要:使用要給項目構建接入動態鏈接庫的思想,需要完成以下事情把網頁依賴的基礎模塊抽離出來,打包到一個個單獨的動態鏈接庫中去。接入已經內置了對動態鏈接庫的支持,需要通過個內置的插件接入,它們分別是插件用于打包出一個個單獨的動態鏈接庫文件。 webpack優化 查看所有文檔頁面:全棧開發,獲取更多信息。原文鏈接:webpack優化,原文廣告模態框遮擋,閱讀體驗不好,所以整理成本文,方便查找。 ...
摘要:從零開始搭建同構應用三配置這篇文章來講解來配置,我們先從最簡單的方法開始,用的方式模擬實現。影響生產環境下執行效率。最后權衡下,還是決定使用現在多一套編譯配置的方案。新建,寫入以下內容以為例,注意不能少。 從零開始搭建React同構應用(三):配置SSR 這篇文章來講解來配置server side render,我們先從最簡單的方法開始,用cli的方式模擬實現SSR。 demo在這里 ...
摘要:配置完成后就可以使用來打包代碼了。值得注意的是會刪除所有無作用代碼也就是說那些包裹在這些全局變量下的代碼塊都會被刪除這樣就能保證這些代碼不會因發布上線而泄露。默認會從項目的根目錄下引入這些文件。 命令使用 npm install webpack -g 作為全局安裝, 在任意目錄使用 npm install webpack --save-dev 作為項目依賴安裝 np...
摘要:配置以何種方式導出庫。當檢測文件不再發生變化,會先緩存起來,等等待一段時間后之后再通知監聽者,這個等待時間通過配置。發布到線上給用戶使用的運行環境。 一 縮小文件搜索范圍 1 include & exclude 1) action 限制編譯范圍 2) useage module: { rules: [ { test...
摘要:使用教程一,,,使用教程二版本官方的文檔上一篇講到的是被用來轉換某些類型的模塊,它則可以用來做更廣泛的任務。可看作綁定事件,打包時會觸發事件。它的作用是定義全局常量,是常量。為,啟用兩步之間的延遲。請注意,規范建議始終使用引號。 使用教程(一)--- entry,devtool,output,resolve使用教程(二)--- module.loadersWebpack版本 3.10...
閱讀 2729·2021-08-11 11:16
閱讀 3098·2019-08-30 15:55
閱讀 3485·2019-08-30 12:53
閱讀 1805·2019-08-29 13:28
閱讀 3431·2019-08-28 18:17
閱讀 1113·2019-08-26 12:19
閱讀 2595·2019-08-23 18:27
閱讀 871·2019-08-23 18:17