成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

解析 Webpack中import、require、按需加載的執(zhí)行過程

caozhijian / 2488人閱讀

摘要:但是瀏覽器是不識別這個關(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.js
webpack 中 require 和 import 的執(zhí)行過程

在進入按需加載的講解之前,我們需要看一個問題 requireimportwebpack 的執(zhí)行過程是怎樣的呢 ?現(xiàn)在我們在 src建立兩個文件 index.js、module-es6.jsmodule-commonjs.js。我們通過這三個文件解析 requireimport 的執(zhí)行過程

首先我們要區(qū)分的是 CommonJSES6 模塊導(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)生兩個變量 AB. 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í)行過程

看完上面的 requireimport,我們回到 按需加載 這個執(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,rejectpromise本身 存入一個數(shù)組,然后緩存起來.接著生成一個 script 標簽,填充完信息之后添加到HTML文件上,其中的 scriptsrc屬性 就是我們按需加載的文件(module2),webpack 會對這個 script 標簽監(jiān)聽 errorload時間,從而做相應(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)建的promiseresolve函數(shù),讓require.ensure里面的callback執(zhí)行,之后的執(zhí)行情況就跟我上面將 requirimport 一樣了

當(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

相關(guān)文章

  • 9102年:手寫一個React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統(tǒng)擴展性很好。 webpack馬上要出5了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...

    Kylin_Mountain 評論0 收藏0
  • 9102年:手寫一個React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統(tǒng)擴展性很好。 webpack馬上要出5了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...

    whatsns 評論0 收藏0
  • 9102年:手寫一個React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。每個依賴項隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細討論這個過程。的事件流機制保證了插件的有序性,使得整個系統(tǒng)擴展性很好。 webpack馬上要出5了,完全手寫一個優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗過可...

    bingo 評論0 收藏0
  • 淺談webpack4.0 性能優(yōu)化

    摘要:中在性能優(yōu)化所做的努力,也大抵圍繞著這兩個大方向展開。因此,將依賴模塊從業(yè)務(wù)代碼中分離是性能優(yōu)化重要的一環(huán)。大型庫是否可以通過定制功能的方式減少體積。這又違背了性能優(yōu)化的基礎(chǔ)。接下來可以抓住一些細節(jié)做更細的優(yōu)化。中,為默認啟動這一優(yōu)化。 前言:在現(xiàn)實項目中,我們可能很少需要從頭開始去配置一個webpack 項目,特別是webpack4.0發(fā)布以后,零配置啟動一個項目成為一種標配。正因為...

    leanxi 評論0 收藏0
  • 【Vue項目總結(jié)】webpack常規(guī)打包優(yōu)化方案

    摘要:由于新建項目發(fā)版打包時間大概需要分鐘,發(fā)版時嚴重拖慢下班時間,所以特意查看了相關(guān)文檔來優(yōu)化打包速度,爭取早點下班,。分析打包文件要優(yōu)化,先分析。 由于新建項目發(fā)版打包時間大概需要30分鐘,發(fā)版時嚴重拖慢下班時間,所以特意查看了相關(guān)文檔來優(yōu)化打包速度,爭取早點下班,^_^。 分析打包文件 要優(yōu)化,先分析。我們先要知道到底是哪里拖慢我們的打包速度呢? 打包后生成文件分析 可以利用webpa...

    andong777 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<