初始化项目文件:
npm init -y
安装webpack and webpack-cli
npm i webpack webpack-cli -D or yarn add webpack webpack-cli -D
文件根目录下创建 webpack.config.js 文件
src 是 所有开发文件的目录
dist 是打包后的文件
webpack.config.js:
const path = require("path");
const{resolve}=require('path');
const reslovePath = _path =>path.resolve(__dirname,_path);
module.exports ={
// 入口文件
entry:reslovePath('./src/main.js'),
// 输出文件
output:{
path:reslovePath('dist'),
filename:'[name].bundle.js',
clean:true, //清理dist
},
// //加载器
module:{
rules:[
]
},
// // 插件
plugins:[
],
mode:'development'
}
开发模式介绍
- 编译代码,使浏览器能够识别
- 开发的时候我们有样式资源,图片资源等,webpack 不能处理这些资源,所以我们要加载配置 来编译这些资源
- 代码质量检查,树立代码规范
loader:
css-loader:
yarn add css-loader style-loader -D
rules:[
{
test: /\.css$/, //只检测 css 为后缀的文件
use: [
// 执行顺序 从下到上
'style-loader',//style-loader 将js 中的css通过创建style 标签添加
// html 文件中生效
'css-loader' //将css 资源编译成commonjs的模块到js
]
}
]
less-loader
yarn add less less-loader -D
{
test: /\.less$/,
use:['style-loader','css-loader','less-loader']
}
图片资源
{
test:/\.(png|jpe?g|gif|svg|webp)/,
type:'asset',
parser:{
dataUrlCondition:{
//小于10 kb 转为 base64
// 优点减少请求数量 缺点 体积变大
maxSize:10 * 1024
}
generator: {
filename: 'images/[hash:8][ext][query]'
}
}
文字资源
{
test: /\.(ttf|eot|woff|woff2|otf)$/,
type:'asset/resource',
generator: {
filename: 'fonts/[hash:8][ext][query]'
}
},
配置babel
yarn add babel-loader @babel/core @babel/preset-env -D
{
test: /\.js$/,
exclude: /node_modules/,
loader:'babel-loader',
},
创建 babel.config.js 文件
module.exports ={
//智能预设 ,编译es6 语法
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-proposal-object-rest-spread']
}
处理html 资源
yarn add html-webpack-plugin -D
public/index.html
const ESLintPlugin = require('eslint-webpack-plugin');
plugins:[
new ESLintPlugin({
// 检测 哪些文件
context:reslovePath('./src')
}),
+ new HtmlWebpackPlugin({
+ template: resolve('/public/index.html'),
+ filename:'index.html'
+ })
],
搭建开发服务器
yarn add webpack-dev-server -D
npx webpack sever
devServer:{
host:'localhost',
port:'3000',
open:true
},
css单独文件
yarn add mini-css-extract-plugin -D
// css 单独文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
//loader
{
test: /\.css$/, //只检测 css 为后缀的文件
use: [
// 执行顺序 从下到上
MiniCssExtractPlugin.loader,
'css-loader'
]
}
{
test: /\.less$/,
use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']
},
//Plugin
new MiniCssExtractPlugin({
filename:'css/[name].bundle.css'
})
开发模式:
在根目录下面创建 config文件,将webpack.congin.js 文件复制两份
绝对路径需要回退一层目录
dev:
output:{
path:reslovePath('../dist'),
// path:undefined, //开发模式没输出
filename:'js/[name].bundle.js',
// clean:true, //清理dist
// assetModuleFilename: 'images/[hash][ext][query]'
},
prod:
不需要 devServer
mode:'development'
package.json 配置(快速启动)
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npm run dev",
"dev":"webpack server --config ./config/webpack.dev.js",
"build":"webpack --config ./config/webpack.prod.js "
},
css兼容性处理(前缀)
yarn add postcss postcss-loader postcss-preset-env -D
{
test: /\.css$/, //只检测 css 为后缀的文件
use: [
// 执行顺序 从下到上
MiniCssExtractPlugin.loader,//style-loader 将js 中的css通过创建style 标签添加 html 文件中生效
'css-loader' ,//将css 资源编译成commonjs的模块到js
{
loader: 'postcss-loader',
options:{
postcssOptions:{
plugins:[
'postcss-preset-env', //能解决大部分兼容问题
]
}
}
}
]
},
{
test: /\.less$/,
use:[MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options:{
postcssOptions:{
plugins:[
'postcss-preset-env', //能解决大部分兼容问题
]
}
}
},
'less-loader']
},
package.json //告诉浏览器兼容到那个版本
"browserslist":[
"last 2 version", // 所有浏览器最近的两个版本
">1%", // 覆盖百分之九十九的浏览器
"not dead"
]
css压缩
npm i css-minimizer-webpack-plugin --save-dev
// css 压缩
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
plugins:[
new CssMinimizerPlugin()
]
webpack优化
source-map:
Source-map(源代码映射)是一个生成源代码与构建后的代码--映射的文件方案
他会生成 一个 xxx.map 的文件,里面包含源代码于构建后的代码,每一行,每一列的关系,当构建后的代码出错了,会通过 xxx.map 文件,从构建后代码出错位置,找到出错后源代码位置,从而让浏览器找源文件的 出错位置,帮助我们快速找到出错的根源
开发:development
优点:打包编译速度快,只包含行映射,
缺点:没有列映射
devtool: 'cheap-module-source-map',// devtool:'inline-source-map',
生产:production
优点:包含 行/列 映射
缺点:打包编译速度更慢
devtool: 'source-map',// devtool:'inline-source-map',
OneOf:
打包时,每一个文件都会经过 loader 处理,虽然因为 test 正则原因实际没有处理上,但是都要过一遍,会比较慢,
匹配上一个 loader ,剩下的就不会匹配
rules:[
{
oneOf[
{test: /\.css$/,use:'...'}
......
]
}
]
Include/Exclude
开发是我们使用的第三方库和插件,所有的文件都下载到 node_modules 中了,而这些文件是不需要编译的直接使用
所以我们在编译的时候需要排除 node_modules 下面的文件
Include: 包含 只处理 xxx文件
Exclude:排除,除了xxx 文件 其他文件都处理
{
test: /\.js$/,
exclude: /node_modules/,
loader:'babel-loader',
},
Cache
每次打包 js 文件都要经过 Eslint 检查 和 Babel 编译 速度比较慢
我们可以缓存之前的 Eslint检查 和 Babel 编译结果,这样第二次打包速度就会变快
Eslint检查 和 Babel 编译缓存
{
test: /\.js$/,
exclude: /node_modules/,
loader:'babel-loader',
options:{
cacheDirectory:true, // 开启babel 缓存
cacheCompression:false // 关闭缓存文件压缩
}
},
new ESLintPlugin({
// 检测 哪些文件
context:reslovePath('./src'),
exclude:'node_modeules',
cache:true,
cacheLocation:reslovePath('../node_modeules/.cache/eslints'),
}),
多进程打包 Thread
npm i thread-loader --save-dev
当项目却来越大时,打包速度越来越慢
我们想要继续提升打包速度,其实就是提升js 的打包速度,应为其他文件都比较少,而对js 文件处理的只要是 eslint babel Terser 三个工具,所以我们要提升他们的打包速度,
我们可以开启多进程处理js 文件。
需要注意:需要在特别耗时 的项目中使用, 每个进程 启动的时间是 600ms
获取cpu 的核心数:
const os = require('os');
console.log(os.cpus().length);
const os = require('os');
const threads = os.cpus().length;
{
test: /\.js$/,
exclude: /node_modules/,
use:[
+{
+ loader:'thread-loader', // 开启多进程
+ options:{
+ workers:threads // 进程数量
+ }
+ },
{
loader:'babel-loader',
options:{
cacheDirectory:true, // 开启babel 缓存
cacheCompression:false // 关闭缓存文件压缩
}
}
]
},
//plugin
new ESLintPlugin({
// 检测 哪些文件
context:reslovePath('./src'),
exclude:'node_modeules',
cache:true,
cacheLocation:reslovePath('../node_modeules/.cache/eslints'),
+ threads, // 开启多进程
}),
压缩js
webpack 已内置插件
//js 压缩 内置
const TerserWebpack = require('terser-webpack-plugin');
new TerserWebpack({
parallel:threads // 开启多进程
})
减少代码体积
Tree Shaking
开发时定义了一些工具函数库,或者是引应的第三方工具库 或组件 库
如果没有特殊处理的话,我们打包会引入整个库,但是也许我们只是用了 极少部分
three shaking 是一个术语,通常用于描述移除 javascript 没有使用的代码、
他依赖于 ES Module
webpack 默认配置了这项功能,无需其他配置
Babel
Babel 为每一个编译文件 都插入了辅助代码,使代码体积过大!
Babel 对一些公共方法 使用了非常小的辅助代码,比如_extend。默认情况下会被添加到每一个需要他的文件,
你可以将这些辅助代码作为一个独立模块,来避免重复引入。
@babel/plugin-transform-runtime:禁用了Babel 自动对每个文件的 runtime注入,而是引入
@babel/plugin-transform-runtime 并且使用辅助代码 从这里引入
npm install -D @babel/plugin-transform-runtime
{
test: /\.js$/,
exclude: /node_modules/,
use:[
{
loader:'thread-loader', // 开启多进程
options:{
workers:threads // 进程数量
}
},
{
loader:'babel-loader',
options:{
cacheDirectory:true, // 开启babel 缓存
cacheCompression:false ,// 关闭缓存文件压缩
+ plugins:['@babel/plugin-transform-runtime'] //减少代码体积
}
}
]
},
Image Minimizer 图片压缩
开发中 如果项目中 引入了较多的图片文件,那么图片体积变大,请求速度比较慢
我们可以对图片进行压缩,减少图片体积
image-minimizer-webpack-plugin 用来压缩图片插件
npm install image-minimizer-webpack-plugin --save-dev
还有两个包下载
无损压缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev
有损压缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
代码分割(多入口)
module.exports ={
//entry:'./src/main.js', //单入口
entry:{
app:'./src/index.js',
main:'./src/main.js
}
mode:'production',
output:{
path:reslovePath('../dist'),
filename:'js/[name].bundle.js',
},
// //加载器
module:modules,
plugins:plugins,
};
多入口提取公共模块
optimization:{
splitChunks: {
chunks: 'all', // 对所有模块进行分割
// 一下是默认配置
// minSize: 20000, // 分割代码最小的 大小
// minRemainingSize: 0, // 类似于 minSize 最后确保提取的文件大小不能为0
// minChunks: 1, //至少被引用的次数
// maxAsyncRequests: 30, // 按需加载时 并行加载的文件最大数量
// maxInitialRequests: 30, // 入口 js 文件 最大并行请求数量
// enforceSizeThreshold: 50000, // 超过 50kb 一定会单独打包(此时忽略 minRemainingSize、maxAsyncRequests、maxInitialRequests)
// cacheGroups: { // 组, 哪些模块要打包到一个组
// defaultVendors: {
// test: /[\\/]node_modules[\\/]/, // 需要打包到一起的模块
// priority: -10, // 权重 越大越高
// reuseExistingChunk: true, // 如果当前 chunk 包含 以从主 bundle 中拆分的 模块,则 他 将被重用,而不是生成新的模块
// },
// default: { // 其他没有写的配置 会使用下面默认配置
// minChunks: 2,
// priority: -20,
// reuseExistingChunk: true,
// },
// },
cacheGroups: { // 组, 哪些模块要打包到一个组
default: { // 其他没有写的配置 会使用下面默认配置
minSize: 0,
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
}
我们写一个公共方法,minSize 设置为0 ,
count 为方法
进行打包: npm run build
此时就多出来一个 方法模块
Preload、Prefetch
preload:告诉浏览器 立即加载资源
prefetch:告诉浏览器 在空闲的时候加载资源
他们的共同点:都是只会加载资源 并不会执行、都有缓存
他们的区别:
preload加载优先级高,prefetch 加载优先级低
preload 只能加载当前页面的资源
prefetch 可以加载当前页面的资源,也可以加载下一页的资源
npm install --save-dev @vue/preload-webpack-plugin
Core-js
过去我们使用 babel 对 js 代码做兼容性处理,其中使用 @babel/preset-env 智能预设 处理兼容性问题
它能将 es6 的 语法进行编译转换,比如箭头函数 、 。。。 运算符,但是 如果是 async promise 它就没办法处理
core-js 是专门处理 es6 以及以上的api的polyfill
polyfill 翻译过来就是 垫片,补丁,就是社区上提供的代码,让我们不兼容某些新特性的浏览器上,使用该特性