webpack官网 webpack.p2hp.com/
webpack简介
webpack是一个打包模块化JavaScript的工具,他会从入口模块出发,识别出源码中的模块化导入语句,递归地找出入口文件的所有依赖,将入口和其他所有的依赖打包到一个单独的文件中
webpack是基于node.js使用的工具
webpack
的能力
编译代码能力,提高效率,解决浏览器兼容问题

模块整合能力,提高性能,可维护性,解决浏览器频繁请求文件的问题

万物皆可模块能力,项目维护性增强,支持不同种类的前端模块类型,统一的模块化方案,所有资源文件的加载都可以通过代码控制

webpack安装
-
可以安装全局,但是不建议安装全局,不利于版本更新
-
可以安装早项目里,命令如下:
javascript
# webpack安装在项目里
# 安装最新的稳定版本
npm i -D webpack
#安装指定版本
npm i -D webpack@<version>
#安装最新版的体验版,会出现bug,不可以用于生产换将
npm i -D webpack@beta
#安装webpack V4+版本时,需要额外安装webpack-cli
npm i -D webpack-cli
补充: -D 开发依赖 -S 生产依赖
如果是做普通前端项目,package.json 里面的依赖包作为开发依赖和生产依赖基本没啥区别;如果项目是做 npm 包或者 node 服务的,会有些许差别。
- 开发依赖
- 执行操作后,package.json 里 devdependencies 里保存相应依赖包,这些包只在做项目的时候会使用到,在项目打包上线后不依赖于这些包项目依然可以正常运行。比如:gulp/webpack 等等。
- 在举个例子:比如说在nodejs中的开发阶段我想要通过爬虫向我这个里面数据库里面放点东西,实际上这个东西打包上线之后用户根本就不会用到这个东西,只是我们开发人员在开发时候的使用,这个就是开发依赖.
- 生产依赖
执行操作后,package.json 里 dependencies 里保存相应依赖包,这些包在项目打包上线后依然需要使用项目才能正常运行,比如:axios 等等
准备执行构建
-
初始化项目
-
准备入口文件:新建src文件夹,并在文件夹下新建index.js文件
-
新建文件webpack.config.js文件,并简单配置webpack
-
终端执行 npx webpack 命令,结果会生成dist文件夹,其中的main.js文件是项目代码经webpack处理后得到的文件 注意:webpack执行构建会找webpack.config.js这个配置文件,如果没有找到,走默认配置
-
在dist文件夹下新增index.html文件,并引入main.js文件
-
浏览器执行index.html文件,可以看到项目运行结果
webpack基础配置和理解
javascript
//webpack.config.js
const path = require("path");
// webpack 是基于nodeJS的,webpack配置就是module.exports抛出的对象,
module.exports = {
// context -- 上下文,项目打包的相对路径,默认值:process.cwd(),必须是绝对目录
context:process.cwd(), // 项目文件夹的根目录
// entry -- 入口 执行构建的入口,项目入口
// 从入口文件开始,将所有的依赖、代码等解析压缩到一个文件里
// entry 可以是字符串,数组,对象
entry:'./src/index.js', // --> 实际:entry:{ main:"./src/index.js", }
// entry:['./src/index.js','./src/other.js'], // 并非多入口,只是将两个模块的代码放在了一个文件里
// entry:{
// index:'./src/index.js',
// other:'./src/other.js',
// }, // 多入口,更改 --- output.filename:[name].js
// 意思是:从index.js文件开始执行的代码会在打包后存在index.js文件中
// 从other.js文件开始执行的代码会在打包后存在other.js文件中
// 输出
output:{
// path -- 构建后的文件资源存放的地方,必须是绝对路径
path:path.resolve(__dirname,"./dist"),
// filename -- 构建后的文件资源名字
filename:"main.js", // 文件会被dist文件夹下的index.html引用,之后直接执行index.html文件,就可以使项目在浏览器上执行
// filename:"[name].js", // 多出口 配合 entry 多入口使用,不同的html文件引用不同的执行文件,就可以执行两套代码了
// 比如:other.html文件引用other.js文件,执行代码1;index.html文件引用index.js文件,执行代码2;
}
}
javascript
// other.js
export function add(n1,n2){
return n1 + n2;
}
javascript
// index.js
// 模块化开发,当前流行的单页面入口应用 spa
// 引入模块,形成依赖
import { add } from "./other.js";
console.log(add(2,3));
执行 npx webpack 命令后,src/main.js文件内容如图
webpack执行过程:
- 寻找webpack.config.js文件,如果有按照配置解析入口文件,如果没有按照默认配置解析文件
- 找到entry配置的入口文件
- 入口文件第一行代码:import { add } from "./other.js",将add函数引入到方法内存里
- 入口文件第二行代码:console.log(add(2,3));
- 先执行add(2,3),得出结果5,并替换内容
- 将console.log(add(2,3));编译为console.log(5);
- 入口代码结束,解析后的代码被放入新的文件main.js文件中。
- 按照webpack配置的出口文件内容,在目录下新建dist文件,并在dist文件下放入main.js文件。
webpack 中 hash 的作用,以及如何利用 hash 实现不停机更新
Webpack 中的 Hash
在 Webpack 的构建流程中,hash 是一个重要的概念。hash 是一个特殊的字符串,它是根据文件的内容计算得出的。在 Webpack 中,有三种不同类型的 hash:hash,chunkhash 和 contenthash。
- hash:是根据整个项目构建的,当项目中的任何一个文件内容改变,整个项目的 hash 值都会改变。
- chunkhash:根据不同的入口文件(Entry)进行依赖文件解析、构建,对应不同的 chunk,最后每个 chunk 根据内部模块的内容和依赖关系构建出一个 hash 值。只要组成 chunk 的文件内容或其依赖的文件内容发生改变,那么构建的 hash 值就会改变,用于存在两个或以上的入口文件的项目。
- contenthash:根据文件的内容进行 hash 计算,只有文件内容改变,这个 hash 值才会改变。
在实际的构建过程中,我们通常会将这些 hash 值添加到打包输出的文件名中,这样一来,只要文件的内容发生改变,那么文件名就会改变,从而达到浏览器缓存管理的目的。
如何利用 Hash 实现不停机更新
利用 Hash 实现不停机更新主要是利用浏览器的缓存机制和服务器配置。
在 Webpack 打包的时候,如果我们在配置中设置了 output 的 filename 为 '[name].[contenthash].js',那么每次构建出的文件名就会带上基于文件内容计算出的 hash 值。只要我们的代码有改动,那么打包出的新文件的文件名就会变化。
当用户访问网站的时候,服务器会返回包含这些静态资源链接的 HTML 文件。因为每次更新的文件名不同,所以用户浏览器会重新请求新的文件,而不是使用旧的缓存文件。而旧的文件如果没有被请求,也不会影响网站的正常使用。
要注意的是,这需要服务器配置长时间的静态资源缓存,并且在发布新版本时,要保证新旧版本文件同时存在,从而实现无缝切换,也就是我们说的"不停机更新"。
这种方式不仅可以利用浏览器缓存,提高网站性能,也可以在更新网站的时候不影响用户的使用体验。
java
filename:"[name][hash:16].js"
// hash:哈希值默认20位 hash:16 -- 16位哈希值
mode构建模式
mode:模式配置,用于指定Webpack的工作模式。包括开发模式(development)和生产模式(production)。
loader 模块转换
webpack默认只支持.json和.js模块,不支持其他的不认识的模块。
java
// 处理不认识的模块
module:{
rules:[
{
test:/\.css$/,
// loader 模块转换
// loader的执行顺序是从后往前
// css-loader 言简意赅 是把css模块的内容 加入到 js模块中去
// css in js方式
// style-loader 从js中提取css的loader 在html中创建style标签 把css的内容放在这个style标签中
use:["style-loader","css-loader"],
}
]
}
常见的 loader:
- image-loader:加载并且压缩图片文件
- css-loader:帮助 webpack 打包处理 css 文件,使用 css-loader 必须要配合使用 style-loader
- style-loader:用于将 css 编译完成的样式,挂载到页面的 style 标签上。但是要注意 loader 执行顺序,style-loader 要放在第一位,loader 都是从后往前执行
- babel-loader:把 ES6 转换成 ES5
- sass-loader: css 预处理器,能更好的编写 css
- postcss-loader: 用于补充 css 样式在各种浏览器的前缀,很方便,不需要手动写了
- eslint-loader: 用于检查代码是否符合规范,是否存在语法错误
- url-loader: 处理图片类型资源,可以根据图片的大小进行不同的操作,如果图片大小大于指定大小,则将图片进行资源打包,否则将图片转换为 base64 格式字符串,再把这个字符串打包到 JS 文件里
第一节课全部配置:
webpack
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// webpack 是基于nodeJS的,webpack配置就是module.exports抛出的对象,
module.exports = {
// context -- 上下文,项目打包的相对路径,默认值:process.cwd(),必须是绝对目录
context:process.cwd(), // 项目文件夹的根目录
// entry -- 入口 执行构建的入口,项目入口
// 从入口文件开始,将所有的依赖、代码等解析压缩到一个文件里
// entry 可以是字符串,数组,对象
entry:'./src/index.js', // --> 实际:entry:{ main:"./src/index.js", }
// entry:['./src/index.js','./src/other.js'], // 并非多入口,只是将两个模块的代码放在了一个文件里
// entry:{
// index:'./src/index.js',
// other:'./src/other.js',
// }, // 多入口,更改 --- output.filename:[name].js
// 意思是:从index.js文件开始执行的代码会在打包后存在index.js文件中
// 从other.js文件开始执行的代码会在打包后存在other.js文件中
// 输出
output:{
// path -- 构建后的文件资源存放的地方,必须是绝对路径
path:path.resolve(__dirname,"./dist"),
// filename -- 构建后的文件资源名字
// filename:"main.js", // 文件会被dist文件夹下的index.html引用,之后直接执行index.html文件,就可以使项目在浏览器上执行
filename:"[name]-[hash:16].js", // 多出口 配合 entry 多入口使用,不同的html文件引用不同的执行文件,就可以执行两套代码了
// 比如:other.html文件引用other.js文件,执行代码1;index.html文件引用index.js文件,执行代码2;
// hash:哈希值默认20位 hash:16 -- 16位哈希值
},
// 构建模式:none 生产模式--production 开发模式--development
mode:"development",
// 处理不认识的模块
module:{
rules:[
{
test:/\.css$/,
// loader 模块转换
// loader的执行顺序是从后往前
// css-loader 言简意赅 是把css模块的内容 加入到 js模块中去
// css in js方式
// style-loader 从js中提取css的loader 在html中创建style标签 把css的内容放在这个style标签中
use:["style-loader","css-loader"],
},
]
},
// 插件 这个机制原理是作用于webpack整个打包周期的
// CleanWebpackPlugin 清除冗余的打包文件
plugins:[new CleanWebpackPlugin()],
}