Webpack原理与实践之Webpack究竟解决了什么问题?

Webpack所解决的问题是:如何在前端项目中更高效地管理和维护项目中的每个资源。想要搞明白webpack,就必须先对它想要解决的问题或目标有个充分的认识。
首页 新闻资讯 行业资讯 Webpack原理与实践之Webpack究竟解决了什么问题?

[[440682]]

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

写在前面

Webpack所解决的问题是:如何在前端项目中更高效地管理和维护项目中的每个资源。想要搞明白webpack,就必须先对它想要解决的问题或目标有个充分的认识。

模块化的演化进程

阶段1:文件划分方式

复制

|--01-files   |--module-01.js   |--module-02.js   |--index.html
  • 1.

  • 2.

  • 3.

  • 4.

复制

<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8">   <meta http-equiv="X-UA-Compatible" content="IE=edge">   <meta name="viewport" content="width=device-width, initial-scale=1.0">   <title>Document</title> </head> <body>   <script src="./module-01.js"></script>   <script src="./module-02.js"></script>   <script>     // 直接使用全局成员     fun()//可能存在命名冲突     console.log(data)     data = "onechuan";//数据可能被修改   </script> </body> </html>
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

复制

//module-01.js function fun(){   console.log("module-01-fun"); }
  • 1.

  • 2.

  • 3.

  • 4.

复制

//module-02.js var data = "yichuan";
  • 1.

  • 2.

在这种进行文件划分方式中,缺点有:

  • 模块直接在全局工作,大量模块成员会污染全局作用域

  • 没有私有空间,所有模块内的成员都可以在模块外部被访问或修改

  • 一旦模块增多,容易产生命名冲突

  • 无法管理模块与模块之间的依赖关系

  • 在维护过程中很难分辨每个成员所属的模块

当然,当你项目代码少的时候可能感受不到这种方式的缺点,但是当你代码变大的时候,这种划分方式造成的问题会暴露地淋漓尽致。

阶段2:命名空间方式

在命名空间方式中,解决命名冲突的问题外,其它问题依旧存在

复制

<script src="./module-01.js"></script>   <script src="./module-02.js"></script>   <script>     module01.fun();//module-01-fun     module02.fun();//module-02-fun     // 模块成员依然可以被修改     module01.data = "onechuan"     console.log(module01.data);//"onechuan"   </script>
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

复制

// module-01.js  window.module01 = {   fun:function(){     console.log("module-01-fun");   } }  // module-02.js window.module02 = {   data:"yichuan",   fun:function(){     console.log("module-02-fun")   } }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

阶段3:立即执行函数 IIFE

通过在文件中使用立即函数和闭包的方式,可以有效解决前面的全局作用污染的问题,而且可以通过参数明显表明这个模块的依赖。虽然解决了全局作用域污染问题,但是不能够通过代码控制模块的加载顺序的问题,不便于对模块的管理,因为你不知道什么模块没有被导入,什么模块被移除。

复制

<script src="./module-01.js"></script> <script src="./module-02.js"></script> <script>   module01.fun();//module-01-fun   module02.fun();//module-02-fun </script>
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

复制

// module-01.js ;(function(){   var name = "module-01";   function fun(){     console.log(name+"-fun");   }   window.module01 = {     fun:fun   }  })()  // module-01.js ;(function(){   var name = "module-02";   function fun(){     console.log(name+"-fun");   }   window.module02 = {     fun:fun   }  })()
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

模块化规范的出现

当前是通过约定规则实现模块化的方式,不同的开发者在实施过程中会出现一些差别。

模块化规范的两点标准:

  • 一个统一的模块化标准规范

  • 一个可以自动加载模块的基础库

CommonJS规范

CommonJS规范是Node.js中所遵循的模块规范,该规范约定一个文件就是一个模块,每个模块都有单独的作用域,通过module.exports到处成员,再通过require函数进行导入模块。

AMD规范

虽然CommonJS规范使用也很方便,但是早期指定前端标准化模块时,并没有直接选择CommonJS规范,而是专门为浏览器短重新设计了AMD规范,也就是异步模块定义规范。

同期推出了Require.js,除了实现AMD模块化规范,本身也是一个非常强大的模块加载器。

复制

//AMD规范定义了一个模块 //module01.js define(["./module02.js"],function(){   return{     fun:function(){       console.log("hello-module-02");     }   } })  //AMD规范载入了一个模块 //module02.js require(["./module01.js"],function(module01){   module01.fun(); })
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

在Javascript的标准逐渐走向完善,端模块化规范的最佳实践方式也基本得到了统一:

  • 在Node.js环境中,遵循CommonJS规范来实现模块化

  • 在浏览器环境中,遵循ES Modules规范实现模块化

ES  Modules规范是ES2015中才定义的模块化系统,是最近几年才制定的标准,存在环境兼容性问题,随着webpack等一系列打包工具的流行,此规范才逐渐开始被普及。经过几年的迭代,ES  Modules规范已经成为现今最主流的前端模块化标准。

复制

//module01.js export default function fun(){   console.log("hello-module01"); }  //module02.js import fun from "./module01.js"; fun()
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

模块打包工具的出现

随着日益复杂的项目开发,在前端应用开发过程中不仅只有JS代码需要模块化,HTML和CSS这些资源文件也会面临需要被模块化的问题。从宏观角度看,这些文件也都应该被看做前端应用的一个模块,只不过这些模块的种类和用途和JS不同。

我们知道ES Modules近些年才制定的模块化标准,因此在当前浏览器环境可存在兼容问题,因此需要经过模块打包工具将ES6代码转为ES5代码。

参考文章

《Webpack官方文档》

《webpack原理与实践》

写在最后

前端模块化的发展过程和最终统一的ES Modules标准使我们深入了解webpack必须掌握的基础内容,也是现代前端开发者必不可少的基础知识。

 

19    2021-12-15 23:42:56    Webpack 原理 实践