关键词
静态模块、前端模块化、打包、四个核心概念(entry/output/loader/plugins)
webpack定义
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) —— webpack中文网
什么是静态模块?
静态模块即静态资源文件,包括js文件、css样式文件、jpg图像文件、svg等,浏览器加载网页时需要去服务器请求下载这些文件,再去解析渲染生成页面。
为什么需要前端模块化?
(ps:降低维度,这里专指js模块化)
初始,js只是一个在网页上用于和用户完成简单交互的脚本语言,一个网站只需要嵌入少量js代码,一个全局作用域挂载着所有的变量和函数。此时就好似js刚打下了浏览器这块偌大的江山,军政合一,想怎么玩怎么玩,网站能跑起来就行。
而随着网站需要实现的功能越来越多,js代码量也越来越大,也暴露出两个重大问题。
-
作用域重合
大家的代码都在一个作用域,不同的人定义的变量可能会重复从而产生覆盖
var name = 'yfj' // by yuan var name = 'wy' // by wang -
依赖关系固定
<script type="text/javascript" src="a.js"></script> <script type="text/javascript" src="b.js"></script> <script type="text/javascript" src="c.js"></script> <script type="text/javascript" src="d.js"></script> <script type="text/javascript" src="e.js"></script>一个项目引入了a、b、c、d、e五个
js文件,它们的依赖关系是e -> d -> c -> b -> a,我们需要在html文件中一次引入方可正常运行,而若是一个项目需要引入几十上百个js文件,那我们每次都需要按依赖关系手动确定引入关系岂不是太麻烦且易错了。
若是此时能出来个一世明君出来重整江山就好了,有的,“前端模块化”就是这位明君,它针对上面的两个问题给出了两个解决方案
-
独立作用域
一个前端项目拥有多个模块
- 每个模块拥有自己的作用域互不影响
- 每个模块可引入其他模块导出的变量或方法
-
主模块
- 确定主模块,主模块引入其他模块
- html中引入主模块
有了模块化之后,我们再也不用担心自己声明的变量被别人重新声明赋值,把你想要的“美羊羊”变成了“灰太狼”,更不用蛋疼的在html文件内去引入几十个甚至上百个js文件了。
但是模块化如何实现呢?
从最开始的闭包,到node服务端中的CommonJs,再到可用于前端的AMD、UMD规范,最后到趋于完美的ES6模块,这都是前端模块化走过的路
但问题在于,一旦js文件以<script src="">的形式插入html,那么require、export、import之类的模块语法就会报错,因为浏览器不支持模块化,模块语法是建立在node的环境下才有的。
即使现在绝大多数浏览器支持了ES6大部分语法,而ES6支持class模块化,但仍有部分浏览器未支持。
所以webpack等模块打包工具的一个作用就是让我们在只插入一个script标签的同时,还允许我们在js文件之间使用export、import、require这些语法。
什么是打包?
我理解的打包就是项目上线前的准备,做一些预处理的工作,将各种静态文件压缩整合,这样浏览器就可以通过少量的HTTP请求获取想要的前端资源了。
就好似出远门时,我们可以把想要携带的东西都放到一个行李箱中打包起来,而且行李箱中还分很多功能区,比如电子产品和护肤品就不能放在一个功能区,防止互相碰撞磕破护肤品的玻璃瓶,这和webpack根据各个模块之间的依赖关系进行智能打包是一个道理,最终浏览器只用请求打包好的这一个bundle即可。
webpack四大核心概念
-
entry
webpack在打包前会根据各个模块的依赖关系递归地构建一个依赖关系图,而webpack需要使用者配置依赖关系图的起点,从而将该起点作为入口分析出webpack需要打包哪些模块、怎么打包。webpack通常用于构建单页面应用,但也可通过配置多个entry文件构建多页面应用
上图就是三个页面,三个入口文件,也可复用公共代码、公共模块。
-
output
指定输出文件路径、文件名等配置
对于多入口的应用,输出文件时可用变量生成动态名,来确保每个输出文件具有唯一的名称
-
loader
loader就是转换器,能将webpack不能理解的非js模块转化为能被webpack处理的有效模块。在配置时,通过配置
rules匹配规则,根据不同的文件决定使用相应的loader进行转化。例如解析
css模块,就需要先用css-loader解析css语法,再用style-loader将css放入<style>标签中。 -
plugin
loader专用来转化,而plugin用于执行范围更广的任务。比如代码压缩、图片压缩,热更新等等。