This is the 16th day of my participation in the August Text Challenge.More challenges in August

preface

Webpack is the front-end modular packaging tool, we use vue2 or React official scaffolding generated projects, there are webpack shadow.

However, these scaffolds provide packaging commands, and we just need to run the packaging commands to package, generally not care about the content of the packaging.

Today, I would like to take this opportunity to take a look at the wepback packaged source code is how, analysis.

packaging

  1. Install webapck

    yarn add webpack webpack-cli -D // You can also use NPM here
    Copy the code

    I installed version is “webpack”, “^ 5.42.1”, “webpack – cli” : “^ 4.7.2”.

  2. Write webpack.config.js, webpack configuration file

    webpack.config.js

      const path = require('path')
      module.exports = {
        entry: ['./export/index.mjs']./ / the entry
        output: {
          path: path.resolve(__dirname, 'dist'), // Output directory
          filename: 'bundle.js'  // Output the file name}}Copy the code

    Index.mjs, which introduces only a simple module, is the simplest code

     import { name } from './test.mjs'
     console.log(name)
    Copy the code

    test.mjs

       var name = 'the answer cp3'
       export { name }
    Copy the code
  3. Then run webpack –mode development on the terminal (based on wepback global installation), if not globally add the scripts field to package.json, write this command, execute it through YARN or NPM. Here I write development, so that the packaged code is not compressed and easy to read.

    Packaged successfully, let’s look at the packaged code (with some comments removed)

     (() = > {
       "use strict";
       var __webpack_modules__ = ({
    
         "./export/index.mjs": ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) = > {
           eval("__webpack_require__.r(__webpack_exports__); \n/* harmony import */ var _test_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./test.mjs */ \"./export/test.mjs\"); \n\r\nconsole.log(_test_mjs__WEBPACK_IMPORTED_MODULE_0__.name)\r\n\n\n//# sourceURL=webpack://test/./export/index.mjs?");
         }),
    
         "./export/test.mjs": ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) = > {
    
           eval("__webpack_require__.r(__webpack_exports__); \n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"name\": () => (/* binding */ name)\n/* harmony export */ }); \ nvar name = 'answers cp3 \ r \ n \ r \ n \ n \ n # sourceURL = webpack: / / / / test /. / export/test. The MJS?"); })});// The module cache
       var __webpack_module_cache__ = {};
    
       // The require function
       function __webpack_require__ (moduleId) {
         // Check if module is in cache
         var cachedModule = __webpack_module_cache__[moduleId];
         if(cachedModule ! = =undefined) {
           return cachedModule.exports;
         }
         // Create a new module (and put it into the cache)
         var module = __webpack_module_cache__[moduleId] = {
           // no module.id needed
           // no module.loaded needed
           exports: {}};// Execute the module function
         __webpack_modules__[moduleId](module.module.exports, __webpack_require__);
    
         // Return the exports of the module
         return module.exports;
       }
    
       / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
       /* webpack/runtime/define property getters */
       (() = > {
         // define getter functions for harmony exports
         __webpack_require__.d = (exports, definition) = > {
           for (var key in definition) {
             if(__webpack_require__.o(definition, key) && ! __webpack_require__.o(exports, key)) {
               Object.defineProperty(exports, key, { enumerable: true.get: definition[key] }); }}}; }) ();/* webpack/runtime/hasOwnProperty shorthand */
       (() = > {
         __webpack_require__.o = (obj, prop) = > (Object.prototype.hasOwnProperty.call(obj, prop))
       })();
    
       /* webpack/runtime/make namespace object */
       (() = > {
         // define __esModule on exports
         __webpack_require__.r = (exports) = > {
           if (typeof Symbol! = ='undefined' && Symbol.toStringTag) {
             Object.defineProperty(exports.Symbol.toStringTag, { value: 'Module' });
           }
           Object.defineProperty(exports.'__esModule', { value: true}); }; }) ();/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
    
       // startup
       // Load entry module and return exports
       // This entry module can't be inlined because the eval devtool is used.
       var __webpack_exports__ = __webpack_require__("./export/index.mjs"); }) ();Copy the code

    This packaged code can run directly on the browser console, but it needs to run under the HTTPS protocol because of browser restrictions on eval.

The analysis process

Let’s parse the packaged code:

  1. All code is wrapped in immediate execution of anonymous functions in strict mode (es6 modules package in strict mode by default)

  2. Define an __webpack_modules__ object, where key is the path to each module and value is an arrow function that wraps the code for each module. In WebPack mode, the module code is executed using the eval function.

  3. Define the __webpack_module_cache__ object, which is used to cache code after each module executes, with key being the path of each module.

  4. Define the __webpack_require__ function, which is the equivalent of the module execution function. Create a new object and assign it to __webpack_module_cache__. Key is the path of the module that was passed in. Then go to the __webpack_modules__ object declared in step 2 and find the corresponding module code. Defines exported values to this object. It is read-only and cannot be written. The value of the new object is also synchronized to __webpack_module_cache__.

  5. If __webpack_require__ is repeatedly called, the corresponding cache value can be found through the __webpack_module_cache__ cache object based on the path passed in and returned.

  6. Several methods are defined on the __webpack_require__ function

    • D method

      The attributes on the export module are defined internally using the defineProperty method

    • O method

      Use hasOwnProperty to determine if it is a property of its own

    • R method

      Assign an __esModule attribute to each object of the exported module

  7. Execute the __webpack_require__ function, which takes the entry module of the webpack.config.js configuration.

conclusion

Above is the source code analysis of webPack ES6 module, this is a relatively simple module dependency, but the general idea should be like this, if you do not understand the place, follow the steps to package, and then the packaged code in the console, plus breakpoint print results.

Thank you for reading.