Webpack 原理与实践之如何使用 Webpack 实现模块化打包?

webpack还具备代码拆分的能力,能够将应用中所有的模块按需分块打包,不用担心全部代码打包到一起,
首页 新闻资讯 行业资讯 Webpack 原理与实践之如何使用 Webpack 实现模块化打包?

本文转载自微信公众号「前端万有引力」,作者一川。转载本文请联系前端万有引力公众号。

写在前面

我们知道当前生产中主流的模块化打包工具有Webpack、Parcel和Rollup。作为模块化打包工具,它们基本的特点有:

  • 能够将散落的模块打包在一起

  • 能够编译转换代码中的新特性,使得可以兼容各种生产环境

对于主流的webpack而言,webpack作为一个模块打包工具,自身就可以实现模块化代码打包的问题,通过webpack可以将零散的JS代码打包到一个JS文件中。对于有环境兼容性问题的代码,webpack可以在代码打包过程中通过loader机制对其实现编译转换,然后再进行打包。对于不同类型的前端模块,webpack支持在js中以模块化的方式载入任意类型的资源文件,例如:可以通过webpack实现在JS中加载CSS文件,被加载的CSS文件会以style标签的方式工具。

webpack还具备代码拆分的能力,能够将应用中所有的模块按需分块打包,不用担心全部代码打包到一起,产生单个文件过大,导致加载慢的问题。这种模块按需分块打包非常适合大型web项目。

Webpack上路

Webpack作为主流的前端模块打包器,提供了一整套前端项目模块化方案,而不仅仅局限于JS的模块化,可以实现对前端项目开发过程中涉及到的资源进行模块化。

我们知道ES  Modules中制定的html中使用script导入js模块,需要设定type="module",用来区分加载的是普通JS脚本还是一个模块。对于支持ES  Modules的浏览器可以直接使用,但是对于不支持的浏览器就会报错,因此需要使用webpack模块打包工具避免报错。

复制

<script src="./index.js" type="module"></script>
  • 1.

复制

// heading.js export default function(){   const element = document.createElement("div");   element.textContent = "hello yichuan";   element.addEventListener("click",()=>{     console.log("hello onechuan");     return element   }) }  // index.js import createHeader  from "./heading.js"; document.body.append(createHeader())
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

对于,我们需要先安装webpack的核心模块和cli程序,用于在命令行中调用webpack。npx是npm5.2以后新增的一个命令,可以更方便地执行远程模块或者项目node_modules中的cli程序。

复制

$ npm init --yes $ npm i webpack webpack-cli -D $ npx webpack --version $ npx webpack
  • 1.

  • 2.

  • 3.

  • 4.

通过执行npx  webpack实现自动化打包,webpack会默认从src/index.js文件开始打包,打包完毕后会在根目录下生产dist目录,所有打包文件会在dist目录。

复制

|--dist   |--main.js
  • 1.

  • 2.

复制

(()=>{"use strict";document.body.append(function(){const e=document.createElement("div");e.textContent="hello yichuan",e.addEventListener("click",(()=>(console.log("hello onechuan"),e)))}())})();
  • 1.

webpack4.0以后的版本支持零配置的方式直接启动打包,整个过程会按照约定将src/index.js文件作为打包入口,最终打包的结果会存放到dis/main.js中。但是,很多时候webpack的默认规则并能满足我们实际需求,对此我们需要对webpack进行自定义配置。

webpack支持在项目中创建webpack.config.js文件进行自定义打包配置,由于webpack是运行在node.js环境,对应应该遵守CommonJS规则进行导入导出。

复制

|--backpack   |--src     |--heading.js     |--main.js   |--index.html   |--package.json   |--webpack.config.js-------webpack配置文件
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

webpack自定义的配置文件:

复制

// webpack.config.js const path = require("path");  module.exports = {   entry:"./src/index.js",//打包入口   output:{//打包出口     filename:"bundle.js",//命名打包后的文件     path:path.join(__dirname,"output")   },   // 打包模式   mode:"none" }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

