<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        探索webpack模塊及webpack3新特性

        來源:懂視網 責編:小采 時間:2020-11-27 22:29:43
        文檔

        探索webpack模塊及webpack3新特性

        探索webpack模塊及webpack3新特性:本文從簡單的例子入手,從打包文件去分析以下三個問題:webpack打包文件是怎樣的?如何做到兼容各大模塊化方案的?webpack3帶來的新特性又是什么? 一個簡單的例子 webpack配置 // webpack.config.js module.exports = { entry: '.
        推薦度:
        導讀探索webpack模塊及webpack3新特性:本文從簡單的例子入手,從打包文件去分析以下三個問題:webpack打包文件是怎樣的?如何做到兼容各大模塊化方案的?webpack3帶來的新特性又是什么? 一個簡單的例子 webpack配置 // webpack.config.js module.exports = { entry: '.

        本文從簡單的例子入手,從打包文件去分析以下三個問題:webpack打包文件是怎樣的?如何做到兼容各大模塊化方案的?webpack3帶來的新特性又是什么?

        一個簡單的例子

        webpack配置

         // webpack.config.js
        module.exports = {
         entry: './src/index.js',
         output: {
         filename: 'bundle.js',
         path: path.resolve(__dirname, 'dist')
         },
        };

        簡單的js文件

         // src/index.js
         console.log('hello world');

        webpack打包后的代碼

        一看你就會想,我就一行代碼,你給我打包那么多???(黑人問號)

        // dist/bundle.js
         /******/ (function(modules) { // webpackBootstrap
        /******/ // The module cache
        /******/ var installedModules = {};
        /******/
        /******/ // The require function
        /******/ 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);
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, exports) {
        console.log('hello world');
        /***/ })
        /******/ ]);

        我們來分析一下這部分代碼,先精簡一下,其實整體就是一個自執行函數,然后傳入一個模塊數組

         (function(modules) { 
         //...
         })([function(module, exports) {
         //..
         }])

        好了,傳入模塊數組做了什么(其實注釋都很明顯了,我只是大概翻譯一下)

         /******/ (function(modules) { // webpackBootstrap
        /******/ // The module cache 緩存已經load過的模塊
        /******/ var installedModules = {};
        /******/
        /******/ // The require function 引用的函數
        /******/ 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, //模塊id
        /******/ 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 為ES6 exports定義getter
        /******/ __webpack_require__.d = function(exports, name, getter) {
        /******/ if(!__webpack_require__.o(exports, name)) { // 假如exports本身不含有name這個屬性
        /******/ Object.defineProperty(exports, name, {
        /******/ configurable: false,
        /******/ enumerable: true,
        /******/ get: getter
        /******/ });
        /******/ }
        /******/ };
        /******/
        /******/ // getDefaultExport function for compatibility with non-harmony modules 解決ES module和Common js module的沖突,ES則返回module['default']
        /******/ __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配置下的公共路徑
        /******/ __webpack_require__.p = "";
        /******/
        /******/ // Load entry module and return exports 最后執行entry模塊并且返回它的暴露內容
        /******/ return __webpack_require__(__webpack_require__.s = 0);
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, exports) {
        console.log('hello world');
        /***/ })
        /******/ ]);

        整體流程是怎樣的呢

      1. 傳入module數組
      2. 調用__webpack_require__(__webpack_require__.s = 0)
      3. 構造module對象,放入緩存

        調用module,傳入相應參數modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); (這里exports會被函數內部的東西修改)

        標記module對象已經加載完畢

        返回模塊暴露的內容(注意到上面函數傳入了module.exports,可以對引用進行修改)

      4. 模塊函數中傳入module, module.exports, __webpack_require__
      5. 執行過程中通過對上面三者的引用修改,完成變量暴露和引用
      6. webpack模塊機制是怎樣的

        我們可以去官網看下webpack模塊

        doc.webpack-china.org/concepts/mo…

        webpack 模塊能夠以各種方式表達它們的依賴關系,幾個例子如下:

      7. ES2015 import 語句
      8. CommonJS require() 語句
      9. AMD define 和 require 語句
      10. css/sass/less 文件中的 @import 語句。
      11. 樣式(url(...))或 HTML 文件()中的圖片鏈接(image url)
      12. 強大的webpack模塊可以兼容各種模塊化方案,并且無侵入性(non-opinionated)

        我們可以再編寫例子一探究竟

        CommonJS

        修改src/index.js

        var cj = require('./cj.js');
        console.log('hello world');
        cj();

        新增src/cj.js,保持前面例子其他不變

        // src/cj.js
        function a() {
         console.log("CommonJS");
        }
        module.exports = a;

        再次運行webpack

        /******/ (function(modules) { // webpackBootstrap
         //... 省略代碼
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, exports, __webpack_require__) {
        let cj = __webpack_require__(1);
        console.log('hello world');
        cj();
        /***/ }),
        /* 1 */
        /***/ (function(module, exports) {
        function a() {
         console.log("CommonJS");
        }
        module.exports = a;
        /***/ })
        /******/ ]);

        我們可以看到模塊數組多了個引入的文件,然后index.js模塊函數多了個參數__webpack_require__,去引用文件(__webpack_require__在上一節有介紹),整體上就是依賴的模塊修改了module.exports,然后主模塊執行依賴模塊,獲取exports即可

        ES2015 import

        新增src/es.js

        // src/es.js
        export default function b() {
         console.log('ES Modules');
        }

        修改src/index.js

        // src/index.js
        import es from './es.js';
        console.log('hello world');
        es();
        webpack.config.js不變,執行webpack
        /******/ (function(modules) { // webpackBootstrap
        // ... 省略代碼
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
        /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__es_js__ = __webpack_require__(1);
        console.log('hello world');
        Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["a" /* default */])();
        /***/ }),
        /* 1 */
        /***/ (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        /* harmony export (immutable) */ __webpack_exports__["a"] = b;
        function b() {
         console.log('ES Modules');
        }
        /***/ })
        /******/ ]);

        我們可以看到它們都變成了嚴格模式,webpack自動采用的

        表現其實跟CommonJS相似,也是傳入export然后修改,在主模塊再require進來,

        我們可以看到這個

        Object.defineProperty(__webpack_exports__, "__esModule", { value: true });

        這個干嘛用的?其實就是標記當前的exports是es模塊,還記得之前的__webpack_require__.n嗎,我們再拿出來看看

        /******/ // getDefaultExport function for compatibility with non-harmony modules 解決ES module和Common js module的沖突,ES則返回module['default']
        /******/ __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;
        /******/ };

        為了避免跟非ES Modules沖突?沖突在哪里呢?

        其實這部分如果你看到babel轉換ES Modules源碼就知道了,為了兼容模塊,會把ES Modules直接掛在exports.default上,然后加上__esModule屬性,引入的時候判斷一次是否是轉換模塊,是則引入module['default'],不是則引入module

        我們再多引入幾個ES Modules看看效果

        // src/es.js
        export function es() {
         console.log('ES Modules');
        }
        export function esTwo() {
         console.log('ES Modules Two');
        }
        export function esThree() {
         console.log('ES Modules Three');
        }
        export function esFour() {
         console.log('ES Modules Four');
        }

        我們多引入esTwo和esFour,但是不使用esFour

        // src/index.js
        import { es, esTwo, esFour} from './es.js';
        console.log('hello world');
        es();
        esTwo();

        得出

        /******/ (function(modules) { // webpackBootstrap
        // ...
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
        /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__es_js__ = __webpack_require__(1);
        console.log('hello world');
        Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["a" /* es */])();
        Object(__WEBPACK_IMPORTED_MODULE_0__es_js__["b" /* esTwo */])();
        /***/ }),
        /* 1 */
        /***/ (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        /* harmony export (immutable) */ __webpack_exports__["a"] = es;
        /* harmony export (immutable) */ __webpack_exports__["b"] = esTwo;
        /* unused harmony export esThree */
        /* unused harmony export esFour */
        function es() {
         console.log('ES Modules');
        }
        function esTwo() {
         console.log('ES Modules Two');
        }
        function esThree() {
         console.log('ES Modules Three');
        }
        function esFour() {
         console.log('ES Modules Four');
        }
        /***/ })
        /******/ ]);

        嗯嗯其實跟前面是一樣的,舉出這個例子重點在哪里呢,有沒有注意到注釋中

        /* unused harmony export esThree */
        /* unused harmony export esFour */

        esThree是我們沒有引入的模塊,esFour是我們引用但是沒有使用的模塊,webpack均對它們做了unused的標記,其實這個如果你使用了webpack插件uglify,通過標記,就會把esThree和esFour這兩個未使用的代碼消除(其實它就是tree-shaking)

        AMD

        我們再來看看webpack怎么支持AMD

        新增src/amd.js

        // src/amd.js
        define([
        ],function(){
         return {
         amd:function(){
         console.log('AMD');
         }
         };
        });

        修改index.js

        // src/index.js
        define([
         './amd.js'
        ],function(amdModule){
         amdModule.amd();
        });

        得到

        /******/ (function(modules) { // webpackBootstrap
        // ... 省略代碼
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, exports, __webpack_require__) {
        var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
         __webpack_require__(1)
        ], __WEBPACK_AMD_DEFINE_RESULT__ = function(amdModule){
         amdModule.amd();
        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
         __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
        /***/ }),
        /* 1 */
        /***/ (function(module, exports, __webpack_require__) {
        var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
        ], __WEBPACK_AMD_DEFINE_RESULT__ = function(){
         return {
         amd:function(){
         console.log('AMD');
         }
         };
        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
         __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
        /***/ })
        /******/ ]);

        先看amd.js整理一下代碼

        function(module, exports, __webpack_require__) {
         var __WEBPACK_AMD_DEFINE_ARRAY__,
         __WEBPACK_AMD_DEFINE_RESULT__;
         !(
         __WEBPACK_AMD_DEFINE_ARRAY__ = [],
         __WEBPACK_AMD_DEFINE_RESULT__ = function() {
         return {
         amd: function() {
         console.log('AMD');
         }
         };
         }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
         __WEBPACK_AMD_DEFINE_RESULT__ !== undefined &&
         (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)
         );
        })

        簡單來講收集define Array然后置入返回函數,根據參數獲取依賴

        apply對數組拆解成一個一個參數

        再看index.js模塊部分

        function(module, exports, __webpack_require__) {
         var __WEBPACK_AMD_DEFINE_ARRAY__,
         __WEBPACK_AMD_DEFINE_RESULT__;
         !(
         __WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)],
         __WEBPACK_AMD_DEFINE_RESULT__ = function(amdModule) {
         amdModule.amd();
         }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
         __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && 
         (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)
         );
        }

        其實就是引入了amd.js暴露的{amd:[Function: amd]}

        css/image?

        css和image也可以成為webpack的模塊,這是令人震驚的,這就不能通過普通的hack commonjs或者函數調用簡單去調用了,這就是anything to JS,它就需要借助webpack loader去實現了

        像css就是轉換成一段js代碼,通過處理,調用時就是可以用js將這段css插入到style中,image也類似,這部分就不詳細闡述了,有興趣的讀者可以深入去研究

        webpack3新特性

        我們可以再順便看下webpack3新特性的表現

        具體可以看這里medium.com/webpack/web…

        Scope Hoisting

        我們可以發現模塊數組是一個一個獨立的函數然后閉包引用webpack主函數的相應內容,每個模塊都是獨立的,然后帶來的結果是在瀏覽器中執行速度變慢,然后webpack3學習了Closure Compiler和RollupJS這兩個工具,連接所有閉包到一個閉包里,放入一個函數,讓執行速度更快,并且整體代碼體積也會有所縮小

        我們可以實際看一下效果(要注意的是這個特性只支持ES Modules,是不支持CommonJs和AMD的)

        使用上面的例子,配置webpack.config.js,增加new webpack.optimize.ModuleConcatenationPlugin()

        const path = require('path');
        const webpack = require('webpack');
        module.exports = {
         entry: './src/index.js',
         output: {
         filename: 'bundle.js',
         path: path.resolve(__dirname, 'dist')
         },
         module: {
         },
         plugins: [
         new webpack.optimize.ModuleConcatenationPlugin(),
         ]
        };

        打包

        /******/ (function(modules) { // webpackBootstrap
        // ... 省略代碼
        /******/ })
        /************************************************************************/
        /******/ ([
        /* 0 */
        /***/ (function(module, __webpack_exports__, __webpack_require__) {
        "use strict";
        Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
        // CONCATENATED MODULE: ./src/es.js
        function es() {
         console.log('ES Modules');
        }
        function esTwo() {
         console.log('ES Modules Two');
        }
        function esThree() {
         console.log('ES Modules Three');
        }
        function esFour() {
         console.log('ES Modules Four');
        }
        // CONCATENATED MODULE: ./src/index.js
        // src/index.js
        console.log('hello world');
        es();
        /***/ })
        /******/ ]);

        我們可以驚喜的發現沒有什么require了,它們拼接成了一個函數,good!😃

        Magic Comments

        code splitting是webpack一個重點特性之一,涉及到要動態引入的時候,webpack可以使用 require.ensure去實現,后來webpack2支持使用了符合 ECMAScript 提案 的 import() 語法,但是它有個不足之處,無法指定chunk的名稱chunkName,為了解決這個問題,出現了Magic Comments,支持用注釋的方式去指定,如下

        import(/* webpackChunkName: "my-chunk-name" */ 'module');

        小結

        webpack是一個強大的模塊打包工具,在處理依賴、模塊上都很優秀,本文從bundle.js文件分析出發去探索了不同模塊方案的加載機制,初步去理解webpack,并且對webpack3特性進行闡述,當然,webpack還有很多地方需要去探索深究,敬請期待以后的文章吧~關于本文如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        探索webpack模塊及webpack3新特性

        探索webpack模塊及webpack3新特性:本文從簡單的例子入手,從打包文件去分析以下三個問題:webpack打包文件是怎樣的?如何做到兼容各大模塊化方案的?webpack3帶來的新特性又是什么? 一個簡單的例子 webpack配置 // webpack.config.js module.exports = { entry: '.
        推薦度:
        標簽: 模塊 新特性 探索
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲狠狠婷婷综合久久久久| 亚洲国产一区二区视频网站| 噜噜噜亚洲色成人网站∨| 免费精品一区二区三区第35| 久久久久国产成人精品亚洲午夜 | 精品国产日韩亚洲一区| 一级做a免费视频观看网站| 久久亚洲国产精品123区| 成人免费ā片在线观看| 国产av天堂亚洲国产av天堂| 99久久精品免费精品国产| 91亚洲国产成人精品下载| 久草在视频免费福利| 亚洲色大成网站www永久网站| 国产极品粉嫩泬免费观看| 春暖花开亚洲性无区一区二区| 亚洲第一区在线观看| 成人久久久观看免费毛片| 亚洲深深色噜噜狠狠爱网站| 无码国产精品一区二区免费vr| 亚洲经典在线观看| 成年丰满熟妇午夜免费视频| 国产亚洲精品91| 亚洲AV无码成人网站久久精品大 | 高清免费久久午夜精品| 国产∨亚洲V天堂无码久久久| 9277手机在线视频观看免费| 亚洲中文无码亚洲人成影院| 亚洲AV无码乱码在线观看牲色| 免费精品久久天干天干| 亚洲国产精品成人综合色在线婷婷| 嫩草影院免费观看| 国产一级在线免费观看| 91亚洲国产成人久久精品| 日日AV拍夜夜添久久免费| 很黄很污的网站免费| 亚洲色精品VR一区区三区| 在线观看亚洲精品国产| 又黄又爽又成人免费视频| 污污污视频在线免费观看| 亚洲码在线中文在线观看|