Webpack学习笔记
第1章 Webpack简介
学习视频:https://www.bilibili.com/video/BV1e7411j7T5?p=1&spm_id_from=pageDriver
1.1Webpack是什么
Webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler).
在Webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理.
它根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle).
1.2Webpack五个核心概念
-
1.2.1 Entry
-
1.2.2 Output
-
1.2.3 Loader
-
1.2.4 Plugins
-
1.2.5 Mode
第2章webpack初体验
2.1 webpack打包样式资源(css,less)
/*
webpack.config.js webpack的配置文件
作用指示:webpack 干哪些活 (当你运行webpack 指令时,会加载里面的配置)
所有构建工具都是基于nodejs平台运行的~ 模块化默认采用commonjs.
*/
// resolve 用来拼接绝对路径的方法
const { resolve } = require('path');
module.exports = {
// webpack配置
// 入口起点
entry: './src/index.js',
output: {
// 输出文件名
filename: 'built.js',
// 输出路径
// __dirname nodejs的变量,代表当前文件的目录绝对路径
path: resolve(__dirname, 'build'),
},
// loader的配置
module: {
rules: [
// 详细loader配置
{
test: /\.css$/,
use: [
// use数组中loader执行顺序:从右到左,从下到上依次执行
// 创建style标签,将js中的样式资源插入进去,添加到head中生效
'style-loader',
// 将css文件变成commonjs模块加载js中,里面内容是样式字符串
'css-loader',
],
},
{
test:/.\less$/,
use:[
'style-loader',
'css-loader',
// 将less文件编译成css文件
// 需要下载less-loader和 less
'less-loader'
]
}
],
},
// plugins 的配置
plugins: [],
// 模式
mode: 'development',
// mode:'production'
};
2.2 webpack打包html资源
/*
loader: 1.下载 2.使用(配置loader)
plugins:1.下载 2.引用 3.使用
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
module:{
rules:[
// loader配置
]
},
plugins:[
// plugins的配置
// html-webpack-plugin
// 功能:默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
new HtmlWebpackPlugin({
// 复制'./src/index.html' ,并自动引入打包输出的所有资源(JS/CSS)
template:'./src/index.html'
})
],
mode:'development'
};
2.3 打包图片资源
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.less$/,
use: [
// 要使用多个loader处理用use
'style-loader',
'css-loader',
'less-loader',
],
},
{
// 问题:默认处理不了html中的img图片 (webpack5时省略该图片loader配置,能默认处理而不需要该处配置)
// 处理图片资源
test:/\.(jpg|png|gif)$/,
// webpack5已经弃用url-loader
// 使用一个loader
// 下载url-loader file-loader
loader:'url-loader',
options:{
// 图片大小小于8kb,就会被base64处理
// 优点:减轻请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit:8*1024,
// 问题:因为url-loader默认使用es6模块化解析,而htm-loader引入图片是commonjs
// 解析时会出问题:[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule:false,
// 给图片重命名,[hash:10]:取图片的hash的前10位,[ext]:取文件原来扩展名
name: '[hash:10].[ext]'
}
},
{
test:/\.html$/,
// 处理html文件的img图片(如则引入img,从而能被url-loader处理)
loader:'html-loader'
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
// mode:'production'
};
2.4 打包其他资源(字体)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口
entry: './src/index.js',
// 出口
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
// loader配置
module: {
rules: [
// 打包css
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
// 打包其他资源(除了html/css/js以外的资源)
{
// 排除css/js/html
// exclude: /\.(css|js|html)$/,
// webpack file-loader弃用
//loader:'file-loader'
test:/\.ttf|eot|woff2?$/, // webpack5打包字体资源
type: 'asset/resource',
generator: {
filename: 'font/[name].[hash:6][ext]',
},
},
],
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 开发环境/生产环境
mode: 'development',
// mode:'production'
};
2.5 使用devServer
/*
开发环境配置:能让代码运行
运行项目指令:
webpack 会将打包结果输出出去
npx webpack serve 只会在内存中打包编译,没有输出
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口
entry: './src/index.js',
// 出口
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
// loader配置
module: {
rules: [
// 打包css
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
// 打包其他资源(除了html/css/js以外的资源)
{
// 排除css/js/html
// exclude: /\.(css|js|html)$/,
// webpack file-loader弃用
//loader:'file-loader'
test: /\.ttf|eot|woff2?$/, // webpack5打包字体资源
type: 'asset/resource',
generator: {
filename: 'font/[name].[hash:6][ext]',
},
},
],
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 开发环境/生产环境
mode: 'development',
// mode:'production'
// 开发服务器 devServer: 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为:npx webpack serve
// 下载:webpack-dev-server
devServer: {
// 项目构建够路径
static: {
directory: resolve(__dirname, 'build'),
},
// 启动gzip压缩
compress: true,
// 所启动服务器的端口号
port: 3003,
// 自动打开浏览器
open: true,
},
};
第3章webpack开发环境的基本配置
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用资源模块处理字体
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用资源模块处理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用资源模块处理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用资源模块处理图片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 转base64条件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 处理html中的图片
test: /\.html$/,
loader: 'html-loader',
options:{
esModule:false
}
},
],
},
plugins: [
// 处理html资源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 项目构建目录
static:{
directory:resolve(__dirname,'build'),
},
compress:true, // gzip压缩
open:true, // 自动打开浏览器
port:3003, // 端口
},
};
第4章 webpack生产环境基本介绍
4.1 将CSS提取成单独文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 创建style标签,将样式放入
// 'style-loader',
// 这个loader取代style-loader.作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
'css-loader',
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
// 提取CSS成单独文件
new MiniCssExtractPlugin({
// 对输出的CSS文件进行重命名
filename: 'css/built.css',
}),
],
mode: 'development',
};
4.2 CSS兼容性处理
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 设置nodejs环境变量
process.env.NODE_ENV = 'development';
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
/*
兼容性处理
postcss:postcss-loader和postcss-preset-env
识别对应的环境加载对应的配置
该插件帮postcss找到package.json中的browserslist里面的配置,通过配置加载指定的css兼容性样式
"browserslist":{
* 开发环境 :设置node环境变量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一个chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生产环境: 默认是看生产环境
"production":[
">0.2%",
"not dead", // 不要已经丢弃的浏览器
"not op_mini all" 不要所有的欧朋浏览器
]
}
*/
{
loader: 'postcss-loader',
options: {
postcssOptions:{
plugins: [require('postcss-preset-env')()],
}
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/built.css',
}),
],
mode: 'development',
};
4.3 CSS压缩
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 设置nodejs环境变量
// process.env.NODE_ENV = 'development';
// optimize-css-assets-webpack-plugin
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 将CSS提取成单独文件
MiniCssExtractPlugin.loader,
'css-loader',
// 兼容性处理
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [require('postcss-preset-env')()],
},
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/built.css',
}),
// 压缩文件(webpack5采用该插件:CssMinimizerWebpackPlugin)
new OptimizeCssAssetsWebpackPlugin(),
],
mode: 'development',
};
4.4 Eslint语法检查
// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
mode: "development",
entry: './src/index.js',
// devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
compress: true,
open: false
},
output: {
publicPath: '/',
// 指定打包后输出的文件名
filename: 'js/app.[contenthash:10].js',
// 指定打包后输出的目录
path: path.resolve(__dirname, 'dist')
},
resolve: {
alias: {
# !!!!!!注意如果配置了此处 要安装步骤5的插件!!!!!!!! #
"@": path.resolve(__dirname, 'src')
}
},
module: {
rules: [
]
},
plugins: [
#使用 配置项都可以在eslint-webpack-plugin的github上找到
new ESLintPlugin({
// 启用 ESLint 自动修复特性
fix: true,
// 指定需要检查的扩展名。
extensions: ['js', 'json', 'coffee'],
// 指定需要排除的文件及目录。必须是相对于 options.context 的相对路径
exclude: '/node_modules/'
}),
]
};
// package.json
"eslintConfig": {
"extends": "airbnb-base",
#!!!!如果没使用alias下面的不用配置!!!!!
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.config.js"
}
}
}
}
4.5 js兼容性处理
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
/*
js兼容性处理:babel-loader @babel/core @babel/preset-env
1. 基本js兼容性处理 --> @babel/preset-env
问题: 只能转换基本语法,如promise不能转换
2. 全部js兼容性处理 -->@babel/polyfill不用写配置,引入即可(下载了,只需要引入即可:import '@babel/polyfill'; )
问题:我只要解决部分的兼容性问题,但是将所有的兼容性代码引入,体积太大了
3.需要做兼容性处理的就做:按需加载 --> core-js
*/
{
test: /\.js$/,
// 排除第三方库
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设:指示babel做怎么样的兼容性处理
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
module: 'development',
};
4.6 压缩html和js
js压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 生产环境下会自动压缩js代码
module: 'production',
};
html压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 压缩html
minify: {
// 移出空格
collapseWhitespace: true,
// 移出注释
removeComments: true,
},
}),
],
// 生产环境下会自动压缩js代码
module: 'production',
};
第5章webpack生产环境的基本配置
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';
// 复用loader
const commonCssLoader = [
// 这个loader取代style-loader.作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合(加载)到js文件中
'css-loader',
// 兼容性处理
{
// 还需要在package.json中定义browserslist
/*"browserslist":{
* 开发环境 :设置node环境变量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一个chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生产环境: 默认是看生产环境
"production":[
">0.2%",
"not dead", // 不要已经丢弃的浏览器
"not op_mini all" 不要所有的欧朋浏览器
]
}
*/
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
/*
正常来讲,一个文件只能被一个loader处理,
当一个文件要被多个loader处理,name一定要指定loader执行的顺序
先执行eslint 在执行babel
*/
{
// js语法检查 在package.json中添加eslintConfig -->airbnb
/*
在package.json中添加eslintConfig -->airbnb
"eslintConfig": {
"extends": "airbnb-base"
}
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
{
// 处理图片资源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 处理HTML资源中的图片
test: /\.html/,
loader: 'html-loader',
},
{
// 处理其他资源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
plugins: [
// 提取CSS成单独文件
new MiniCssExtractPlugin({
// 对输出的CSS文件进行重命名
filename: 'css/built.css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html压缩 移出空格,注释
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
};
第5章webpack优化配置
5.1 开发环境性能优化
- 优化打包构建速度
- 优化代码调试
5.2 生产环境性能优化
- 优化打包构建速度
- 优化代码运行的性能
5.3 HMR: hot module replacement 热模块替换 / 模块热替换
/*
HMR: hot module replacement 热模块替换 / 模块热替换
作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
极大提升构建速度
样式文件:可以使用HMR功能,因为style-loader内部实现了~
js文件:默认不能使用HMR功能 -->需要修改js代码,添加支持HMR功能的代码
注意:HMR功能对js的处理,只能处理非入口js文件的其他文件.
html文件:默认不能使用HMT功能,同时会导致问题:html文件不能热更新了
解决:修改entry入口,将html文件引入
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['./src/index.js','./src/index.html']
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用资源模块处理字体(其他资源)
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用资源模块处理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用资源模块处理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用资源模块处理图片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 转base64条件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 处理html中的图片
test: /\.html$/,
loader: 'html-loader',
options: {
esModule: false,
},
},
],
},
plugins: [
// 处理html资源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 项目构建目录
static: {
directory: resolve(__dirname, 'build'),
},
compress: true, // gzip压缩
open: true, // 自动打开浏览器
port: 3003, // 端口
hot: true, //开启HMR功能 (当修改了webpack配置,新配置要想生效,必须重启webpack服务)
},
};
5.4 source-map: 一种提供源代码到构建后代码映射技术(如果构建后代码出错,通过映射关系可以追踪到源代码错误)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['./src/index.js', './src/index.html'],
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用资源模块处理字体(其他资源)
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用资源模块处理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用资源模块处理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用资源模块处理图片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 转base64条件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 处理html中的图片
test: /\.html$/,
loader: 'html-loader',
options: {
esModule: false,
},
},
],
},
plugins: [
// 处理html资源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 项目构建目录
static: {
directory: resolve(__dirname, 'build'),
},
compress: true, // gzip压缩
open: true,
port: 3003,
hot: true,
},
devtool: 'source-map',
};
/*
source-map: 一种提供源代码到构建后代码映射技术(如果构建后代码出错,通过映射关系可以追踪到源代码错误)
参数:
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
source-map:外部
错误代码准确信息 和 源代码的错误位置
inline-source-map:内联
只生成一个内联source-map
错误代码准确信息 和 源代码的错误位置
hidden-source-map:外部
错误代码错误原因,但是没有错误位置
不能追踪源代码错误,只能提示到构建后代码的错误位置
eval-source-map:内联
每一个文件都生成对应的source-map,都在eval函数中
错误代码准确信息 和 源代码的错误位置
nosources-source-map:外部
错误代码准确信息,但是没有任何源代码信息
cheap-source-map:外部
错误代码准确信息 和源代码错误位置
只能精确到行
cheap-module-source-map:外部
错误代码准确信息 和源代码错误位置
只能精确到行
module会将loader的source map加入
内联和外部的区别: 1.外部生成了文件,内联没有 2.内联构建速度更快
开发环境:速度快,调试更友好
速度快(eval>inline>cheap>...)
eval-cheap-source-map
eval-source-map
调试更友好
source-map
cheap-module-source-map
cheap-source-map
-->eval-source-map / eval-cheap-module-source-map
生产环境:源代码要不要隐藏?调试要不要更友好
内联会让代码体积变大,所以生产环境不用内联
nosources-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
-->source-map/cheap-module-source-map
*/
5.5 oneOf:生产环境提升打包构建速度
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';
// 复用loader
const commonCssLoader = [
// 这个loader取代style-loader.作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合(加载)到js文件中
'css-loader',
// 兼容性处理
{
// 还需要在package.json中定义browserslist
/*"browserslist":{
* 开发环境 :设置node环境变量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一个chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生产环境: 默认是看生产环境
"production":[
">0.2%",
"not dead", // 不要已经丢弃的浏览器
"not op_mini all" 不要所有的欧朋浏览器
]
}
*/
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js语法检查 在package.json中添加eslintConfig -->airbnb
/*
在package.json中添加eslintConfig -->airbnb
"eslintConfig": {
"extends": "airbnb-base"
}
*/
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf:[
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
/*
正常来讲,一个文件只能被一个loader处理,
当一个文件要被多个loader处理,name一定要指定loader执行的顺序
先执行eslint 在执行babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
{
// 处理图片资源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 处理HTML资源中的图片
test: /\.html/,
loader: 'html-loader',
},
{
// 处理其他资源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
]
}
],
},
plugins: [
// 提取CSS成单独文件
new MiniCssExtractPlugin({
// 对输出的CSS文件进行重命名
filename: 'css/built.css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html压缩 移出空格,注释
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
};
5.6 缓存:生产环境缓存的配置
视屏教程地址:https://www.bilibili.com/video/BV1e7411j7T5?p=23&spm_id_from=pageDriver
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
缓存:
babel缓存
cacheDirectory:true
-->让第二次打包构建速度更快
文件资源缓存
hash: 每次webpack构建时会生成一个唯一的哈希值
问题: 因为js和css同时使用一个hash值.
如果重新打包,会导致所有缓存失效.
chunkhash: 根据chunk生成的hash值.如果打包来源于同一个chunk,那么hash值就一样
问题: js和css的hash值还是一样的.
因为css是在js中被引入的,所以属于同一个chunk
contenthash: 根据文件的内容生成hash值.不同文件hash值一定不一样.
-->让代码上线运行缓存更好使用
*/
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';
// 复用loader
const commonCssLoader = [
// 这个loader取代style-loader.作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合(加载)到js文件中
'css-loader',
// 兼容性处理
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js语法检查 在package.json中添加eslintConfig -->airbnb
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
// 开启babel缓存 第二次构建时,会读取之前的缓存
cacheDirectory: true,
},
},
{
// 处理图片资源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 处理HTML资源中的图片
test: /\.html/,
loader: 'html-loader',
},
{
// 处理其他资源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
],
},
plugins: [
// 提取CSS成单独文件
new MiniCssExtractPlugin({
// 对输出的CSS文件进行重命名
filename: 'css/built.[contenthash:10].css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html压缩 移出空格,注释
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
// 映射
devtool: 'source-map',
};
5.7 tree shaking(树摇/树震):
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //处理css文件并提取成单独文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css压缩
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
tree shaking: 去除无用代码
前提: 1. 必须使用ES6模块化 2.开启production环境 -->同时满足,自动开启tree shaking
作用: 减少代码体积
在package.json中配置
"sideEffects": false 所有代码都没有副作用(都可以进行tree shaking)
问题: 可能会把css/@babel/polyfill(副作用)文件干掉
"sideEffects": ["*.css","*.less"]
*/
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'production';
// 复用loader
const commonCssLoader = [
// 这个loader取代style-loader.作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合(加载)到js文件中
'css-loader',
// 兼容性处理
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js语法检查 在package.json中添加eslintConfig -->airbnb
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
// 开启babel缓存 第二次构建时,会读取之前的缓存
cacheDirectory: true,
},
},
{
// 处理图片资源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 处理HTML资源中的图片
test: /\.html/,
loader: 'html-loader',
},
{
// 处理其他资源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
],
},
plugins: [
// 提取CSS成单独文件
new MiniCssExtractPlugin({
// 对输出的CSS文件进行重命名
filename: 'css/built.[contenthash:10].css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html压缩 移出空格,注释
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
// 映射
devtool: 'source-map',
};
5.8 code split:代码分割
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 单入口
//entry: './src/js/index.js',
entry: {
index: './src/js/index.js',
test: './src/js/test/js',
},
output: {
// name: 取文件名(取index/test)
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html压缩 移出空格,注释
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
// 可以将node_modules中代码单独打包成一个chunk最终输出
// 自动分析多入口chunk中,有没有公共的文件.如果有会打包成一个单独chunk
optimization: {
splitChunks: {
chunks: 'all',
},
},
mode: 'production',
};
代码分割之方法3
![image](https://img2022.cnblogs.com/blog/2560128/202202/2560128-20220215174904713-157394179.png)
5.9 懒加载和预加载
![image](https://img2022.cnblogs.com/blog/2560128/202202/2560128-20220215181052264-376673648.png)
PWA:渐进式网络开发应用程序
多进程打包
externals
dll (动态连接库)
性能优化总结
### WEBPACK 性能优化
- 开发环境性能优化
- 生产环境性能优化
#### 开发环境性能优化
- 优化打包构建速度
- HMR
- 优化代码调试
- source-map
#### 生产环境性能优化
- 优化打包构建速度
- onfOf
- babel 缓存
- 多进程打包
- externals(让某些库不打包,直接通过 cdn 连接引入)
- dll(让某些库不打包,单独打包)
- 优化代码运行的性能
- 缓存(hash-chunkhash-contenthash)
- tree shaking(树摇)
- code split(代码分割)
- 懒加载/预加载
- PWA(渐进式网络应用开发技术/离线访问技术)
第6章 webpack详细配置
webpack详细配置之entry
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
/*
entry:入口起点
1.string --> './src/index.js'
单入口(应用最多)
打包形成一个chunk.输出一个bundle文件
此时chunk的名称默认是 main
2.array --> ['./src/index.js','./src/add.js']
多入口
所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件.
-->只有在HMR功能中让html热更新生效
3.object -->entry: { index: './src/index.js', add: './src/add.js' },
多入口
有几个入口文件就形成几个chunk,输出几个bundle文件
此时chunk的名称就是key
-->特殊用法
{
// 所有入口文件最终只会形成一个chunk,输出出去只有一个bundle文件.
index: ['./src/index.js', './src/count.js'],
// 形成一个chunk,输出一个bundle文件
add: './src/add.js'
}
*/
module.exports = {
// entry: './src/index.js',
entry: { index: ['./src/index.js', './src/count.js'], add: './src/add.js' },
output: {
filename: '[name].js',
path: resolve(__dirname, 'build'),
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack详细配置之output
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/index.js',
output: {
// 文件名称(可以指定名称+目录)
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
// (一般适用于生产环境)所有资源引入公共路径前缀-->'imgs/a.jpg'-->'/imgs/a.jpg'
publicPath: '/',
chunkFilename: '[name]_chunk.js', // 非入口chunk的名称
// 一般结合dll一起使用
//library: '[name]', // 整个库向外暴露的变量名
//libraryTarget:'window',// 变量名添加到哪个上 browser
//libraryTarget:'global',// 变量名添加到哪个上 node
//libraryTarget:'commonjs',
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack详细配置之module
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/index.js',
output: {
// 文件名称(可以指定名称+目录)
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多个loader 用use
use: ['style-loader', 'css-loader'],
},
{
test: /\.js$/,
// 排除node_modules下的js文件
exclude: /node_modules/,
// 只检查src下面的js文件
include: resolve(__dirname, 'src'),
// pre 优先执行 ,post 延后执行
enforce: 'pre',
// 单个loader
loader: 'eslint-loader',
},
{
// 以下配置只会生效一个
oneOf: [],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack详细配置之resolve(用来解析模块的规则)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名称(可以指定名称+目录)
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多个loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
// 解析模块的规则
resolve: {
// 配置解析模块路径别名: 优点可以简写路径 缺点:写路径时没有提示
alias: {
$css: resolve(__dirname, 'src/css'),
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', 'jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
};
webpack详细配置之devServer
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名称(可以指定名称+目录)
filename: 'js/[name].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多个loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
// 解析模块的规则
resolve: {
// 配置解析模块路径别名: 优点可以简写路径 缺点:写路径时没有提示
alias: {
$css: resolve(__dirname, 'src/css'),
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', 'jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
// 用于开发环境
devServer: {
// 运行代码的目录
contentBase: resolve(__dirname, 'build'),
// 监视contentBase 目录下的所有文件,一旦文件发生变化就会 reload(重载)
watchContentBase: true,
watchOptions: {
// 忽略文件
ignored: /node_modules/,
},
// 启动gzip压缩
compress: true,
// 端口
port: 5000,
// 域名
host: 'localhost',
// 自动浏览器
open: true,
// 开启HMR功能
hot: true,
// 不需要显示启动服务器日志信息
clientLogLevel: 'none',
// 除了一些基本启动信息以外,其他内容都不要显示
quiet: true,
// 如果出现错误,不要全屏提示
overlay: false,
// 服务器代理 -->解决开发环境跨域问题
proxy: {
// 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器 (3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': '',
},
},
},
},
};
webpack详细配置之optmization
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
const TerserWebpackPlugin = require('terser-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名称(可以指定名称+目录)
filename: 'js/[name].[contenthash:10].js',
// 输出文件目录(将来所有资源输出的公共目录)
path: resolve(__dirname, 'build'),
chunkFilename: 'js/[name].[contenthash:10]_chunk.js',
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多个loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'production',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css'),
},
extensions: ['.js', '.json', 'jsx', '.css'],
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
optimization: {
splitChunks: {
chunks: 'all',
// 默认值,可以不写
/* minSize: 30 * 1024, // 分割的chunk最小为30kb
maxSize: 0, // 最大没有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
maxInitialRequests: 3, // 入口js文件最大并行请求数量
automaticNameDelimiter: '~', // 名称连接符
name: true, // 可以使用命名规则
cacheGroups: {
// 分割chunk的组
// node_modules文件会被打包到vendors 组的chunk中. -->vendors~XXX.js
// 满足上面的公共规则,如:大小超过30KB,至少被引用一次.
vendors: {
test: /[\\/]node_modules[\\/]/,
// 优先级
priority: -10,
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
priority: -20,
// 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用.而不是重新打包模块
reuseExistingChunk: true,
},
}, */
},
// 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
// 解决:修改a文件导致b文件的contenthash变化
runtimeChunk: {
name: (entrypoint) => `runtime-${entrypoint.name}`,
},
// 配置生产环境的压缩方案:js和css
minimizer: {
new TerserWebpackPlugin({
// 开启缓存
cache:true,
// 开启多进程打包
parallel:true,
// 启用source-map
sourceMap:true,
})
},
},
};
第7章 webpack5介绍和使用