《一》Webpack简介

代码中使用的Webpack版本:4.43.0

在过去的很长一段时间里,JavaScript这门语言并没有模块这一概念。如果工程中有多个JS文件,只能通过script标签将它们一个个插入页面中。但这种做法有很多缺点:

  1. 需要手动维护JS的加载顺序。页面的多个script之前通常会有依赖关系,但由于这种依赖关系是隐式的,除了添加注释以外很难清晰地指明谁依赖了谁,这样当页面中加载的文件过多时就很容易出现问题。
  2. 每一个script标签都意味着需要向服务器请求一次静态资源,在HTTP2还没出现的时期,建立连接的成本是很高的,过多的请求会严重拖慢网页的渲染速度。
  3. 在每个script标签中,顶层作用域即全局作用域,如果没有任何处理而直接在代码中进行变量声明或函数声明,就会造成全局作用域的污染。

从2009年开始,JavaScript社区开始对模块化进行不断地尝试,并依次出现了AMD、CommonJS、CMD等解决方案,但这些都只是由社区提出的,并不能算语言本身的特性。在2015年,ES6正式定义了JavaScript模块标准。模块化解决了上述的所有问题:

  1. 通过导入和导出语句可以清晰地看到模块间的依赖关系。
  2. 模块可以借助工具来进行打包,在页面中只需要加载合并后的资源文件,减少了网络开销。
  3. 多个模块之间的作用域是隔离的,彼此不会有命名冲突。

ES6模块标准目前已经得到大多数现代浏览器的支持,但在实际应用方面还需要等待一段时间,主要有以下几点原因:

  1. 无法使用Webpack的两个特别重要的特性:code splitting和tree shaking。
  2. 大多数npm模块还是CommonJS的形式,而浏览器并不支持其语法,因此这些包没有办法直接拿来用。
  3. 仍然需要考虑个别浏览器及平台的兼容性问题。

如何能让工程在使用模块化的同时也能正常运行在浏览器中呢?就需要使用模块打包工具了。模块打包工具的任务就是解决模块间的依赖,使其打包后的结果能运行在浏览器上。它的工作方式主要分为两种:

  1. 将存在依赖关系的模块按照特定规则合并为单个JS文件,一次全部加载进页面中。
  2. 在页面初始时加载一个入口模块,其他模块异步地进行加载。

Webpack:

Webpack是一个打包模块化JavaScript的工具,在Webpack里一切文件皆模块,通过Loader转换文件,通过Plugin注入钩子,最后输出由多个模块组合成的文件。

Webpack在启动后会从Entry里配置的Module开始,递归解析出Entry依赖的所有Module。每找到一个Module,就会根据配置的Loader去找出对应的转换规则,对Module进行转换后,再解析出当前Module依赖的Module。这些模块会以Entry为单位进行分组,一个Entry及其所有依赖的Module被分到一个组也就是一个Chunk。最后,Webpack会将所有Chunk转换成文件输出。在整个流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑。

Webpack的优缺点:

Webpack的优点是:

  1. 专注于处理模块化的项目,能做到开箱即用、一步到位。
  2. 可通过Plugin扩展,完整好用又不失灵活。
  3. 使用场景不局限于Web开发。
  4. 社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展。
  5. 良好的开发体验。

Webpack的缺点是只能用于采用模块化开发的项目。

安装Webpack:

Webpack对于操作系统没有要求,使用windows、Mac、Linux操作系统均可。它唯一的依赖就是Node.js。

全局安装:

使用Node.js的包管理器npm来安装Webpack到全局。全局安装的好处是npm会帮我们绑定一个命令行环境变量,一次安装,处处使用。

命令:npm i -g webpack

本地安装:

使用Node.js的包管理器npm来安装Webpack到本地。本地安装会添加其成为项目中的依赖,只能在项目内部使用。

命令:

  1. npm i -D webpack:安装最新的稳定版;
  2. npm i -D wenpack@<version>:安装指定版本;
  3. npm i -D webpack@beta:安装最新的体验版本;

npm i -D:是npm install --save-dev的简写,是指安装模块并保存到package.json的devDependencies。

