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