核心概念
enrty
- 指定打包的入口文件
- 文档:https://www.webpackjs.com/concepts/entry-points/
//单⼊口 SPA,本质是个字符串
entry:{
main: './src/index.js'
}
// ==相当于简写===
entry:"./src/index.js"
//多⼊口 entry是个对象
entry:{
index:"./src/index.js",
login:"./src/login.js"
}
output
//单入口文件
output: {
filename: "bundle.js",//输出文件的名称
path: path.resolve(__dirname, "dist")//输出⽂件到磁盘的⽬录,必须是绝对路径
},
//多入⼝的处理
output: {
filename: "[name][chunkhash:8].js",//利用占位符,文件名称不要重复
path: path.resolve(__dirname, "dist")//输出文件到磁盘的⽬录,必须是绝对路路径
},
[chunkhash:8] : 指定hash为8位
[name] 表示占位符,输出的文件名字和入口文件名字对应
publicPath
- 可以指定了打包后的静态资源的基础路径,也就是前缀,会在静态资源加上指定的前缀路径
- 影响到在浏览器中访问这些静态资源时的路径
mode
- 文档:https://www.webpackjs.com/concepts/mode/
- mode用来指定当前的构建环境
- production
- development
- none
- 设置mode可以⾃动触发webpack内置的函数,达到优化的效果
开发阶段的开启会有利于热更更新的处理,识别哪个模块变化
生产阶段的开启会有帮助模块压缩,处理副作用等一些功能
记住,只设置 NODE_EN,则不会自动设置 mode。
development:
- process.env.NODE_ENV 的值设为 development
- 默认开启以下插件,充分利用了持久化缓存。参考基于 webpack 的持久化缓存方案
NamedChunksPlugin:以名称固化 chunk idNamedModulesPlugin:以名称固化 module id
production:
- process.env.NODE_ENV 的值设为 production
- 默认开启以下插件,其中
SideEffectsFlagPlugin和UglifyJsPlugin用于 tree-shaking
FlagDependencyUsagePlugin:编译时标记依赖FlagIncludedChunksPlugin:标记子chunks,防子chunks多次加载ModuleConcatenationPlugin:作用域提升(scope hosting),预编译功能,提升或者预编译所有模块到一个闭包中,提升代码在浏览器中的执行速度NoEmitOnErrorsPlugin:在输出阶段时,遇到编译错误跳过OccurrenceOrderPlugin:给经常使用的ids更短的值SideEffectsFlagPlugin:识别 package.json 或者 module.rules 的 sideEffects 标志(纯的 ES2015 模块),安全地删除未用到的 export 导出- SideEffecs:副作用
UglifyJsPlugin:删除未引用代码,并压缩- Uglify:糟蹋、丑化, 就是说把js文件进行压缩 (压缩之后会乱码,也就说把文件丑化了)
loader
模块解析,模块转换器,用于把模块原内容按照需求转换成新内容。 webpack是模块打包⼯具,而模块不仅是js,还可以是css,图片或者其他格式 但是webpack默认只知道如何处理理js和JSON模块,那么其他格式的模块处理,和处理方式就需loader了
- 因为webpack不支持css、png、ts、jsx、vue等,因此需要借助loader来处理这些模块,让浏览器支持和识别这些模块
注意:loader有顺序,从右到左,从下到上
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
常见的loader
style-loader css-loader less-loader sass-loader //处理编译sass文件,转换为css文件 ts-loader //将Ts转换成js babel-loader//转换ES6、7等js新特性语法 file-loader//处理理图⽚片⼦子图 eslint-loader
raw-loader
- 它允许你以字符串的形式导入文件。 (简单来说:加载文件原始内容)(utf-8)
- utf-8是一种编码方式,可以表示unicode标准中的任何字符
file-loader
loader: file-loader:处理静态资源模块 (字体、图片啦等等) loader: file-loader 原理是把打包⼊口中识别出的资源模块,移动到输出目录,并且返回⼀地址名称
- file-loader 返回的是图片的url,解析为一个url,并将该文件发出到输出目录中。
所以我们什时候⽤file-loader呢? 场景:就是当我们需要模块,仅仅是从源代码挪移到打包目录,就可以 使⽤用file-loader来处理理,txt,svg,csv,excel,图⽚资源啦等等
npm install file-loader -D
module: {
//test:标识应转换哪个或哪些文件
//use:指示应使用哪个加载程序loader进行转换
rules: [
//处理图片
{
test: /\.(png|jpe?g|gif)$/,
//use使⽤⼀个loader可以⽤对象,字符串,两个loader需要用数组
use: {
loader: "file-loader",
// options额外的配置,⽐如资源名称
options: {
// placeholder 占位符 [name]资源模块的名称
// [ext]资源模块的后缀
// https://webpack.js.org/loaders/fileloader#
placeholders
name: "[name]_[hash].[ext]",
//打包后的存放位置
outputPath: "images/",
publicPath: "../images"
}
},
//处理字体
{
test: /\.(eot|ttf|woff|woff2|svg)$/,
use: "file-loader"
}
}
]
},
url-loader
url-loader内部使用了file-loader,所以可以处理file-loader所有的事情,但是遇到jpg格式的模块,会把该图片转换成base64格式字符串串,并打包到js。对小体积的图片比较合适,大图片不合适。
与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值时返回其 publicPath,小于阈值时返回文件 base64 形式编码 (处理图片和字体)
- 大于limit时调用file-loader对图片进行处理。
转换为base64的好处:
1、提升性能: 网页上的每一个图片,都是需要消耗一个 http 请求下载而来的, 图片的下载始终都要向服务器发出请求,要是图片的下载不用向服务器发出请求,base64可以随着 HTML 的下载同时下载到本地.减少https请求。
2、加密: 让用户一眼看不出图片内容 , 只能看到编码。
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/,
use: {
loader: "url-loader",
options: {
name: "[name]_[hash].[ext]",
outputPath: "images/",
//小于2048,才转换成base64
//1024 = 1kb
limit: 2048
}
}
}
]
},
css-loader 和 style-loader
- 文档:https://www.webpackjs.com/loaders/style-loader/
- css-loader :分析css模块之间的关系,并合成一个css (打包css文件,编译css文件)
- style-loader :会把css-loader生成的内容,将css插入到页面的style标签
- 建议将
style-loader与css-loader结合使用
npm install style-loader css-loader -D
postcss-loader
- 文档:<https://www.webpackjs.com/loaders/postcss-loader/
- 参考文章使用postcss-loader添加前缀:https://www.jianshu.com/p/15d51e796dca
扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀 (样式自动添加前缀)
- 如果我们自己手动添加前置是很麻烦的,因此我们可以借助postcss-loader来自动添加前缀
npm i postcss-loader autoprefixer -D
{
test: /\.less$/,
use: [
"style-loader",
"css-loader",
"less-loader",
{
loader: "postcss-loader",
options: {
plugins: () => [
require("autoprefixer")({
overrideBrowserslist: ["last 2 versions",
">1%"]//autoprefixer新版本中browsers替换成 overrideBrowserslist
})
]
}
}
]
},
-
新建postcss.config.js
或者我们也可以在postcsss.config.js来配置
module.exports = {
plugins: [
require("autoprefixer")({
overrideBrowserslist: ["last 2 versions", ">1%"]
})
]
}
- 这时候webpack.config.js就不需要写额外配置了
{
test: /\.css$/,
use:["style-loader", "css-loader",'postcss-loader']
}
module
module是webpack中非常重要的模块,定义module模块规则来去解析对应的模块资源
- 文档:https://www.webpackjs.com/configuration/module/
- 模块,在 Webpack ⾥⼀切皆模块,⼀个模块对应着⼀个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
module:{
rules:[
{
test:/\.xxx$/,//指定匹配规则
use:{
loader: 'xxx-load'//指定使⽤用的loader
}
}
]
}
-
当webpack处理理到不认识的模块时,需要在webpack中的module处进行 配置,当检测到是什么格式的模块,使用什么loader来处理理。
-
rules中,oneOf作用是什么?
- oneOf可以提升性能
- 每个不同类型的文件在loader转换时,会遍历module中rules中所有的loader, 而oneOf则是当有一个loader能够进行转换的时候,就不再遍历
watch (监听文件)
webpack 可以监听文件变化,当它们修改后会重新编译
- 轮询判断文件的最后编辑时间是否变化,某个文件发生了变化,并不会立刻告诉监听者,先缓存起来
-
webpack开启监听模式,有两种
ignored:忽略的文件或者目录
poll :轮询 (指定毫秒为单位进行轮询)
aggregateTimeout: 总超时
//在package.json文件里配置启动webpack命令式 带上--watch 参数,启动监听后,需要⼿动刷新浏览器
scripts:{
"watch":"webpack --watch"
}
//在配置文件里设置 watch:true
watch: true, //默认false,不开启
//配合watch,只有开启才有作⽤
watchOptions: {
//默认为空,不监听的文件或者目录,支持正则
ignored: /node_modules/,
//监听到文件变化后,等300ms再去执行,默认300ms,
aggregateTimeout: 300,
//判断文件是否发生变化是通过不停的询问系统指定文件有没有变化,默认每秒问1次
poll: 1000 //ms
}
Plugins
- 文档:https://webpack.docschina.org/concepts/plugins/
- https://webpack.docschina.org/configuration/plugins/
plugin 可以在webpack运行到某个阶段的时候,帮你做一些事情,类似于生命周期的概念 扩展插件,在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。 作用于整个构建过程
HtmlWebpackPlugin
- 文档:https://webpack.docschina.org/plugins/html-webpack-plugin/
- github文档查看具体配置:https://github.com/jantimon/html-webpack-plugin#options
htmlwebpackplugin会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中。
npm install --save-dev html-webpack-plugin
配置:
title: 用来⽣生成页面的 title 元素 filename: 输出的 HTML 文件名,默认是 index.html, 也可以直接配置带有子目录。 template: 模板文件路路径,支持载器,比如 html!./index.html inject: true | 'head' | 'body' | false ,注入所有的资源到特定的 template 或者 templateContent 中,如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body 元素的底部,'head' 将放置到 head 元素中。 favicon: 添加特定的 favicon 路路径到输出的 HTML 文件中。 minify: {} | false , 传递 html-minifier 选项给 minify 输出 hash: true | false, 如果为 true, 将添加⼀一个唯⼀一的 webpack 编译 hash 到所有包含的脚本和 CSS ⽂文件,对于解除 cache 很有用。 cache: true | false,如果为 true, 这是默认值,仅仅在⽂文件修改之后才会发布文件。 showErrors: true | false, 如果为 true, 这是默认值,错误信息会写入到 HTML 页面中 chunks: 允许只添加某些块 (比如,仅仅 unit test 块) chunksSortMode: 允许控制块在添加到页面之前的排序方式,支持的 值:'none' | 'default' | {function}-default:'auto' excludeChunks: 允许跳过某些块,(比如,跳过单元测试的块)
plugins:[
new HTMLWebpackPlugin({
title:'首页',
template:'./src/index.html',
inject:true,
chunks:['index'], //添加模块
filename:'index.html'
}),
new HTMLWebpackPlugin({
title:'登录',
template:'./src/index.html',
inject:true,
chunks:['login'],
filename:'login.html'
}),
}
clean-webpack-plugin
- github:https://github.com/johnagan/clean-webpack-plugin
- 目录清理: 默认情况下,会删除webpack之前打包出来的文件 (也就是说把上一次dist文件夹删除掉)
npm install --save-dev clean-webpack-plugin
mini-css-extract-plugin
- 文档:https://webpack.js.org/plugins/mini-css-extract-plugin/
- 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代extract-text-webpack-plugin)
- 该插件将CSS提取到单独的文件中
注意:这里使用了contenthash : 由文件内容产生的hash值,内容不同产生的contenthash值也不一样。
const MiniCssExtractPlugin = require("mini-css-extractplugin");
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
new MiniCssExtractPlugin({
filename: "[name][chunkhash:8].css"
})
devtool
devtool属性
eval:速度最快,使用eval包裹模块代码, source-map: 产生.map 文件 (这个map文件会和原始文件做一个映射) cheap: 低消耗打包,什么叫低消耗,就是打包的时候map文件,不会保存原始代码的列位置信息,只包含行位置信息 (较快,不用管列的信息,也不包含loader的sourcemap) Module:第三方模块,包含loader的sourcemap(比如jsx to js ,babel的sourcemap) inline: 将.map 作为DataURI嵌入bundle,不单独生成.map 文件
配置推荐
- 一般开发环境设置就好了,便于调试
devtool:"cheap-module-eval-source-map",// 开发环境配置
//线上不推荐开启 (否则用户可以看到源代码,这时候对业务代码就产生风险了)
devtool:"cheap-module-source-map", // 线上生成配置
sourceMap
源代码与打包后的代码的映射关系
(一个js文件或css文件产生对应的映射.nap文件)
- 启动sourceMap的好处就是开发时候,当我们代码发生错误的时候,会帮我们指向哪个文件哪一行发生错误,因此做调试的时候很方便
在dev模式中,默认开启,关闭的话 可以在配置文件里
devtool:"source-map" //开启sourceMap
devtool:"none" //关闭none
devServer
提升开发效率的利器 每次改完代码都需要重新打包一次,打开浏览器,刷新一次,很麻烦 我们可以安装使用webpackdevserver来改善这块的体验
npm install webpack-dev-server --save-dev
修改下package.json
"scripts": {
"server": "webpack-dev-server"
},
在webpack.config.js配置
- dist:distribution的缩写 ,分发、分布、发行版的意思
devServer: {
contentBase: "./dist", //指定访问入口 (会找到dist目录的index.html文件), 默认会指向dist输出文件路径
open: true,
port: 8081
},
启动:
- 注意: (启动之后会发现没有dist目录了,这是为什么呢??)
- devserver会先打包,但是打包后不会直接放在本地的资源,会放到内存里,提升打包速度
- 所以并不会输出打包后的dist文件夹 ,⽽是放到内存中!!!!
npm run server
跨域:
前后端分离,直接获取数据会跨域,上线后我们使用nginx转发,开发期间,webpack就可以搞定这件事
- 修改webpack.config.js 设置服务器器代理理
devServer: {
contentBase: "./dist",
open: true,
port: 8081,
proxy: {
"/api": {
target: "http://localhost:9092"
}
}
},