推荐本地安装的方式,原因是:

  1. 如果采用全局安装,那么在与他人进行项目协作的时候,由于每个人系统中的Webpack版本不同,可能会导致输出结果不一致。
  2. 部分依赖于Webpack的插件会调用项目中Webpack的内部模块,这种情况下仍然需要在项目本地安装Webpack,而如果全局和本地都有,则容易造成混淆。

使用Webpack:

  1. 新建一个目录webpack-demo,从命令行进行该目录,并执行npm的初始化命令npm init,会生成package.jaon文件(相当于npm项目的说明书,里面记录了项目名称、版本、仓库地址等信息)。
    在这里插入图片描述
  2. 在项目的根目录下执行npm install webpack webpack-cli –-save-dev命令,安装Webpack到本地,会生成node_modules文件夹和package-lock.json文件,而且package.json中的devDependencies下也增加了webpack和webpack-cli。
    在这里插入图片描述
  3. 新建HTML和JS文件:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  4. 在项目的根目录下执行webpack --entry=./index.js --output-filename=bundle.js --mode=development命令进行打包。

在这里插入图片描述
5. 用浏览器打开index.html即可看到效果。
在这里插入图片描述

使用npm scripts:

从上面的例子发现,每进行一次打包都要输入一段冗长的命令,这样做不仅耗时而且容易出错。为了使命令行指令更加简洁,可以在pageage.json中添加一个脚本命令scripts,scripts是npm提供的脚本命令功能,在这里可以直接使用由模板所添加的指令。

  1. 在package.json文件中配置scripts。
    "scripts": {
        "build": "webpack --entry=./index.js --output-filename=bundle.js --mode=development"
      }
    
  2. 可以对add-content.js的内容稍加修改,然后执行npm run build命令重新打包。
  3. 浏览器打开index.html即可验证效果。
使用默认目录配置:

上面的index.js是放在工程根目录下的,而通常情况下我们会分别设置源码目录与资源输出目录。工程源代码放在/src中,输出资源放在/dist中。

  1. 在工程中创建一个src目录,并将index.js和add-content.js移动到该目录下。对于输出资源目录来说,Webpack已经默认是/dist,我们不需要做任何改动。而且,Webpack默认的源代码入口就是src/index.js,因此可以省略掉entry的配置了。
    在这里插入图片描述
  2. 重新执行npm run build命令进行打包,打开浏览器查看效果。
使用配置文件:

从之前在package.json中添加的脚本命令来看,当项目需要越来越多的配置时,就要往命令中添加更多的参数,那么到后期维护起来就会相当困难。为了解决这个问题,可以把这些参数改为对象的形式专门放在一个配置文件里,在Webpack每次打包的时候读取该配置文件即可。Webpack的默认配置文件为webpack.config.js。

  1. 在工程根目录下创建webpack.config.js,并添加如下代码。
    module.exports = {
        entry:'./src/index.js',
        output:{
            filename:'bundle.js'
        },
        mode:'development'
    }
    
  2. 去掉package.json中配置的打包参数。
    "scripts": {
        "build": "webpack"
      }
    
  3. 对add-content.js的内容稍加修改;然后执行npm run build,Webpack就会预先读取webpack.config.js,然后进行打包;完成之后打开index.html进行验证即可。
webpack-dev-server:

webpack-dev-server的作用是启动一个本地服务,可以处理打包资源与静态文件的请求。当服务启动时,会先让Webpack进行模块打包并将资源准备好;当webpack-dev-server接收到浏览器的资源请求时,首先会进行URL地址检验,如果该地址是资源服务地址,就会从Webpack的打包结果中寻找该资源并返回给浏览器,反之如果请求地址不属于资源服务地址,则直接读取硬盘中的源文件并将其返回。

webpack-dev-server的两大职能:令Webpack进行模块打包,并处理打包结果的请求资源;作为普通的Web Server,处理静态资源文件请求。

