构建系列之webpack窥探上

前言

在网页开发的早期只是单纯的静态html文件,后来引入了js,可以做一些简单的交互动作,比如表单验证或动画实现等,那个时候整个网站的代码还是很少的,js直接写在<script>标签中也不会有什么问题。

前端的转折变迁

2008年9月2号,当Chrome第一次出现的时候(V8与Chrome同一天宣布开源),它对网页的加载速度让所有人惊叹,是V8引擎把JavaScript的运行速度提上来了,让前端从蒸汽机机时代正式步入内燃机时代。

2009年诞生的Node.js和2010年诞生的npm,迅速将JavaScript变成全球最受欢迎的生态系统之一。前端正式从石器时代进入到了工业化时代。

随着业务复杂度的与日俱增,js代码越来越多,单个js文件已经不能解决问题,于是我们将代码组织在多个js文件中,进行维护。但是这种维护方式,依然不能避免一些灾难性的问题。痛点如下:

  • 变量和方法不容易维护,容易污染全局作用域。
  • 加载资源的方式通过script标签从上到下。
  • 依赖的环境主观逻辑偏重,代码较多就会比较复杂。
  • 大型项目资源难以维护,特别是多人合作的情况下,资源的引入会让人崩溃。

面对如上问题,我们需要降低复杂度,用分治的思想将原有的代码拆成子模块,模块化的开发方式可以提供代码复用率,方便进行代码的管理。通常来说,一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。

但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!考虑到Javascript模块现在还没有官方规范,这一点就更重要了。目前流行的js模块化规范有CommonJS、AMD、CMD以及ES6的模块系统。

CommonJS

NodeJS诞生之后,它使用CommonJS的模块化规范。从此,js模块化开始快速发展。它有四个重要的环境变量为模块化的实现提供支持:module、exports、require、global。

ES6

在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

Webpack登场

模块化思想的提出,将复杂的程序分割成更小的文件。前端工程师们还通过不懈的努力,将开发效率进一步提升。这些年优秀的框架层出不穷react、vue、angular、es6这种在javascript基础上拓展的新的语法规范和less、sass、css处理器等等等。但这些框架大大提高开发效率的同时,又为后期维护造成了困扰。因为利用这些工具的文件往往不能直接被浏览器识别,需要手动处理,很影响开发进度。

是否可以有一种方式,不仅可以让我们编写模块,而且还支持任何模块格式(至少在我们到达ESM之前),并且可以同时处理资源和资产?所以webpack应运而生~这就是webpack存在的原因。它是一个工具,可以打包你的JavaScript应用程序(支持ESM和CommonJS),可以扩展为支持许多不同的静态资源,例如:images, fonts和stylesheets。

webpack的官方定义:

At its core, webpack is a static module bundler for modern JavaScript applications.

通俗地讲webpack 是一个传统的 JavaScript 模块打包器。创建的目的是通过有效地将前端应用分割成块,快速地将其传送到用户的浏览器。作为最古老、最成熟的打包工具之一,至今仍在积极地维护中,webpack 拥有一个庞大的插件生态系统,适应任何类型的复杂应用。

Webpack的原理

核心概念

  • entry:一个可执行模块或者库的入口,webpack编译的起点
  • chunk:多个文件组成一个代码块。webpack会将module按特定的规则组织成一个一个的chunk,这是打包。
  • loader:文件转换器。例如把es6转为es5,scss转为css等
  • plugin:扩展webpack功能的插件。在webpack构建的生命周期节点上加入扩展hook,添加功能,在特定时间点介入编译过程。
  • Compiler:编译管理器,webpack启动后会创建compiler对象,该对象一直存活直到结束退出。
  • Dependence:依赖对象,webpack基于该类型记录模块间依赖关系。
  • Module:webpack内部所有资源都会以“module”对象形式存在,所有关于资源的操作、转译、合并都是以“module”为基本单位进行的。

构建流程

初始化阶段

  • 初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果。

  • 开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的 run 方法开始执行编译。
  • 确定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去。

构建阶段

  • 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,调用JS解释器将内容转换为AST对象再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  • 完成模块编译:递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系

生成阶段

  • 输出:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
  • 写入文件系统(emitAssets):在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

Webpack特点

  • 简单易用:支持零配置,接入简单方便
  • 庞大生态:webpack社区和用户基础庞大
  • 代码拆分:有两种组织模块依赖的方式,同步和异步
  • Loader:将各种类型的资源转换成 JavaScript 模块
  • 智能解析:有一个智能解析器,几乎可以处理任何第三方库
  • 插件系统:有一个功能丰富的插件系统
  • 快速运行:使用异步 I/O 和多级缓存提高运行效率

总结

webpack是一个传统且强大的JavaScript 应用打包工具,致力于解决前端工程化,特别是浏览器端工程化中遇到的问题,让开发者集中注意力编写业务代码,而把工程化过程中的问题全部交给webpack来处理。其强大的社区支持和不断的进化支撑着自己在前端的发展过程中能始终有一席之地。webpack关心性能和加载时间;它始终在改进或添加新功能。webpack引入tree shaking 旨在优化构建和线上运行时的性能,异步地加载chunk和预取,以便为你的项目和用户提供最佳体验。下篇文章我们会在实战和开发中大家更关注的问题上带来更多的知识详解,敬请关注。微信公众号首发构建系列之webpack窥探上,欢迎关注微信公众号:江湖修行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值