摘要:的編譯構(gòu)建上一篇文章詳解中介紹了基于事件流編程,是個(gè)高度的插件集合,整體介紹了的編譯流程。本文將多帶帶聊一聊最核心的部分,編譯構(gòu)建。的編譯重要的構(gòu)建節(jié)點(diǎn)的構(gòu)建中總會(huì)經(jīng)歷如下幾個(gè)事件節(jié)點(diǎn)。
webpack的編譯&構(gòu)建
上一篇文章webpack詳解中介紹了webpack基于事件流編程,是個(gè)高度的插件集合,整體介紹了webpack 的編譯流程。本文將多帶帶聊一聊最核心的部分,編譯&構(gòu)建。
webpack的編譯 重要的構(gòu)建節(jié)點(diǎn)webpack的構(gòu)建中總會(huì)經(jīng)歷如下幾個(gè)事件節(jié)點(diǎn)。
before-run 清除緩存
run 注冊(cè)緩存數(shù)據(jù)鉤子
compile 開始編譯
make 從入口分析依賴以及間接依賴模塊,創(chuàng)建模塊對(duì)象
build-module 模塊構(gòu)建
seal 構(gòu)建結(jié)果封裝, 不可再更改
after-compile 完成構(gòu)建,緩存數(shù)據(jù)
emit 輸出到dist目錄
其中make是整個(gè)構(gòu)建中最核心的部分編譯,通過模塊工廠函數(shù)創(chuàng)建模塊,然后對(duì)模塊進(jìn)行編譯。
在make鉤子的編譯
上圖中提到的*ModuleFactory是指模塊工廠函數(shù),之所以會(huì)有模塊工廠這樣的函數(shù),還要從webpack中entry的配置說起,在webpack的配置項(xiàng)中entry支持如下類型:
字符類型string
字符數(shù)組類型[string]
多頁面對(duì)象key-value類型object {
也支持一個(gè)函數(shù),返回構(gòu)建的入口(function: () => string | [string] | object {
為了處理以后不同類型的入口模塊,所以就需要個(gè)模塊工廠來處理不同的入口模塊類型。
singleEntry: string|object {
multiEntry: [string]|object {
dynamicEntry: (function: () => string | [string] | object {
上圖中為了簡(jiǎn)單說明構(gòu)建的流程,就以最直接的singleEntry類型說起,對(duì)于此類入口模塊,webpack均使用NormalModuleFactory來創(chuàng)建模塊,這個(gè)創(chuàng)建的模塊的類型叫NormalModule,在NormalModule中實(shí)現(xiàn)了模塊的構(gòu)建方法build,使用runLoaders對(duì)模塊進(jìn)行加載,然后利用進(jìn)行解析,分析模塊依賴,遞歸構(gòu)建。
構(gòu)建封裝seal到構(gòu)建封裝階段時(shí)候,代碼構(gòu)建已經(jīng)完畢,但是如何將這些代碼按照依賴引用邏輯組織起來,當(dāng)瀏覽器將你構(gòu)建出來的代碼加載到瀏覽器的時(shí)候,仍然能夠正確執(zhí)行。在webpack中通過Manifest記錄各個(gè)模塊的詳細(xì)要點(diǎn),通過Runtime來引導(dǎo),加載執(zhí)行模塊代碼,特別是異步加載。
Runtime如上所述,我們這里只簡(jiǎn)略地介紹一下。runtime,以及伴隨的 manifest 數(shù)據(jù),主要是指:在瀏覽器運(yùn)行時(shí),webpack 用來連接模塊化的應(yīng)用程序的所有代碼。runtime 包含:在模塊交互時(shí),連接模塊所需的加載和解析邏輯。包括瀏覽器中的已加載模塊的連接,以及懶加載模塊的執(zhí)行邏輯。
Manifest那么,一旦你的應(yīng)用程序中,形如 index.html 文件、一些 bundle 和各種資源加載到瀏覽器中,會(huì)發(fā)生什么?你精心安排的 /src 目錄的文件結(jié)構(gòu)現(xiàn)在已經(jīng)不存在,所以 webpack 如何管理所有模塊之間的交互呢?這就是 manifest 數(shù)據(jù)用途的由來……
當(dāng)編譯器(compiler)開始執(zhí)行、解析和映射應(yīng)用程序時(shí),它會(huì)保留所有模塊的詳細(xì)要點(diǎn)。這個(gè)數(shù)據(jù)集合稱為 "Manifest",當(dāng)完成打包并發(fā)送到瀏覽器時(shí),會(huì)在運(yùn)行時(shí)通過 Manifest 來解析和加載模塊。無論你選擇哪種模塊語法,那些 import 或 require 語句現(xiàn)在都已經(jīng)轉(zhuǎn)換為 webpack_require 方法,此方法指向模塊標(biāo)識(shí)符(module identifier)。通過使用 manifest 中的數(shù)據(jù),runtime 將能夠查詢模塊標(biāo)識(shí)符,檢索出背后對(duì)應(yīng)的模塊。
定義了一個(gè)立即執(zhí)行函數(shù),聲明了__webpack_require__,對(duì)各種模塊進(jìn)行加載。
(function(modules) { // webpackBootstrap var installedModules = {}; // cache module function __webpack_require__(moduleId) { // 模塊加載 // Check if module is in cache if (installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} }; // Execute the module function modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // Flag the module as loaded module.l = true; // Return the exports of the module return module.exports; } // expose the modules object (__webpack_modules__) __webpack_require__.m = modules; // expose the module cache __webpack_require__.c = installedModules; // define getter function for harmony exports __webpack_require__.d = function(exports, name, getter) { if (!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { configurable: false, enumerable: true, get: getter }); } }; // getDefaultExport function for compatibility with non-harmony modules __webpack_require__.n = function(module) { var getter = module && module.__esModule ? function getDefault() { return module["default"]; } : function getModuleExports() { return module; }; __webpack_require__.d(getter, "a", getter); return getter; }; // Object.prototype.hasOwnProperty.call __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; // __webpack_public_path__ __webpack_require__.p = ""; // Load entry module and return exports return __webpack_require__(__webpack_require__.s = 0); })([/**modules*/])
上面提到的代碼片段便是webpack構(gòu)建后在瀏覽器中執(zhí)行的引導(dǎo)代碼。也就是上面提到的runtime。它是個(gè)立即執(zhí)行函數(shù),那么入?yún)?b>modules便是上面的Manifest,組織各個(gè)模塊的依賴邏輯。
(function(modules){ // ... // runtime function __webpack_require__(moduleId) { // 加載邏輯 } // ... })([function (module, exports, __webpack_require__) { var chunk1 = __webpack_require__(1); var chunk2 = __webpack_require__(2); }, function (module, exports, __webpack_require__) { __webpack_require__(2); var chunk1 = 1; exports.chunk1 = chunk1; }, function (module, exports) { var chunk2 = 1; exports.chunk2 = chunk2; }])
上面說到了runtime和manifest就是在seal階段注入的
class Compilation extends Tapable { seal(callback) { this.hooks.seal.call(); // ... if (this.hooks.shouldGenerateChunkAssets.call() !== false) { this.hooks.beforeChunkAssets.call(); this.createChunkAssets(); } // ... } createChunkAssets() { // ... for (let i = 0; i < this.chunks.length; i++) { const chunk = this.chunks[i]; // ... const template = chunk.hasRuntime() ? this.mainTemplate : this.chunkTemplate; // 根據(jù)是否有runTime選擇模塊,入口文件是true, 需要異步加載的文件則沒有 const manifest = template.getRenderManifest({ // 生成manifest chunk, hash: this.hash, fullHash: this.fullHash, outputOptions, moduleTemplates: this.moduleTemplates, dependencyTemplates: this.dependencyTemplates }); // [{ render(), filenameTemplate, pathOptions, identifier, hash }] // ... } }
通過template最后將代碼組織起來,上面看到的構(gòu)建后的代碼就是mainTemplate生成的。
寫在最后通過template生成最后代碼,構(gòu)建已經(jīng)完成,接下來就是將代碼輸出到dist 目錄。
最后騰訊IVWEB團(tuán)隊(duì)的工程化解決方案feflow已經(jīng)開源:Github主頁:https://github.com/feflow/feflow
如果對(duì)您的團(tuán)隊(duì)或者項(xiàng)目有幫助,請(qǐng)給個(gè)Star支持一下哈~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/93927.html
摘要:那時(shí)候所配置的任務(wù)監(jiān)聽匹配文件的變化自動(dòng)刷新瀏覽器自動(dòng)編譯自動(dòng)補(bǔ)全前綴多雪碧圖合并拼圖等等基于編譯圖片的任務(wù),已經(jīng)是完全滿足我們的需求了。直至到后來在雪碧圖的合并,多倍圖的輸出上,在上苦苦找尋不了比較完美的解決方案等等。 折騰 從 2015 到現(xiàn)在,短短的三年內(nèi),幾乎每年折騰一下工作流的 更新?lián)Q代 。從最早開始使用 Grunt 到 Gulp 再到 Webpack,再到 Rollup,...
摘要:原理踩坑起因最近在做框架的熱更新,記錄一下的原理和小坑。文件系統(tǒng)接收更改并通知。運(yùn)行時(shí)通過請(qǐng)求這些更新。類似的問題還有很多,事件綁定手動(dòng)插入并且沒有銷毀的定時(shí)器等,記得把這些副作用一起干掉。參考官方文檔原理分析與實(shí)現(xiàn) webpack hot-module-replacement 原理&踩坑 起因 最近在做san框架的熱更新,記錄一下webpack HMR的原理和小坑。 什么是HMR? ...
摘要:在年成為最大贏家,贏得了實(shí)現(xiàn)的風(fēng)暴之戰(zhàn)。和他的競(jìng)爭(zhēng)者位列第二沒有前端開發(fā)者可以忽視和它的生態(tài)系統(tǒng)。他的殺手級(jí)特性是探測(cè)功能,通過檢查任何用戶的功能,以直觀的方式讓開發(fā)人員檢查所有端點(diǎn)。 2016 JavaScript 后起之秀 本文轉(zhuǎn)載自:眾成翻譯譯者:zxhycxq鏈接:http://www.zcfy.cc/article/2410原文:https://risingstars2016...
摘要:徹底分離源文件目錄和生成文件目錄使用生成出來的頁面可以很安心地跟打包好的其它資源放到一起,相對(duì)于另起一個(gè)目錄專門存放頁面文件來說,整個(gè)文件目錄結(jié)構(gòu)更加合理如何利用生成頁面生成頁面主要是通過來實(shí)現(xiàn)的,下面來介紹如何實(shí)現(xiàn)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000712...
摘要:本質(zhì)上是一個(gè)可以模塊化使用的加載處理的函數(shù)。本文著重討論以作為樣本分析。下面一幅圖分別是單和雙編譯結(jié)果圖。總結(jié)通過簡(jiǎn)單的例子復(fù)習(xí)了編譯后的文件執(zhí)行流程探索了編譯流程研究意義還是有的。相關(guān)問題參考鏈接參考鏈接 引言 在回答一個(gè)問題時(shí),引發(fā)一些疑問,分析總結(jié)下,作為備忘 webpack webpack對(duì)于我來說,應(yīng)用場(chǎng)景主要是,編譯打包我通過模塊化組織書寫的文件,用其提供的各種loader...
閱讀 1058·2019-08-30 12:57
閱讀 2141·2019-08-30 11:11
閱讀 2183·2019-08-29 15:20
閱讀 1877·2019-08-29 14:12
閱讀 3280·2019-08-28 17:51
閱讀 2383·2019-08-26 13:23
閱讀 804·2019-08-26 10:34
閱讀 3865·2019-08-23 12:37