直接用Webpack开发和使用webpack-dev-server有一个很大的区别:前者每次都会生成bundle.js,而webpack-dev-server只是将打包结果放在内存中,并不会写入实际的bundle.js,在每次webpack-dev-server接收到请求时都只是将内存中的打包结果返回给浏览器。
这一点可以通过删除工程中的dist目录来验证,会发现即使dist目录不存在,刷新页面后功能仍然是正常的。

  1. 安装命令:npm install webpack-dev-server --save-dev

    安装指令中的–save-dev参数是将webpack-dev-server作为工程的devDependenceis(开发环境依赖)记录在package.json中。这样做是因为webpack-dev-server仅仅在本地开发时才会用到,在生产环境中并不需要它,所以放在devDependencies中是比较恰当的。

  2. 为了便捷地启动webpack-dev-serve,在package.json中添加一个dev指令。
    在这里插入图片描述

  3. 编辑webpack.config.js,对webpack-dev-server进行配置。
    在这里插入图片描述

  4. 更改一下add-content.js,执行npm run dev并用浏览器打开http://localhost:8080/即可看到效果。

webpack-dev-server还有一项很便捷的特性就是live-reloading(自动刷新),当webpack-dev-server发现工程源文件进行了更新操作就会自动刷新浏览器,显示更新后的内容,该特性可以提升本地开发的效率。可以保持本地服务启动以及浏览器打开的状态,到编辑器去更改add-content.js,此时切回到浏览器,会发现浏览器的内容自动更新了。

后面还会学到hot-module-replacement(模块热替换),甚至不需要刷新浏览器就能获取更新后的内容。

使用Loader:

Loader具有文件转换的功能。webpack.config.js配置里的module.rules数组配置规则,告诉Webpack在遇到哪些文件时使用哪些Loader去加载和转换。
3. 新建main.css文件,为项目引入CSS代码以让文字居中显示。
在这里插入图片描述
4. Webpack将一切文件看作模块,CSS文件也不例外。要引入CSS文件,需要像引入JS文件那样,修改入口文件main.js。
在这里插入图片描述
5. 但是这样修改后去执行Webpack构建是会报错的,因为Webpack不原生支持解析CSS文件。要支持非JS类型的文件,需要使用Webpack的Loader机制。首先安装要使用的Loader:npm i -D style-loader css-loader;然后修改webpack.config.js中的配置。
ubmV0L3dzbG5fMTIzNDU2,size_16,color_FFFFFF,t_70)
6. 重新执行webpack命令构建,会发现bundle.js更新了,里面注入了在main.css中写的CSS,而不会额外生成一个CSS文件,而且重新刷新index.html,“Hello,Webpack”也居中了。

CSS可以被写在JS里,都是style-loader的功劳。它的工作原理大概是将CSS的内容用JS里的字符串存储起来,在网页执行JS的时候通过DOM操作,动态地向HTML head标签里插入 HTML style标签。这样做会导致JS文件变大并且加载网页的时间变长,可以通过Webpack Plugin机制来让Webpack单独输出CSS文件。

使用Plugin:

Plugin是用来扩展Webpack功能,通过在构建流程里注入钩子实现。

Webpack是通过plugins属性来配置需要使用的插件列表的。plugins属性是一个数组,里面的每一项都是插件的一个实例,在实例化一个组件时通过构造函数传入这个组件支持的配置属性。

  1. 上面通过Loader加载了CSS文件,现在通过Plugin将注入bundle.js文件里的CSS提取到单独的文件中。首先安装插件npm i -D extract-text-webpack-plugin;然后修改webpack.config.js中的配置。
    在这里插入图片描述

ExtractTextPlugin插件的作用是提取出JS代码里的CSS到一个单独的文件中。
filename属性告诉插件输出的CSS文件名称是通过[name]_[md5:contenthash:hex:8].css字符串模板生成的,里面的[name]代表文件的名称,[md5:contenthash:hex:8]代表根据文件内容算出来的8位的Hash值。

执行webpack命令构建,会报错:Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead。
原因:extract-text-webpack-plugin还不能支持webpack4.0.0以上的版本。
解决方法:执行npm install -–save-dev [email protected]命令。

  1. 重新执行webpack命令构建,dist目录下多出了一个CSS文件,bundle.js文件里也没有CSS代码了。将该CSS文件通过link标签引入index.html中即可。
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wsln_123456/article/details/106519367