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