1. 当前 Web 开发面临的困境
- 文件依赖关系错综复杂
- 静态资源请求效率低
- 模块化支持不友好
- 浏览器对高级 Javascript 特性兼容程度较低
- …
2. webpack 概述
webpack 是一个流行的前端项目构建工具(打包工具),可以解决当前 web 开发中所面临的困境。
webpack 提供了友好的模块化支持,以及代码压缩混淆、处理 js 兼容问题、性能优化等强大的功能,从而让程序员把工作的重心放到具体的功能实现上,提高了开发效率和项目的可维护性。
目前绝大多数企业中的前端项目,都是基于 webpack 进行打包构建的。
3. webpack 的基本使用
① 使用jQuery创建列表隔行变色项目
- 新建项目空白目录,并运行
npm init –y
命令,初始化包管理配置文件 package.json - 新建 src 源代码目录 -> 创建index.html 首页
- 初始化index.html 首页基本的结构,书写骨架代码:在页面中摆放一个ul,ul里面放置几个li
- 运行
npm install jquery –S
命令,安装 jQuery - 创建index.js文件,书写隔行变色控制代码,如下:
// 打开index.js文件,编写代码导入jQuery并实现功能:
import $ from "jquery";
$(function() {
$("li:odd").css("background","cyan");
$("li:odd").css("background","pink");
})
- index.html文件代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<!-- 这里的文件导入是在head中,是可以的,因为$(function(){}方法是DOM加载完成的入口,相当于原生js中的DOMContentLoaded,所以这里js文件的引入无论是放在head还是body里面都是一样的,一般都放head中 -->
<script src="./index.js"></script>
</head>
<body>
<ul>
<li>这是第1个li</li>
<li>这是第2个li</li>
<li>这是第3个li</li>
<li>这是第4个li</li>
</ul>
</body>
</html>
- 浏览器打开index.html,发现并没有隔行变色效果
注意:此时项目运行会有错误,因为import $ from "jquery";
这句代码属于ES6的新语法代码,在浏览器中可能会存在兼容性问题,我们需要用webpack处理js兼容性问题。
补充:
npm install xxx -S,也就是 npm install xxx --save 写入dependencies
npm install xxx -D,也就是 npm install x'x'x --save-dev 写入devDependencies
② 在项目中安装和配置 webpack
- 运行
npm install webpack webpack-cli –D
命令,安装 webpack 相关的包 - 在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件
- 在 webpack 的配置文件中,初始化如下基本配置:
module.exports = {
// mode 用来指定构建模式,分为 development production
// 在开发阶段使用development,文件不会被压缩和混淆,上线阶段一定要改成 production,文件会被压缩和混淆
mode: 'development'
}
- 在 package.json 配置文件中的 scripts 节点下,新增 dev 脚本如下:
"scripts": {
"dev": "webpack" // script 节点下的脚本,可以通过 npm run dev 执行
}
- 在终端中运行
npm run dev
命令,启动 webpack 进行项目打包 - 打包完成后会生成dist文件夹,里面有个main.js 文件,这就是index.js文件打包后的文件,我们把index.html中index.js文件的导入替换成main.js,重新打开index.html,发现隔行变色有效果了。
自此,webpack打包最简单的使用就完成了。
③ 配置打包的入口与出口
webpack的 4.x 版本中默认约定:
- 打包的入口文件为 src -> index.js
- 打包的输出文件为 dist -> main.js
如果要修改打包的入口与出口,可以在 webpack.config.js 中新增如下配置信息:
const path = require('path') // 导入 node.js 中专门操作路径的模块
module.exports = {
entry: path.join(__dirname, './src/index.js'), // 打包入口文件的路径
output: {
path: path.join(__dirname, './dist'), // 输出文件的存放路径
filename: 'bundle.js' // 输出文件的名称
}
}
重新运行 npm run dev
命令,启动 webpack 进行项目打包,重新在index.html中引入bundle.js文件,浏览器打开index.html,隔行变色没问题。
④ 配置 webpack 的自动打包功能
当我们修改index.js文件代码之后,需要重新打包、刷新,才会生效,这样就很麻烦,所以我们需要自动打包。
- 运行
npm install webpack-dev-server –D
命令,安装支持项目自动打包的工具 - 修改 package.json -> scripts 中的 dev 命令,如下:
"scripts": {
"dev": "webpack-dev-server" // script 节点下的脚本,可以通过 npm run 执行
}
- 将 src 的 index.html 中的
<script src="./index.js"></script>
修改为/bundle.js
注意:①webpack-dev-server
会启动一个实时打包的 http 服务器,打包生成的输出文件,默认放到了项目根目录中,而且是虚拟的、看不见的。②/bundle.js
代表我们的项目根目录中有一个 bundle.js ,但是我们看不到,因为它在内存中(不信你可以通过http://localhost:8080/bundle.js访问一下,可以访问得到的)。 - 运行
npm run dev
命令,重新进行打包,这时候光标会一直在闪。 - 修改index.js 文件内容,保存,在浏览器中访问 http://localhost:8080 地址,打开src下的index.html即可查看效果。
⑤ 配置 html-webpack-plugin 生成预览页面
上面,每次我们进入 http://localhost:8080 还需要点击src才能看到我们写的页面,很麻烦,如果我们想直接输入 http://localhost:8080 就可以看到项目运行结果,怎么办呢?
我们只需要将src中的index.html复制(不是手动复制)到根目录就可以了,那么怎么复制呢?如下:
- 运行
npm install html-webpack-plugin –D
命令,安装生成预览页面的插件 - 修改 webpack.config.js 文件头部区域,添加如下配置信息:
// 导入生成预览页面的插件,得到一个构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin({ // 创建插件的实例对象
template: './src/index.html', // 指定要用到的模板文件
filename: 'index.html' // 指定生成的文件的名称,该文件存在于内存中,在目录中不显示
})
- 修改 webpack.config.js 文件中向外暴露的配置对象,新增如下配置节点:
module.exports = {
plugins: [ htmlPlugin ] // plugins 数组是 webpack 打包期间会用到的一些插件列表
}
使用npm run dev
将项目跑起来,然后浏览器输入 http://localhost:8080 就可以看到项目运行结果了。
⑥ 配置自动打包相关的参数
上面,我们自动打包完成后需要自己手动输入 http://localhost:8080 ,比较麻烦,能不能在打包完成后自动打开 http://localhost:8080 地址呢?在package.json中配置如下:
// --open 打包完成后自动打开浏览器页面
// --host 配置 IP 地址
// --port 配置端口
"scripts": {
"dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888"
},
修改自动打包参数之后需要重新运行打包命令npm run dev
这时候打包完成会自动打开如上地址。
4. webpack 中的loader加载器
在实际开发过程中,webpack默认只能打包处理以.js后缀名结尾的模块,其他非.js后缀名结尾的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,如果没有特定的加载器,则报错!
loader 加载器可以协助 webpack 打包处理特定的文件模块,比如:
- less-loader 可以打包处理 .less 相关的文件
- sass-loader 可以打包处理 .scss 相关的文件
- url-loader 可以打包处理 css 中与 url 路径相关的文件
5. webpack 中加载器的基本使用
① 打包处理 css 文件
- 运行
npm i style-loader css-loader -D
命令,安装处理 css 文件的 loader - 在 webpack.config.js中,添加module属性 -> rules 数组中,添加 loader 规则如下:
// 所有第三方文件模块的匹配规则
module: {
rules: [
// 表示匹配到以.css结尾的文件,就使用style-loader和css-loader来打包处理
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
}
其中,test 表示匹配的文件类型,use 表示对应要调用的 loader。
注意:use 数组中指定的 loader 顺序是固定的,多个 loader 的调用顺序是:从后往前调用
② 打包处理 less 文件
- 运行
npm i less-loader less -D
命令。(其中less是less-loader的内置依赖项,如果想要less-loader正常工作,必须安装less) - 在 webpack.config.js中,添加module属性 -> rules 数组中,添加 loader 规则如下:
// 所有第三方文件模块的匹配规则
module: {
rules: [
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }
]
}
③ 打包处理 scss 文件
- 运行
npm i sass-loader node-sass -D
命令。(其中node-sass是sass-loader的内置依赖项) - 在 webpack.config.js中,添加module属性 -> rules 数组中,添加 loader 规则如下:
// 所有第三方文件模块的匹配规则
module: {
rules: [
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
]
}
注意:scss文件后缀是 .scss,使用的loader是 sass-loader。
④ 配置 postCSS 自动添加 css 的兼容前缀
::placeholder {
color: red;
}
上面的伪元素选择器是将placeholder的文字颜色修改为红色,但是这个选择器有兼容性问题,在ie中没效果,但是我们自己添加浏览器前缀比较麻烦,我们可以通过 postCSS 自动添加 css 的兼容前缀。
- 运行
npm i postcss-loader autoprefixer -D
命令 - 在项目根目录中新创建 postcss 的配置文件 postcss.config.js,并初始化如下配置:
const autoprefixer = require('autoprefixer') // 导入自动添加前缀的插件
module.exports = {
plugins: [ autoprefixer ] // 挂载插件
}
- 在 webpack.config.js 的 module -> rules 数组中,修改 css 的 loader 规则如下:(注意是修改原来的css的loader规则,不是重新添加)
module: {
rules: [
{ test:/\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] }
]
}
⑤ 打包样式表中的图片和字体文件
对于一些图片路径,比如:background: url('../images/1.jpg');
webpack默认处理不了,所以:
- 运行
npm i url-loader file-loader -D
命令,其中 file-loader 是 url-loader 的内置依赖项 - 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
module: {
rules: [
{
// 只要是这些后缀名结尾的文件,统一使用url-loader处理
test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
// 当use后面只有一项,可以不用数组,直接写一个字符串
use: 'url-loader?limit=16940'
}
]
}
其中 ? 之后的是 loader 的参数项,limit 用来指定图片的大小,单位是字节(byte),只有小于 limit 大小的图片,才会被转为 base64 图片,base64 图片在加载期间会更快一些,如果大于等于这个数字,就不会转成 base64 图片,直接还是图片的 url 地址。
⑥ 打包处理 js 文件中的高级语法
如果我们在index.js中写如下代码,weabpack打包的时候会报错,因为这些是js的高级语法。
class Person {
static info = 'aaa'
}
console.log(Person.info)
我们需要安装如下插件:
- 安装babel转换器相关的包:
npm i babel-loader @babel/core @babel/runtime -D
。 - 安装babel语法插件相关的包:
npm i @babel/preset-env @babel/plugin-transformruntime @babel/plugin-proposal-class-properties –D
(我在执行这个命令的时候一直卡住,首先要保证下载源是taobao,如果还是卡住,可以尝试一个一个下载)。 - 在项目根目录中,新创建 babel 配置文件 babel.config.js 并初始化基本配置如下:
module.exports = {
presets: [ '@babel/preset-env' ],
plugins: [ '@babel/plugin-transform-runtime', '@babel/plugin-proposalclass-properties' ]
}
- 在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:
// exclude 为排除项,表示 babel-loader 不需要处理 node_modules 中的 js 文件,只处理我们自己写的js文件
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
这样再次执行:npm run dev
就不会报错了,终端也会打印 "aaa"。