Webpack
Webpack
是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
会以一个文件或多个文件作为打包的入口
Webpack五个核心概念
- entry(入口)
从哪个文件开始打包 - output(输出)
打包输出到哪里,如何命名 - loader(加载器)
webpack本身只处理js.json等资源,
其他资源需要借助loader,webpack才能解析 - plugins(插件)
扩展webpack的功能 - mode(模式)
开发模式:development
生产模式:productionwebpack配置文件
在项目根目录名字为webpack.config.js
// CommonJS语法 模块化规范
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development', // 模式
entry: path.join(__dirname,'src','index.js'),
output: {
path: path.resolve(__dirname,'dist'),//绝对路径
filename: 'bundle.js' //输出文件的名字
},
module: {
rules: []
},
plugins:[
new HtmlWebpackPlugin({
template: path.join(__dirname,'src', 'index.html'),
filename: 'index.html'
})
],
devServer: {
port: 8083,
static: path.join(__dirname,'dist')
}
}
webpack具体配置
下载Webpack
npm install webpack webpack-cli --save-dev
启动Webpack
npx webpack
npm i html-webpack-plugin --save-dev
可以把打包生成文件放在内存里面,自动编译不用每次都输入启动命令
npm i webpack-dev-server --save-dev
使用npm run webpack-dev-server
启动后,修改文件后会自动编译,不需要重复操作启动命令
可以在package.json
文件中,自定义启动命令
每次就可以通过npm run build
或npm run webpack-dev-server
启动项目
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server",
},
出口与入口
entry: path.join(__dirname,'src','index.js'),
output: {
path: path.join(__dirname,'dist'),
filename: 'bundle.js',
publicPath:'CDS地址' //可以配置CDS地址
},
可以配置多个入口文件,打包到不同js文件
entry: {
main: './src/a.js',
sub: './src/b.js'
},
output: {
path: path.join(__dirname,'dist'),
filename: '[name].js'
},
loader
loader 处理不同模块,不同类型文件
没有options
配置时,直接use:'loader名字'
,多个loader使用数组 use: ['style-loader','css-loader']
有options
配置时use是一个对象
loader:'xxxx'
只能使用一个loader,use可以使用多个
use: {
loader:'loader名字',
options:{}
}
use
执行顺序:从左到右(从小到上)
处理js资源
需要下载三个依赖
npm i @babel/core @babel/preset-env babel-loader --save-dev
处理css资源
css-loader
将css资源编译成CommonJS的模块到js
文件中
style-loader
将js中的css通过创建style标签添加到html文件中生效
npm i style-loader css-loader -D
module: {
rules: [
{
test:/.css$/,
use: [
'style-loader',//
{
loader:
options: {
modules: true,
},
}
]
}
]
}
处理less资源
npm i less less-loader -D
{
test:/\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
处理sass和scss资源
npm i sass sass-loader -D
{
test: /\.sass$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
],
},
处理Stylus资源
npm i stylus stylus-loader -D
{
test:/\.styl$/,
use: [
'style-loader',
'css-loader',
'stylus-loader'
]
}
处理图片资源
{
test: /\.(jpg|png|gif)$/,
type:"asset",
parser: {
dataUrlCondition:{
// 小于10kb转base64
maxSize: 10 * 1024
},
//输出路径
generator: {
filename:"static/images/[hash:10][ext][query]" //hash值取前10位
}
}
}
file-loader 打包图片
[] 语法 占位符
module: {
rules: [
{
test: /\.(jpg|png|gif)$/,
//use:'file-loader'
use: {
loader:'file-loader',
options:{
name:'[name]_[hash].[ext]'
outputPath:'images/'
}
}
}
]
},
url-loader 打包图片
转换成base64字符串
好处:dist少了.jpg图片文件,减少了图片的HTTP请求
坏处:图片过大加载完毕时间长
使用需要图片只有1-2kb转为base64, 图片很大 file-loader
单独生成
module: {
rules: [
{
test: /\.(jpg|png|gif)$/,
//use:'url-loader'
use: {
loader:'url-loader',
options:{
name:'[name]_[hash].[ext]'
outputPath:'images/'
limit:2048 //小于2M
}
}
}
]
},
处理字体图标
{
test: /\.(ttf|woff2)$/,
type:"asset/resource",
generator: {
filename:"static/icon/[hash][ext][query]"
}
}
处理其他资源
{
test: /\.(ttf|woff2)|map3|map4|avi$/, // 在此处添加资源类型
type:"asset/resource",
generator: {
filename:"static/icon/[hash][ext][query]"
}
}
样式兼容postcss-loader
兼容CSS样式,为css3样式添加前缀
npm i postcss postcss-loader -D
module.exports = {
Plugin:[
require('autoprefixer')
]
}
npm i autoprefixer -D
package.json中配置
"browerslist":[
"> 1%", //市场份额大于1%的浏览器
"last 2 version" //两个版本以上
],
Plugins 插件
HtmlWebpackPlugin 生成html
CleanWebpackPlugin 删除dist重新打包
template 模板
plugins:[
new HtmlWebpackPlugin({
template: path.join(__dirname,'src', 'index.html'),
filename: 'index.html'
}),
new CleanWebpackPlugin()
],
Eslint 可组装的JavaScript和jsx检查工具
配置文件很多种写法
.eslintrc
.eslinrc.js
.eslinrc.json
ESlint会查找和自动读取它们,所以以上配置文件只需要一个即可
package.json
中eslintConfig
:不需要创建文件,在原有文件基础上写
npm install eslint-webpack-plugin eslint --save-dev
CSS处理 mini-css-extract-plugin
css目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式
这样对与网站来说,会出现闪屏现象,用户体验不好
我们应该单独的css文件,通过link标签加载性能才好
npm install mini-css-extract-plugin -D
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
],
css压缩
npm i css-minimizer-webpack-plugin -D
优化webpack
1.提升开发体验
css和js合并成一个文件,并且有很多其他代码,此时如果运行出错那么提示的代码位置我们是看不懂的。 一旦开发将开发代码文件很多,那么很难去发现出错在哪里。
SourceMap(源代码映射)
是一个用来生产代码与构建后代码一一映射的文件方案。
它会生成一个xxx.map
文件,里面包含源代码和构建代码每一行、每一列的映射的关系。当构建后代码出错了,会通过xxx.map
文件,从构建后代码出错位置找到映射后源码出错位置,从而让浏览器提示源文件出错位置,帮助我们更快的找到错误根源。
通过查看webpack.devtool文档可知,SourceMap的值有很多情况。实际开发只需要关注两种情况即可:
1.开发模式 cheap-module-source-map
优点:打包编译速度快,只包含映射
缺点:没有映射列
module.exports = {
mode:'development',
devtool:'cheap-module-source-map'
}
2.生产模式 source-map
优点:包含行、列映射
缺点:打包编译速度慢
module.exports = {
mode:'development',
devtool:'source-map'
}
2.提升打包构建速度
开发时我们修改一个模块代码,Webpack默认会将所有模块全部重新打包编译,速度很慢。
所以我们需要做到修改某个模块代码,就只有这个模块代码需要重新打包编译,其他模块不变,这样打包速度就能很快。
HotModuleReplacement(HMR/热模块替换)
在程序运行中,替换、添加或删除模块,而无需加载整个页面
开发模式下
module.exports = {
devServer: {
host:'localhost',
port:'3000',
open:true,
hot:ftrue //开启HMR(默认值)
}
}
js需要做到
if(module.hot){
//判断是否支持热模块替换功能
module.hot.accept("./js/count") //count模块
}
实际项目中我们用到其它loader来实现vue-loader
、 react-hot-loader
oneOf
每个文件只能在其中一个loader配置处理
rules:[
{
//每个文件只能在其中一个loader配置处理
oneOf:[]
}
]
include/exclude
include
只处理某些文件
exclude
排除,除了某些文件以为其它文件都能处理
一般情况选择其中一个就可以了
{
test: /\.js$/,
loader:'babel-loader',
include: path.join(__dirname,'src'),
exclude: /node_modules/
},
Cache
打包时js文件都要经过Eslint检查和Babel编译 ,速度比较慢
我们可以缓存之前的Eslint检查 和Babel编译结果,这样第二次打包时速度就会更快
对Eslint检查 和Babel编译结果进行缓存
{
test: /\.js$/,
loader:'babel-loader',
exclude: /node_modules/,
options: {
cacheDirectory:true,//开启babel缓存
cacheCompression:true//关闭缓存压缩
}
},
Thead
当项目越来越庞大时,打包速度越来越慢,甚至需要一个下午才能打包出来代码,这个速度比较慢的
我们想要继续提升打包速度,其实就是要提升js的打包速度,因为其他文件比较少
而对js文件处理主要是eslint、babel、Terser三个工具,所以我们要提升他们的速度
我们可以开启多进程同时处理js文件,这样速度就比之前的进程打包更快
多进程打包:开启电脑的多个进程同时干一件事,速度更快
需要注意:请仅在特别耗时到操作中使用,因为每个进程启动就有大约600ms左右的开销
我们启动进程的数量就是吗CPU的核数
1.如何获取CPU的核数,因为每个电脑不一样
cosnt os = require('os')
const threads = os.cpus().length;
npm i thread-loader -D
{
test: /\.js$/,
include: path.join(__dirname,'src'),
use:[
loader:'babel-loader',
options:{
works: threads,
}
]
},
new ESLintWebpackPlugin({
context: path.resolve(__dirname, './src'),
exclude: 'node_modules',//默认值
threads //开启多进程和设置进程数量
})
压缩js,内置的不用下载
const TerSerWebpackPlugin = require('terser-webpack-plugin')
new TerSerWebpackPlugin({
parallel:threads //开启多进程和设置进程数量
})
3.减少代码体积
Tree Shaking
Tree Shaking是一个术语,通常用于描述移除JavaScript中没有用上的代码。
没有处理的话我们打包时会引入整个库,但实际上可能我们只用上极小部分功能,这样整个库打包体积就太大了
注意:它依赖 ES Module
Webpack 默认开启了这个功能
babel
为编译的每个文件都插入了辅助代码,使代码体积过大
Babel 对一些公共方法使用了非常小的辅助代码,比如 _extend,默认情况下会被添加到每一个需要他的文件中
可以将这些辅助代码作为一个独立模块,来避免引入
禁用了Babel自动对每个文件的runtime注入,而是引入并且使用所有辅助代码从这里引用
npm i @babel/plugin-transform-runtime -D
{
test: /\.js$/,
loader:'babel-loader',
include: path.join(__dirname,'src'),
plugin:[' @babel/plugin-transform-runtime']
},
图片压缩
npm i image-minimizer-webpack-plugin imagemin -dataUrlCondition
无损压缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-svgo -D
有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
code Split
js会打包到一个文件,体积太大
分割文件,生成多个js文件
按需加载 需要哪个文件就加载哪个文件
entry: {
main: './src/a.js',
sub: './src/b.js'
},
output: {
path: path.join(__dirname,'dist'),
filename: '[name].js'
},
4.优化代码运行性能
未完待更新