执行打包命令后会在项目根目录下自动生成打包后的文件目录,我们看到下面是执行打包命令后生成的文件,生成的是一个立即执行函数。

复制

/******/ (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, { enumerable: true, get: getter }); /******/   } /******/  }; /******/ /******/  // define __esModule on exports /******/  __webpack_require__.r = function(exports) { /******/   if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/    Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/   } /******/   Object.defineProperty(exports, '__esModule', { value: true }); /******/  }; /******/ /******/  // create a fake namespace object /******/  // mode & 1: value is a module id, require it /******/  // mode & 2: merge all properties of value into the ns /******/  // mode & 4: return value when already ns object /******/  // mode & 8|1: behave like require /******/  __webpack_require__.t = function(value, mode) { /******/   if(mode & 1) value = __webpack_require__(value); /******/   if(mode & 8) return value; /******/   if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/   var ns = Object.create(null); /******/   __webpack_require__.r(ns); /******/   Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/   if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/   return ns; /******/  }; /******/ /******/  // 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 = "./src/index.js"); /******/ }) /************************************************************************/ /******/ ({  /***/ "./src/heading.js": /*!************************!*\   !*** ./src/heading.js ***!   \************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) {  "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n// heading.js\n/* harmony default export */ __webpack_exports__[\"default\"] = (function(){\n  const element = document.createElement(\"div\");\n  element.textContent = \"hello yichuan\";\n  element.addEventListener(\"click\",()=>{\n    console.log(\"hello onechuan\");\n    return element\n  })\n});\n\n//# sourceURL=webpack:///./src/heading.js?");  /***/ }),  /***/ "./src/index.js": /*!**********************!*\   !*** ./src/index.js ***!   \**********************/ /*! no exports provided */ /***/ (function(module, __webpack_exports__, __webpack_require__) {  "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _heading_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./heading.js */ \"./src/heading.js\");\n// index.js\n\ndocument.body.append(Object(_heading_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])())\n\n//# sourceURL=webpack:///./src/index.js?");  /***/ })  /******/ });
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

  • 36.

  • 37.

  • 38.

  • 39.

  • 40.

  • 41.

  • 42.

  • 43.

  • 44.

  • 45.

  • 46.

  • 47.

  • 48.

  • 49.

  • 50.

  • 51.

  • 52.

  • 53.

  • 54.

  • 55.

  • 56.

  • 57.

  • 58.

  • 59.

  • 60.

  • 61.

  • 62.

  • 63.

  • 64.

  • 65.

  • 66.

  • 67.

  • 68.

  • 69.

  • 70.

  • 71.

  • 72.

  • 73.

  • 74.

  • 75.

  • 76.

  • 77.

  • 78.

  • 79.

  • 80.

  • 81.

  • 82.

  • 83.

  • 84.

  • 85.

  • 86.

  • 87.

  • 88.

  • 89.

  • 90.

  • 91.

  • 92.

  • 93.

  • 94.

  • 95.

  • 96.

  • 97.

  • 98.

  • 99.

  • 100.

  • 101.

  • 102.

  • 103.

  • 104.

  • 105.

  • 106.

  • 107.

  • 108.

  • 109.

  • 110.

  • 111.

  • 112.

  • 113.

在上面打包之后的文件中,src目录中的每个模块对应打包后文件中的一个函数,从而实现模块的私有作用域,在此文件中还挂载了一些其他的数据和工具函数。

写在后面

 

这篇文章主要写了webpack上路使用,对于webpack的基本使用并不是很复杂,特别是在webpack4.0后,很多配置都已经被简化。在这种配置并不复杂的前提下,开发人员对它的掌握程度,主要体现在是否能够理解它的工作机制和原理。

 

26    2021-12-16 22:02:28    webpack 原理 模块化