webpack五个核心概念
1 entry
2 output
3 loader
4 plugins
5 mode
6 *devServer
webpack初体验
1 安装 webpack
npm init
npm i webpack@4.41.6 webpack-cli@3.3.11\
开发环境打包:(以/src/index.js为入口文件)
webpack ./src/index.js -o ./build/built.js --mode=development\
生产环境打包:(以/src/index.js为入口文件)
webpack ./src/index.js -o ./build/built.js --mode=production
注意如果报错可以这样
然后
npm run ss即可
总结
1.webpack能处理js\json,不能处理css\img等资源.
2.生产环境和开发环境将es6模块化编译成浏览器能识别的模块化
3.生产环境比开发环境多一个压缩js代码
打包css样式资源
webpack.config.js
作用 指示webpack干那些活(运行webpack命令时会加载里面的配置)
所有构建工具都是基于nodejs平台运行的 模块化采用commonjs****
webpack.config.js
npm i css-loader@5
npm i style-loader@1
npm i less-loader@5
npm i less@3
//webpack。config。js
const { resolve }=require('path');
//webpack配置文件
//不同文件用不同loader处理
module.exports={
//入口文件
entry:'./src/index.js',
//输出
output:{
//输出文件名
filename:'built.js',
//输出路径
// __dirname nodejs变量 代表当前文件所在文件夹的绝对路径
path:resolve(__dirname,'build')
},
//loader的配置
module:{
rules:[
//详细的loader配置
{
//匹配那些文件
test:/\.less$/,
//使用那些loader进行处理
use:[ //use数组中loader执行顺序:从左到右从上到下依次执行
//创建style标签将js中的样式文件插入进行 添加到head中生效
'style-loader',
//将css变更成commonjs模块加载js中,里面是样式字符串
'css-loader',
//'less-loader', 将less编译为css
]
}
]
},
//plugins配置
plugins:[],
mode:'development'
//mode:'production'
}
打包html资源
loader 1下载 2使用(配置loader)
piugins 1下载 2引入 3使用
下载
npm i html-webpack-plugin@3
在文件开头的引入 const HtmlWebpackPlugin = require('html-webpack-plugin')
使用
plugins:[
//plugins的配置
//html-webpack-plugin
//功能:默认会创建空的html自带引入打包输出的css和js
new HtmlWebpackPlugin(
{ //复制'./src/index.html'文件内容并自带引入打包输出的css和js
template:'./src/index.html'
}
)
]
打包图片资源
loader 1下载 2使用(配置loader)
下载 url-loader@3和 file-loader@5
npm i url-loader@3 file-loader@5
这种方式处理不了html中的图片,如image标签的图片就处理不了 安装html-loader处理html中的图片
module:{
rules:[
//详细的loader配置
{
//匹配那些文件
test:/\.css$/,
//使用那些loader进行处理
use:[ //use数组中loader执行顺序:从左到右从上到下依次执行
//创建style标签将js中的样式文件插入进行 添加到head中生效
'style-loader',
//将css变更成commonjs模块加载js中,里面是样式字符串
'css-loader',
//'less-loader', 将less编译为css
]
},
//处理图片资源
{ //这种方式处理不了html中的图片,如image标签的图片就处理不了
test:/\.(jpg|png|gif)$/,
// use:['url-loader'] 多个loader用use数组配置,单个可以loader:'url-loader'
loader:'url-loader',
options:{
//图片小于8kb,就会被base64处理
//base64优点:减少请求数量(减轻服务器压力)
//base64缺点:图片体积会更大(文件请求速度更慢)
limit:8 * 1024
}
}
]
}
安装html-loader
npm i html-loader@0.5
module: {
rules: [
//详细的loader配置
{
。。。。。。
//处理图片资源
{ //这种方式处理不了html中的图片,如image标签的图片就处理不了
test: /\.(jpg|png|gif)$/,
// use:['url-loader'] 多个loader用use数组配置,单个可以loader:'url-loader'
loader: 'url-loader',
options: {
//图片小于8kb,就会被base64处理
//base64优点:减少请求数量(减轻服务器压力)
//base64缺点:图片体积会更大(文件请求速度更慢
limit: 8 * 1024,
/* 问题:url-loader默认使用es6模块化解析,
而html-loader引入图片是commonjs,
所以解析时会出问题 解析后的引入图片的url本来是
/xxx./xsda.png 结果成为[object Module]
解决:关闭url-loader的es6模块化,使用commonjs解析
*/
esModule:false,
//如果不想图片名字太长可以以下操作
//[hash:10] 取图片哈希的前十位
//[ext] 取文件原来的拓展名
name:'[hash:10].[ext]'
}
}, {
test: /\.html$/,
//处理html文件的img图片,(负责引入img,从而
//能被url-loader进行处理)
loader: 'html-loader',
}
]
},
打包其他资源
注意除了css js html 以外的资源 此时包含了图片文件 exclude:/.(css|js|html)$/
要想不包含图片文件 exclude:/.(css|js|html|jpg|png|gif)$/,
module: {
rules: [
{
.......
},
{//除了css js html jpg png gif以外的资源
exclude:/\.(css|js|html|jpg|png|gif)$/,
loader:'file-loader',
options:{
name:'[hash:10].[ext]'
}
}
]
devServer(热加载)
安装devServer
npm i webpack-dev-server@3
运行 npx webpack-dev-server
写在mode:'xxasdas',后
//开发服务器 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
//特点:只会在内存中打包
devServer:{
contentBase: resolve(__dirname, 'build'),
//启动gzip压缩
compress:true,
//端口号
port:4000
}
}
在浏览器用 http://localhost:xxxx/ 访问devServer
开发环境配置
打包命令直接 webpack 注意 如果报错 在package.json如下设置然后npm run saa效果等同于直接 webpack
可以设置各个类型资源的的输出目录
js直接在
output{
...,
//设置js文件输出到那个目录
filename:'xx/xx/x/xxx.js',
...,
}
其他类型资源在(css资源不需要设置因为css加入到了js文件中)
options:{
...,
//在jmgs文件夹下输出图片
outputPath:'imgs'
...,
}
构建环境介绍
提前css成单独文件
注意 此处如果css引入了图片等填写有路径的 打包后会报错 后文会解决
下载
npm i mini-css-extract-plugin
引入
const MiniCssExtractPlugin= require('mini-css-extract-plugin')
使用(要plugins和loader上同时注册)
plugins
plugins: [ //plugins的配置
//html-webpack-plugin
//功能:默认会创建空的html 自带引入打包输出的css和js
new HtmlWebpackPlugin({ //复制 './src/index.html' 文件内容并自带引入打包输出的css和js
template: './src/index.html'
}),
//注册
new MiniCssExtractPlugin({
//指定文件与指定路径
filename:'css/xxx.css'
})
],
loader
注意style-loader和MiniCssExtractPlugin.loader不共用
style-loader:创建style标签将js中的样式文件插入进行 添加到head中生效
MiniCssExtractPlugin.loader:提前js中css成单独文件 所以不需要创建style标签即不用使用style-loader
{ //匹配那些文件
test: /\.css$/,
//使用那些loader进行处理
use: [ //use数组中loader执行顺序:从左到右从上到下依次执行
//创建style标签将js中的样式文件插入进行 添加到head中生效
//'style-loader',
//注册
MiniCssExtractPlugin.loader,
'css-loader',
],
},
对输出css文件重命名与指定输出路径
new MiniCssExtractPlugin({
//指定文件与指定路径
filename:'css/xxx.css'
})
css的兼容性处理
需要postcss-loader和postcss-preset-env
安装 npm i postcss-loader@3 postcss-preset-env@6
引入loader
test: /\.css$/,
//使用那些loader进行处理
use: [ //use数组中loader执行顺序:从左到右从上到下依次执行
//创建style标签将js中的样式文件插入进行 添加到head中生效
//'style-loader',
//将css变更成commonjs模块加载js中,里面是样式字符串
MiniCssExtractPlugin.loader,
'css-loader',
//'less-loader', 将less编译为css
{ //帮助postcss找到package.json中的browserslist里面的配置,
//通过配置加载指定的css兼容性样式
loader:'postcss-loader',
options:{
ident:'postcss',
plugins:()=>[
require('postcss-preset-env')()
]
}
},
],
配置package.json中的browserslist
"browserslist":{
//开发环境--》设置node环境变量 在webpack。config。js文件头部写 porcess.env.NODE_ENV=development
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
//生产环境 默认是看生产环境
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
},
压缩css
安装插件 npm i optimize-css-assets-webpack-plugin@5
引入插件 const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin')
plugins中引入
plugins:[
new OptimizeCssAssetsWebpackPlugin()
]
js语法检查eslint
安装eslint-loader eslint
npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
在webpack引入
{
test:/\.js$/,
//不语法检查node_modules下js
exclude:/node_modules/,
loader:'eslint-loader',
options:{
//自动修错误
fix:true
}
}
只检测自己写的js代码 第三方库的不经常
设置检查规则:
在package.json中设置
airbnb规则
"eslintConfig":{
"extends:"airbnb-base"
}
要想不检查某一行代码可以在这一行代码的上一行加入此//eslint-disable-next-line注释
js兼容性处理eslint
babel-loader @babel/preset-env
问题:只能转换基本语法 如promise就不能转化 要想解决 需要再安装@babel/polyfillnpm i babel/polyfill
安装
npm i babel-loader@8 @babel/preset-env@7
npm i @babel/core
引入
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
options:{
//预设:指示babel做怎么邀的兼容性处理
presets:['@babel/preset-env']
}
}
解决只能转换基本语法的问题
问题:只能转换基本语法 如promise就不能转化
要想解决 需要再安装@babel/polyfillnpm i @babel/polyfill@7
再需要转换的js文件头引入import '@babel/polyfill';(缺点会将所有兼容性代码引入体积太大了)
终极解决方案:————按需引入兼容性代码(使用此方案不引入import ' @babel/polyfill ' )
安装npm i core-js@3
{
test:/\.js$/,
exclude:/node_modules/,
loader:'babel-loader',
options:{
//预设:指示babel做怎么邀的兼容性处理
presets:[
'@babel/preset-env',
//按需加载
{
useBuiltIns:'usage',
//指定core-js版本
corejs:{
version: 3
},
//指定浏览器做到兼容那个版本的浏览器
targets:{
'chrome':'60',
fireforx:'60',
ie:'9',
safari:'10',
edge:'17'
}
]
}
}
压缩html和js
js压缩
生产环境会自动压缩 把mode调成生产环境
mode:"porduction"
html压缩
在plugins下
plugins:[
//plugins的配置
//html-webpack-plugin
//功能:默认会创建空的html自带引入打包输出的css和js
new HtmlWebpackPlugin(
{ //复制'./src/index.html'文件内容并自带引入打包输出的css和js
template:'./src/index.html',
//压缩的配置项
minify:{
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true,
}
}
)
]
生产环境基本配置
当一个文件要被多个loader处理
一定要处理好loader顺序 先语法检查 在兼容性
enforce:'pre' //优先执行
const {resolve} = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
//入口文件
entry:"./src/js/index.js",
// 输出地址
output:{
filename:"js/built.js",
path:resolve(__dirname,'build')
},
//loader
module:{
rules:[
// 打包css
{
test:/\.css$/,
use:[
//提取css
MiniCssExtractPlugin.loader,
// 将 css 文件整合到 js 文件中
'css-loader',
//修改loader的默认配置需要写成对象的形式
{
//设置加载器
loader:'postcss-loader',
//配置options
options:{
postcssOptions:{
//插件
plugins:[
[
//指定环境
"postcss-preset-env",
{
browsers:'last 2 versions'
}
]
]
}
}
}
]
},
{
//打包less
test:/\.less$/,
use:[
MiniCssExtractPlugin.loader,
'css-loader',
//修改loader的默认配置需要写成对象的形式
{
//设置加载器
loader:'postcss-loader',
//配置options
options:{
postcssOptions:{
//插件
plugins:[
[
//指定环境
"postcss-preset-env",
{
browsers:'last 2 versions'
}
]
]
}
}
},
'less-loader'
]
},
{
//eslint
test:/\.js$/,
exclude:/node_module/,
loader:'eslint-loader',
// 优先执行
enforce: 'pre',
options:{
fix:true
}
},
{
test:/\.js$/,
exclude:/node_module/,
loader:'babel-loader',
options:{
// 预设:指示 babel 做怎么样的兼容性处理
presets:[
[
'@babel/preset-env',
{
//按需加载
useBuiltIns:'usage',
//指定core-js版本
corejs:{
verson:2
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
},
{
//打包图片
test:/\.(jpg|png|gif|webp)$/,
loader:'url-loader',
options:{
limit: 8*1024,
name:'[hash:10].[ext]',
outputPath:'imgs',
esModule:false
}
},
//处理html下的图片
{
test:/\.html$/,
loader:'html-loader',
options:{
esModule:false
}
},
//打包其他文件
{
exclude:/\.(js|css|less|html|jpg|png|gif)$/,
loader:'file-loader',
options:{
outputPath:'media'
}
}
]
},
plugins:[
//提取css文件
new MiniCssExtractPlugin({
filename:"css/built.css"
}),
//压缩css
new OptimizeCssAssetsWebpackPlugin(),
//打包html
new HtmlWebpackPlugin({
template:'./src/index.html',
//压缩html
minify:{
collapseWhitespace:true,
removeComments:true
}
})
],
// 开启生产模式就自动压缩js
mode:'production'
}
性能优化介绍
开发环境性能优化
- 1优化打包速度
- 2优化代码调试 生产环境性能优化
- 1优化打包速度
- 2优化代码性能
HMR
hot module replacement 热模块替换 作用当一个模块发生变化只会打包这一个模块而不是所有模块
devServer:{
....,
自动打开浏览器
open:true,
//开启hmr
hot:true
}
样式文件 style-loader 可以hmr js文件默认没有hmr,在index.js文件下写(之后监听非入口js文件)
module.hot.accept('./print.js',function(){
//会监听print.js的变化,
}
html文件:默认不能hmr 同时会导致问题:html不能热更新了 解决 修改entry入口
source-map(开发环境调试代码)
source-map 是一种提供源代码到映射代码的技术(如果后代们出错了,通过映射可以追溯到源代码)
devServer:{
....,
自动打开浏览器
open:true,
//开启hmr
hot:true
}
devtool:'
/*
*/
'
oneOf
rules:[
oneOf:[
{
test:
use:[]
}
]
]
缓存
这里是在缓存打包后的js文件,尽量少替换,客户端也就少下载了
babel缓存
文件资源缓存
在文件名加哈希值 这样当文件资源改动时 浏览器也会刷新 而不是使用强制缓存的内容
问题 因为js和css同时使用一个哈希值 如果重新打包会导致所有缓存失效但是我只改了一个文件
解决:fileName:
filename:"css/built.[contenthash:10].css"
tree shaking
目的 去除没有使用的代码,使体积更小 使用条件
- 1 必须使用es6模块化
- 2 mode开启production环境 在package.json设置
code spilt(代码分割)非常重要的
比如把一个文件分割成多个文件
多入口文件
第一种
第二种
- 单入口 只会把node包的文件单独打包
- 多入口 把node包的文件单独打包然后会把公共引入的文件单独打包(只因入一次的不会单独打包)
第三种
懒加载和预加载
懒加载 利用代码分割的思路 预加载
PWA:
渐进式网络开发应用程序(离线可访问)
安装 npm i work-webpack-plugin@5
引入 const WorkboxWebpackPlugin=require('worbox-webpack-plugin')\
注册
在入口文件inde。js下
多进程打包
下载 npm i thread-loader只有工作耗时较长才需要多进程打包
写在和loader同一个use数组上 如babel-loader 如果需要图片多线程就需要写在图片的loader的use数组(注意 loader的书写顺序)
externals
和plugin同级
然后再html文件中通过如cdn等使用script标签直接引入JQuery
dll
1 单独写一个xxxx.js 然后书写以下内容
命令
webpack --config xxx.js会把引用的库打包
2 webpackconfig。js下 书写
3 安装add-asset-html-webpack-plugin
npm i add-asset-html-webpack-plugin
然后引入 然后注册