摘要:但是瀏覽器是不識別這個關鍵詞的所以會對的代碼進行解釋首先給設定導出的值如果是會直接賦值給如果是其他形式則給的導出的設定一個該的返回值就是導出的結果而對于來說整個執行過程其實過程和是一樣的。
最近由于一篇分享手淘過年項目中采用到的前端技術的影響,重新研究了一下項目中CSS的架構.本來打算寫一篇文章,但是寫到一半突然發現自己像在寫文檔介紹一樣,所以后來就放棄了。但是覺得過程中研究的 Webpack 倒是可以多帶帶拿出來講一講
在這里非常感謝印記中文 團隊翻譯的 Webpack 文檔.搭建一個簡單環境
npm init
npm install css-loader html-webpack-plugin style-loader webpack webpack-cli
// Webpack 4.0 const htmlPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", entry: "./src/index.js", output: { filename: "[name].js", path: __dirname + "/dist" }, module: { rules: [ { test: /.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", }, ] } ] }, plugins: [ new htmlPlugin({ title: "Test Webpack", filename: "index.html" }) ] };
一個基本的配置就搭建好了,詳細的配置內容我就不介紹了, 然后我們在 src/index.js 上面寫我們的測試代碼, 在 dist/main.js 看一下 webpack 實現的原理,那么目前我們的項目結構是這樣子的
|-- project |-- dist |-- src |-- index.js |-- node_modules |-- webpack.config.jswebpack 中 require 和 import 的執行過程
在進入按需加載的講解之前,我們需要看一個問題 require 和 import在 webpack 的執行過程是怎樣的呢 ?現在我們在 src建立兩個文件 index.js、module-es6.js 和 module-commonjs.js。我們通過這三個文件解析 require 和 import 的執行過程
首先我們要區分的是 CommonJS 和 ES6 模塊導出之間的區別,在 CommonJS 中你導出模塊方式是改變 module.exports,但是對于 ES6 來說并不存在 module 這個變量,他的導出方式是通過一個關鍵詞 export來實現的。在我們書寫 JS文件的時候,我們發現無論是以 CommomJS 還是 ES6 的形式導出都可以實現,這是因為 Webpack做了一個兼容處理
我們建立一個小 DEMO 來查看一下,我們現在上面建立的三個文件的代碼如下
// index.js // import moduleDefault, { moduleValue } from "./module-es6.js"; // import moduleDefault, { moduleValue1, moduleValue2 } from "./module-commanjs.js";
// module-es6.js export let moduleValue = "moduleValue" //ES6模塊導出 export default "ModuleDefaultValue"
// module-commonjs.js exports.moduleValue1 = "moduleValue1" exports.moduleValue2 = "moduleValue2"
現在我們打開 index.js 中加載 module-commonjs.js 的代碼,首先會先給當前模塊打上 ES6模塊的標識符,在 index 則會產生兩個變量 A 和 B. A 保存 module-commonjs 的導出的結果,B 則是兼容 CommonJs中沒有 ES6通過 export default導出的結果,其值跟 A一樣. 用B來兼容 export default 的結果
然后我們重新注釋代碼,再打開 index.js 中加載 module-es6.js 的代碼
這次和上面一樣會先給當前模塊打上 ES6模塊的標識符,然后去加載 module-es6,獲取他的導出值。但是瀏覽器是不識別 export 這個關鍵詞的所以 Webpack 會對的代碼進行解釋,首先給 module.exports 設定導出的值,如果是 export default 會直接賦值給 module.exports,如果是其他形式,則給module.exports的導出的key設定一個 getter,該 getter 的返回值就是導出的結果
而對于require來說整個執行過程其實過程和import是一樣的。
對于 webpack 來說只要你使用了 import 或者 export等關鍵字, 他就會給 module.exports添加一個__esModule : true 來識別這是一個 ES6的模塊,通過這個值來做一些特殊處理
如果覺得我上面講的不太明白 那可以看看下面這些代碼
let commonjs = { "./src/index.js": function(module, __webpack_exports__, __webpack_require__) { "use strict"; //給當前模塊打上 `ES6`模塊的標識符 __webpack_require__.r(__webpack_exports__); //給當前模塊打上 `ES6`模塊的標識符 // 執行 ./src/module-commonjs.js 的代碼 獲取導出值 var A = __webpack_require__("./src/module-commonjs.js"); // 根據 ./src/module-commonjs.js 是否為ES6模塊 給返回值增加不同的 getter函數 var B = __webpack_require__.n(A); }, "./src/module-commonjs.js": function(module, exports) { exports.moduleValue1 = "moduleValue1"; exports.moduleValue2 = "moduleValue2"; } }; let es6 = { "./src/index.js": function(module, __webpack_exports__, __webpack_require__) { "use strict"; //給當前模塊打上 `ES6`模塊的標識符 __webpack_require__.r(__webpack_exports__); // 執行 ./src/module-commonjs.js 的代碼 獲取導出值 var A = __webpack_require__("./src/module-es6.js"); }, "./src/module-es6.js": function(module, __webpack_exports__, __webpack_require__) { //給當前模塊打上 `ES6`模塊的標識符 __webpack_require__.r(__webpack_exports__); // 設置 __webpack_exports__.moduleValue 的 getter __webpack_require__.d(__webpack_exports__, "moduleValue", function() { return moduleValue;z }); __webpack_exports__["default"] = "ModuleDefaultValue"; let moduleValue = "moduleValue"; } };按需加載的執行過程
看完上面的 require 和 import,我們回到 按需加載 這個執行過程. webpack 的按需加載是通過 import() 或者 require.ensure()來實現的,有些讀者可能對于 require.ensure 比較熟悉,所以我們先看看 require.ensure 的執行過程,
現在我們修改建立一個 module-dynamic.js文件,然后修改 index.js文件
這里吐槽一個問題,require.ensure 第一個參數是一個尷尬的存在,寫和不寫根本沒差,如果你填了的這個參數,webpack 會幫你把文件加載近來,但是不執行。一堆不執行的代碼是沒有意義的,你想讓他執行就必須 require() 一遍,但是執行力 require 也會幫你加載文件。所以根本沒差
// index.js setTimeout(function() { require.ensure([], function() { let d = require("./module2") }); }, 1000); // module2.js module.exports = { name : "Jason" }
執行 require.ensure(dependencies,callback,errorCallback,chunkName) 實際上會返回一個 promise , 里面的實現邏輯是 先判斷 dependencies 是否已經被加載過,如果加載過則取緩存值的 promise, 如果沒有被加載過 則生成一個 promise 并將 promise 里面的 resolve,reject 和 promise本身 存入一個數組,然后緩存起來.接著生成一個 script 標簽,填充完信息之后添加到HTML文件上,其中的 script 的 src屬性 就是我們按需加載的文件(module2),webpack 會對這個 script 標簽監聽 error 和 load時間,從而做相應的處理。
webpack打包過程中會給 module2 添加一些代碼,主要就是主動觸發 window["webpackJsonp"].push這個函數,這個函數會傳遞
兩個參數 文件ID 和 文件內容對象,其中 文件標示如果沒有配置的話,會按載入序號自動增長,文件內容對象實際上就是上文說的 require.ensure第一個參數dependencies的文件內容,或者是 callback,errorCallback里面需要加載的文件,以 key(文件路徑) --- value(文件內容)的形式出現.里面執行的事情其實就是執行上面創建的promise的resolve函數,讓require.ensure里面的callback執行,之后的執行情況就跟我上面將 requir 和 import 一樣了
當然其實講了那么長的 require.ensure并沒有什么用,因為這個函數已經被 import() 取代了,但是考慮到之前的版本應該有很多人都是用 require.ensure 方法去加載的,所以還是講一下,而且其實 import 的執行過程跟 require.ensure 是一樣的,只不過用了更友好的語法而已,所以關于 import 的執行流程我也沒啥好講的了,感興趣的人看一下兩者的 API介紹就好了。
到這里就正式講完了,如果有大牛路過看到有不對的地方,希望能幫我指出來.非常謝謝!!!
然后再次感謝印記中文 團隊翻譯的 Webpack 文檔
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93287.html
摘要:馬上要出了,完全手寫一個優化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統擴展性很好。 webpack馬上要出5了,完全手寫一個優化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...
摘要:馬上要出了,完全手寫一個優化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統擴展性很好。 webpack馬上要出5了,完全手寫一個優化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...
摘要:馬上要出了,完全手寫一個優化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統擴展性很好。 webpack馬上要出5了,完全手寫一個優化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...
摘要:中在性能優化所做的努力,也大抵圍繞著這兩個大方向展開。因此,將依賴模塊從業務代碼中分離是性能優化重要的一環。大型庫是否可以通過定制功能的方式減少體積。這又違背了性能優化的基礎。接下來可以抓住一些細節做更細的優化。中,為默認啟動這一優化。 前言:在現實項目中,我們可能很少需要從頭開始去配置一個webpack 項目,特別是webpack4.0發布以后,零配置啟動一個項目成為一種標配。正因為...
摘要:由于新建項目發版打包時間大概需要分鐘,發版時嚴重拖慢下班時間,所以特意查看了相關文檔來優化打包速度,爭取早點下班,。分析打包文件要優化,先分析。 由于新建項目發版打包時間大概需要30分鐘,發版時嚴重拖慢下班時間,所以特意查看了相關文檔來優化打包速度,爭取早點下班,^_^。 分析打包文件 要優化,先分析。我們先要知道到底是哪里拖慢我們的打包速度呢? 打包后生成文件分析 可以利用webpa...
閱讀 3008·2021-10-13 09:39
閱讀 2705·2021-09-27 13:34
閱讀 2044·2019-08-30 15:55
閱讀 3269·2019-08-30 15:43
閱讀 3649·2019-08-30 11:16
閱讀 1767·2019-08-26 18:28
閱讀 1302·2019-08-26 13:56
閱讀 927·2019-08-26 13:35