今天给大家讲讲
Webpack这个前端资源加载/打包工具
,相信大家都使用过Webpack在自己的项目中。本篇文章,详细的给大家介绍一下Webpack
这个东西
我通过下面四个方面给大家阐述Webpack这个前端资源加载/打包工具
1.何为Webpack
2.使用Webpack的意义
3.安装Webpack
4.如何安装一个Webpack工程
上面这张图就是
webpack官网
最为显著的一张图,也是webpack的基本流程。但许多人看到这个图片都是懵的(什么鬼东西,划来划去的)。接下来就给大家说一下webpack的流程
1.
Webpack是一个开源的JavaScript模块打包工具,其最核心的功能是解决模块之间的依赖,把各个模块按照特定的规则和顺序组织在一起,最终合并为一个JS文件(有时会有多个,这里讨论的只是最基本的情况)。这个过程就叫作模块打包。
2.
你可以把Webpack理解为一个模块处理工厂。我们把源代码交给Webpack,由它去进行加工、拼装处理,产出最终的资源文件,等待送往用户。
3.
没有接触过打包工具的读者可能会疑惑,在Web开发中我们打交道的无非是HTML、CSS、JS等静态资源,为什么不直接将工程中的源文件发布到服务器或CDN,而要交给Webpack处理呢?这两者之间有什么不同?接下来我们就要阐述使用Webpack的意义。
1.
开发一个简单的Web应用,其实只需要浏览器和一个简单的编辑器就可以了。最早的Web应用就是这么开发的,因为需求很简单。当应用的规模大了之后,就必须借助一定的工具,否则人工维护代码的成本将逐渐变得难以承受。学会使用工具可以让开发效率成倍地提升,所谓“工欲善其事,必先利其器”就是这个意思。
2.
说回Webpack,既然它解决的最主要问题是模块打包,那么为了更好地阐述Webpack的作用,我们必须先谈谈模块。
1.2.1 何为模块
1.
我们每时每刻都在与模块打交道。比如,在工程中引入一个日期处理的npm包,或者编写一个提供工具方法的JS文件,这些都可以称为模块。
2.
在设计程序结构时,把所有代码都堆到一起是非常糟糕的做法。更好的组织方式是按照特定的功能将其拆分为多个代码段,每个代码段实现一个特定的目的。你可以对其进行独立的设计、开发和测试,最终通过接口来将它们组合在一起。这就是基本的模块化思想。
3.
如果把程序比作一个城市,这个城市内部有不同的职能部门,如学校、医院、消防局等。程序中的模块就像这些职能部门一样,每一个都有其特定的功能。各个模块协同工作,才能保证程序的正常运转。
1.2.2 JavaScript中的模块
1.
在大多数程序语言中(如C、C++、Java),开发者都可以直接使用模块化进行开发。工程中的各个模块在经过编译、链接等过程后会被整合成单一的可执行文件并交由系统运行。
2.
对于JavaScript来说,情况则有所不同。在过去的很长一段时间里,JavaScript这门语言并没有模块这一概念。如果工程中有多个JS文件,我们只能通过script标签将它们一个个插入页面中。
3.
从2009年开始,JavaScript社区开始对模块化进行不断的尝试,并依次出现了AMD、CommonJS、CMD等解决方案。但这些都只是由社区提出的,并不能算语言本身的特性。而在2015年,ECMAScript 6.0(ES6)正式定义了JavaScript模块标准,使这门语言在诞生了20年之后终于拥有了模块这一概念。
4.
ES6模块标准目前已经得到了大多数现代浏览器的支持,但在实际应用方面还需要等待一段时间。主要有以下几点原因:
4.1 无法使用code splitting和tree shaking
4.2 大多数npm模块还是CommonJS的形式,而浏览器并不支持其语法,因此这些包没有办法直接拿来用。
4.3 仍然需要考虑个别浏览器及平台的兼容性问题。
那么,如何才能让我们的工程在使用模块化的同时也能正常运行在浏览器中呢?这就到了模块打包工具出场的时候了。
1.2.3 模块打包工具
模块打包工具(module bundler)的任务就是解决模块间的依赖,使其打包后的结果能运行在浏览器上。它的工作方式主要分为两种:
将存在依赖关系的模块按照特定规则合并为单个JS文件,一次全部加载进页面中。
在页面初始时加载一个入口模块,其他模块异步地进行加载。
目前社区中比较流行的模块打包工具有Webpack、Parcel、Rollup等。
1.2.4为什么选择Webpack
对比同类模块打包工具,Webpack具备以下几点优势。
1.
Webpack默认支持多种模块标准,包括AMD、CommonJS,以及最新的ES6模块,而其他工具大多只能支持一到两种。这对于一些同时使用多种模块标准的工程非常有用,Webpack会帮我们处理好不同类型模块之间的依赖关系。
2.
Webpack有完备的代码分割(code splitting)解决方案。从字面意思去理解,它可以分割打包后的资源,首屏只加载必要的部分,不太重要的功能放到后面动态地加载。这对于资源体积较大的应用来说尤为重要,可以有效地减小资源体积,提升首页渲染速度。
3.
Webpack可以处理各种类型的资源。除了JavaScript以外,Webpack还可以处理样式、模板,甚至图片等,而开发者需要做的仅仅是导入它们。比如你可以从JavaScript文件导入一个CSS或者PNG,而这一切最终都可以由第4章讲到的loader来处理。
4.
Webpack拥有庞大的社区支持。除了Webpack核心库以外,还有无数开发者来为它编写周边插件和工具,绝大多数的需求你都可以直接找到已有解决方案,甚至会有多个解决方案供你挑选。
以上我们对Webpack进行了简要介绍,但是说再多也不如实际操作一次。
是全局安装还是本地安装呢?
1.
Webpack对于操作系统没有要求,使用Windows、Mac、Linux操作系统均可。它唯一的依赖就是Node.js,下面来对其进行安装。所以安装Webpack之前你必须要安装node.js
2.
npm安装模块的方式有两种:一种是全局安装,一种是本地安装。对于Webpack来说,我们也有这两种选择。
3.
全局安装Webpack的好处是npm会帮我们绑定一个命令行环境变量,一次安装、处处运行;本地安装则会添加其成为项目中的依赖,只能在项目内部使用。这里建议使用本地安装的方式(官方也是这么建议的)
,主要有以下两点原因:
3.1
如果采用全局安装,那么在与他人进行项目协作的时候,由于每个人系统中的Webpack版本不同,可能会导致输出结果不一致。
3.2
部分依赖于Webpack的插件会调用项目中Webpack的内部模块,这种情况下仍然需要在项目本地安装Webpack,而如果全局和本地都有,则容易造成混淆。
基于以上两点,我们选择在工程内部安装Webpack的方式。首先新建一个工程目录,从命令行进入该目录,并执行npm的初始化命令。
第一步:
先初始当前的文件夹
首先你创建一个文件夹(注意这个文件夹不要带中文字体)用软件打开这个空文件夹,这里我使用vscode
通过vscode打开终端【 快捷键是:Ctrl + ` 】在终端操作下面的步骤
npm init
此时会要求你输入项目的基本信息,因为这里只是为了生成一个示例,根据提示操作就好。然后,我们会看到
目录中生成了一个package.json文件
,它相当于npm项目的说明书,里面记录了项目名称、版本、仓库地址等信息。
package.json初始内容下面图片呈现
第二步:
安装Webpack的命令(本地安装)
npm install webpack webpack-cli –-save-dev
这里我们同时安装了webpack以及webpack-cli。webpack是核心模块,webpack-cli则是命令行工具,在本例中两者都是必需的。
此时目录中生成了一个package-lock.json文件和node_modules文件夹
安装结束之后,在命令行执行npx webpack-v以及npx webpack-cli-v,可显示各自的版本号,即证明安装成功。此时可以检查是否安装成功了输入下面的语句
注意:
由于我们将Webpack安装在了本地,因此无法直接在命令行内使用“webpack”指令。工程内部只能使用npx webpack的形式。
npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
由于 npx 会检查环境变量path,所以系统命令也可以调用。
使用npx 能避免全局安装的模块。
npx webpack -v
让我们趁热打铁来打包刚刚的示例工程。如果你是第一次接触Webpack,建议按照下面的指引一步步进行操作。代码中不熟悉的地方也不必深究,这个示例只是为了让我们直观地认识Webpack的一些特性。
1.4.1 使用默认目录配置
在工程中创建一个src目录,并在src目录下创建index.html、index.js、util.js来提供我们后面的测试
1.4.2 先使用最复杂的
util.js:
//使用CommonJS导出
module.exports = function() {
console.log('hello world!')
}
index.js:
//使用CommonJS导入
const {fn} = require('./util')
fn()
index.html:
script路径先这样到后面还有改掉
此时在控制台输入打包命令:
分析下面命令
1.
npx webpack ------ 找到webpack并进入webpack
2.
entry ------ 是资源打包的入口。Webpack从这里开始进行模块依赖的查找,得到项目中包含index.js和add-content.js两个模块,并通过它们来生成最终产物。
3.
output-filename ------是输出资源名。你会发现打包完成后工程中出现了一个dist目录,其中包含的bundle.js就是Webpack的打包结果。
4.
mode ------是打包模式。Webpack为开发者提供了development、production、none三种模式。当置于development和production模式下时,它会自动添加适合于当前模式的一系列配置,减少了人为的工作量。在开发环境下,一般设置为development模式就可以了
5.
为了验证打包结果,可以用浏览器打开index.html。项目中的index.js和content.js现在已经成为了budnle.js,被页面加载和执行,并输出了各自的内容。
``
npx webpack --entry=./src/index.js --output-filename=bundle.js --mode=development
所以刚刚html文件夹里面script路径要改为bundle.j
现在可以打开index.html文件看看
1.4.3 使用npm scripts
从上面的例子不难发现,我们每进行一次打包都要输入一段冗长的命令,这样做不仅耗时而且容易出错。为了使命令行指令更加简洁,我们可以在package.json中添加一个脚本命令。
编辑工程中的package.json文件:
"scripts": {
"build": "webpack --output-filename=bundle.js --mode=development "
},
scripts是npm提供的脚本命令功能,在这里我们可以直接使用由模块所添加的指令(比如用“webpack”取代之前的“npx webpack”)。
Webpack默认的源代码入口就是 src/index.js,因此现在可以省略掉entry的配置了。如上面所示
此时在终端使用语法来验证刚刚的配置,
npm run build
1.4.4 使用webpack.config.js(推荐使用这个方法)
1.
从之前我们在package.json中添加的脚本命令来看,当项目需要越来越多的配置时,就要往命令中添加更多的参数,那么到后期维护起来就会相当困难。为了解决这个问题,可以把这些参数改为对象的形式专门放在一个配置文件里,在Webpack每次打包的时候读取该配置文件即可。
2.
Webpack的默认配置文件为webpack.config.js(也可以使用其他文件名,需要使用命令行参数指定)。现在让我们在工程根目录下创建webpack.config.js,
webpack.config.js中添加如下代码:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
},
mode: 'development',
}
现在我们可以去掉package.json中配置的打包参数了
执行npm run build,Webpack就会预先读取webpack.config.js,然后进行打包。
"scripts": {
"build": "webpack"
},
1.4.5 webpack-dev-server
到这里,其实我们已经把Webpack的初始环境配置完毕了。你可能会发现,单纯使用Webpack以及它的命令行工具来进行开发调试的效率并不高。以往只要编辑项目源文件(JS、CSS、HTML等),刷新页面即可看到效果。现在多了一步打包,我们在改完项目源码后要执行npm run build更新bundle.js,然后才能刷新页面生效。有没有更简便的方法呢?
其实Webpack社区已经为我们提供了一个便捷的本地开发工具——webpack-dev-server。用以下命令进行安装:
npm install webpack-dev-server --save-dev
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server"
},
devServer: {
static: './dist', // static静态
},
webpack-dev-server的两大职能
1.
令Webpack进行模块打包,并处理打包结果的资源请求。
2.
作为普通的Web Server,处理静态资源文件请求。
一切就绪,执行npm run dev并用浏览器打开[http://localhost:8080/],可以看到输出结果。
有时候我们希望能够更改webpack-dev-server开发服务器的默认端口号,那么可以这样做,在webpack.config.js文件中,添加devServer配置项,在其中修改主机名与端口号即可。同时还可以配置open为true,让每次启动开发服务器都打开新的窗口。
在执行npm run dev时端口号改为8081,且页面会自动打开
1.4.6 配置html-webpack-plugin
webpack核心概念:插件。通过使用插件可以让webpack用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量等。
在真实发布项目时,发布的是dist文件夹中的内容,但是dist文件夹中如果没有index.html文件,那么打包的js等文件也就没有意义了。所以,我们需要将index.html文件打包到dist文件夹中,这个时候就需要使用HtmlWebpackPlugin插件。
那么,HtmlWebpackPlugin插件到低可以为我们做什么呢?
1.
自动生成一个index.html文件(可以指定模板来生成)
2.
将打包的js文件,自动通过script标签插入到body中
实现步骤如下:
A.安装默认预览功能的包:html-webpack-plugin
npm i html-webpack-plugin -D
B.修改webpack.config.js文件,如下:
//导入包
const HtmlWebpackPlugin = require("html-webpack-plugin");
//创建对象
const htmlPlugin = new HtmlWebpackPlugin({template:"./src/index.html"})
C.继续修改webpack.config.js文件,添加plugins信息:
module.exports = {
mode: "development",
...
plugins: [htmlPlugin],
}
D.修改一下package.json文件
"serve": "webpack serve"
在执行npm run serve之前(可以先进入index.html中把script的路径给删除掉或者注释掉,因为html-webpack-plugin这个插件会帮助我们填写script的路径
D. 配好之后,使用npm run serve命令启动开发服务器之后,插件会自动的将打包好的js文件和模板html文件结合在一起,作为首页显示。
注意:
刚刚我们在webpack.config.js中添加的一些配置,当我们每次修改webpack.config.js中内容是我们都要重新打包项目输入npx webpack
来重新打包当前的文件目录。但每次都这样打包会很麻烦,当然有一些配置可以帮我们自动打包好,在这里就不说了,家人们可以去自己琢磨琢磨。
小结
上面的一系列操作就把webpack的基本配置给配置好了,不要看的很多,我只是讲的很详细一点(
要不然怎么对的起全网最详细讲解的webpack的基本操作了
)。在上面我使用了三种配置webpack的操作从难—中—易的过程逐步递进让大家可以更加了解webpack里面的原理。
同时按照了两个插件
webpack-dev-server
- 开启服务
- 监听src中代码 每次代码更新,重新打包,并且刷新页面
html-webpack-plugin
- 打包时候,生成一个index.html文件(可以根据指定的模板来生成)
- 把打包好的js文件,通过script标签引入到index.html
完结!散花!希望大家耐心看完,一定可以收获很多东西
谢谢大家的支持!!!
累死了!!!!