一文彻底读懂webpack常用配置
开发环境
const webpack = require("webpack");
const path = require('path')
module.exports = {// entry: {// a: './src/0706/a.js',// c: './src/0706/c.js',// },entry: "./src/0707/reactDemo.js",output: {filename: '[name]_dist.js',path: path.resolve(__dirname, 'dist3'),},mode: 'development',devtool: 'source-map',module: {rules: [{test:/.js$/,use: 'babel-loader',},{test: /.css$/,use: ['style-loader','css-loader']},{test:/.less$/,use: ['style-loader','css-loader','less-loader']},{test: /.(png|jpg|gif|jpeg)$/,use: 'file-loader'},{test: /.(png|jpg|jpeg|gif)$/,use: {loader: 'url-loader',options: {limit: 10240 * 10}}},{test: /.(woff|woff2|eot|ttf|otf)$/,use: 'file-loader'}],},// plugins: [// new webpack.HotModuleReplacementPlugin()// ],// 在使用devServer的时候,如果hot为true的话,会自动帮我们添加HotModuleReplacementPlugin// 如果使用自己实现的服务器,就需要自己添加devServer: {contentBase: './dist3',hot: true}
}
生产环境
const webpack = require("webpack");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// minicssextractplugin 推荐使用cssminimizerwebpackplugin来压缩css
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// 根据模板生产html,并插入相应的chunk,同时也可以压缩html
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 清除构建产物的插件,注意这里的引入方式
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
module.exports = {// entry: {// a: './src/0706/a.js',// c: './src/0706/c.js',// },entry: "./src/0707/reactDemo.js",output: {// 文件指纹 chunkhash chunk改变就会重新生成// hash 整个项目有文件改变就会重新生成// contenthash 文件内容改变才会重新生成filename: '[name]_[chunkhash:8].js',path: path.resolve(__dirname, 'dist3'),},mode: 'production',optimization: {minimizer: [// 压缩CSSnew CssMinimizerPlugin(),// webpack5内置了terser-plugin,但是上面的插件会覆盖掉默认的terser-plugin,所以通过下面的一行来将默认的插件加回去'...']},module: {rules: [{test:/.js$/,use: 'babel-loader',},{test: /.css$/,use: [MiniCssExtractPlugin.loader,'css-loader']},{test:/.less$/,use: [// 使用miniCssExtractPlugin提取css后,这里需要替换成它的loaderMiniCssExtractPlugin.loader,'css-loader','less-loader']},{test: /.(png|jpg|gif|jpeg)$/,use: {loader: 'file-loader',options: {name: '[name]_[hash:8].[ext]'}}},{test: /.(png|jpg|jpeg|gif)$/,use: {loader: 'url-loader',options: {limit: 10240 * 10}}},{test: /.(woff|woff2|eot|ttf|otf)$/,use: 'file-loader'}],},plugins: [new MiniCssExtractPlugin({// 使用contenthash 这样如果只改变了js的话css也无需重新生成filename: '[name]_[contenthash:8].css'}),new HtmlWebpackPlugin({// 模板所在路径template: path.resolve(__dirname, 'src/index.html'),// 生成的html的名字filename: 'index2.html',// 用到了哪个chunk// chunks: ['a']// 压缩选项minify: {html5: true,collapseWhitespace: true,preserveLineBreaks: false,minifyCSS: true,minifyJS: true,removeComments: true}})]
}
自动添加CSS前缀
- 使用postcss-loader + autoprefixer
- 添加postcss.config.js 新版本直接在webpack配置文件里添加会报错,所以需要写到一个独立的配置文件里
module.exports = {plugins: [require('autoprefixer')({overrideBrowserslist: ['last 2 version', '>1%', 'ios 7']})]
}
- 添加loader
{test: /.css$/,use: [MiniCssExtractPlugin.loader,'css-loader','postcss-loader' // 这里为新加的loader]
},
移动端适配 css px自动转rem
- 使用手淘lib-flexible 动态计算font-size
// 将lib-flexible静态内联到html上,因为要最先执行计算
// 在头部加入如下代码
// 使用了raw-loader,相当于在对应的位置是插入字符串
// 需注意raw-loader新老版本引入的差异
<script type="text/javascript"
<%=require('raw-loader!babel-loader!./node_modules/lib-flexible/flexible.js')%>
</script>
- 使用px2rem-loader 将px转成rem
{test: /.less$/use: ['style-loader','css-loader','less-loader',{loader: 'px2rem-loader',options: {// 以设计稿宽度750px为例,1rem = 75pxremUnit: 75,// 转换后的小数点后保留位数remPrecision: 8,}}]
}
- 代码里面直接按设计稿一样写px
// 下面的px最后会被转成em,如果有些特殊的地方不想转,可写成大写PX
.box {width: 100px;height: 100px;// 写成大写则不会被转换border: 1PX;
}
代码分割
- 利用splitChunks plugin将公共代码抽离
optimization: {splitChunks: {cacheGroups: {vendors: {chunks: 'all',name: 'vendors',// 将react和react-dom提取出一个包test: /(react|react-dom)/},common: {name: 'common',chunks: 'all',minSize: 0,// 被引用两次以上的提取出一个包minChunks: 2}}}
}
参考 前端进阶面试题详细解答
动态import 懒加载
- 通过ES6的动态import + babel插件@babel/plugin-syntax-dynamic-import
//babel配置里增加
plugins: ['@babel/plugin-syntax-dynamic-import'
]
// 代码里按需引入
import('xxx').then(res => res.default);
webpack结合eslint
- 以react为例,用到几个插件eslint eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-a11y
- 安装解析器babel-eslint
- 用airbnb的规则,需安装eslint-config-airbnb
- 安装eslint-loader
- 增加eslint配置 eslintrc.js
module.exports = {// 使用babel-eslint作为解析器"parser": "babel-eslint",// 继承airbnb的规则"extends": ["airbnb"],// 指定环境,这样使用全局变量的时候不会报错"env": {"browser": true,"node": true},// 自定义规则覆盖默认规则"rules": {// 使用4个空格缩进,否则error"indent": ["error", 4]}
}
webpack打包库
- 代码写好后,webpack配置如下
const path = require('path');
module.exports = {// 同时提供未压缩和压缩的版本entry: {'mylibrary': './src/entry.js','mylibrary.min': './src/entry.js'},output: {path: path.resolve(__dirname, 'lib'),// mylibrary.js mylibrary.min.jsfilename: '[name].js',// 对外暴露的库的名称library: 'mylibrary',// 支持cjs, ejs, script脚本等引入方式libraryTarget: 'umd',// 不加这个的话,使用的时候可能需要mylibrary.defaultlibraryExport: 'default'}
}
- 添加terser-webpack-plugin进行压缩
const TerserPlugin = require(‘terser-webpack-plugin’);
optimization: {minimize: true,minimizer: [new TerserPlugin({// 只对min版本压缩test: /.min.js/})]
}
- package.json 指定入口文件
"main": "index.js"
- index.js里面做环境判断
if(process.env.NODE_EVN === 'production') {module.exports = require('./lib/mylibrary.min.js');
} else {module.exports = require('./lib/mulibrary.js');
}
主动捕获异常
- 通过插件主动捕获异常
plugins: [function() {this.hooks.done.tap('done', (stats) => {if(stats.compilation && stats.compilation.errors.length > 1) {console.log('error')}})}
]
构建优化
速度优化:
- speed-measure-webpack-plugin分析构建速度
const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
const spm = new SpeedMeasureWebpackPlugin();
module.exports = spm.wrap({...});
- thread-loader开启多进程,放在需要的loader上面
module: {rules: [{test: /.js$/use: [{loader: 'thread-loader',options: {workers: 3}}]}]
}
- include exclude缩小构建目标
- resolve减少文件搜索范围
modules.exports = {...resolve: {// 指定node_modules的路径,减少模块搜索层级modules: [path.resolve(__dirname, 'node_modules')],// import react的时候直接从指定的路径去找alias: {react: path.resolve(__dirname, './node_modules/react/dist/react.min.js')},// import xx from 'a'的时候,只找.js后缀的// 高频文件后缀名放前面extensions: ['.js'],// 指定入口,避免不必要的分析mainFields: ['main']}
}
- 开启babel-loader缓存
// 仅需加个url参数
module: {rules: [{test: /.js$/,use: ['babel-loader?cacheDirectory=true'}]
}
- terser-webpack-plugin开启缓存
// webpack5之后不再用这种方式
new TerserWebpackPlugin({cache: true
})
- cache-loader缓存
- hard-source-webpack-plugin缓存,减少二次构建时间
plugins: [new HardSourceWebpackPlugin()]
- terser-webpack-plugin默认开启了JS多进程压缩
optimization: {minimizer: [new TerserWebpackPlugin({// 指定进程数量parallel: 4})]
}
- 使用DLLPlugin进行分包
先构建出单独的包
// 单独的配置文件用于生成包
module.exports = {entry: {// 将react react-dom抽离出单独的包library: ['react', 'react-dom']},output: {filename: '[name].dll.js',path: path.resolve(__dirname, 'dist3/lib')library: '[name]'},plugins: [// 使用DLLPlugin抽离,生成manifestnew webpack.DllPlugin({name: '[name]_2',path: path.resolve(__dirname, 'dist3/lib/[name].json'),}),// new CleanWebpackPlugin(),]
}
再通过manifest关联抽离的包
// webpack.prod.config.js
new webpack.DllReferencePlugin({manifest: require('./dist3/lib/library.json')
})
最后将抽离的包插入html模板中
- noParse 对完全不需要解析的库进行忽略 (不去解析但仍会打包到 bundle 中,注意被忽略掉的文件里不应该包含 import、require、define 等模块化语句)
体积优化
- webpack-bundle-analyzer分析体积
plugins: [new WebpackBundleAnalyzer()
]
- 图片压缩
使用image-webpack-loader
rules: [{test: /\.(gif|png|jpe?g|svg)$/i,use: ['file-loader',{loader: 'image-webpack-loader',options: {mozjpeg: {progressive: true,},// optipng.enabled: false will disable optipngoptipng: {enabled: false,},pngquant: {quality: [0.65, 0.90],speed: 4},gifsicle: {interlaced: false,},// the webp option will enable WEBPwebp: {quality: 75}}},],
}]
- 对CSS 进行tree shaking
使用purgecss-webpack-plugin,要配合mini-css-extract-plugin一起使用
const purgecssPath = path.join(__dirname, 'src');
const glob = require('glob');
new PurgecssPlugin({paths:glob.sync(`${purgecssPath}/**/*`, { nodir: true }),
}),
- 动态polyfill
根据浏览器的user agent 动态下发polyfill
<script src="https://polyfill.io/v3/polyfill.min.js"></script>
或者可以自建CDN
相关文章:
一文彻底读懂webpack常用配置
开发环境 const webpack require("webpack"); const path require(path) module.exports {// entry: {// a: ./src/0706/a.js,// c: ./src/0706/c.js,// },entry: "./src/0707/reactDemo.js",output: {filename: [name]_dist.js,path: path.resolve(__…...

大环境不好,找工作太难?三面阿里,幸好做足了准备,已拿offer
三面大概九十分钟,问的东西很全面,需要做充足准备,就是除了概念以外问的有点懵逼了(呜呜呜)。回来之后把这些题目做了一个分类并整理出答案(强迫症的我狂补知识)分为软件测试基础、Python自动化…...
C++ 手撸简易服务器(完善版本)
本文没有带反射部分内容,可以看我之前发的 Server.h #pragma once#include <string> #include <iostream> #include <thread> #include <unordered_map> using namespace std; #ifndef _SERVER_ #define _SERVER_#include <winsock.h&…...
【Python入门第三十四天】Python丨文件处理
文件处理是任何 Web 应用程序的重要组成部分。 Python 有几个用于创建、读取、更新和删除文件的函数。 文件处理 在 Python 中使用文件的关键函数是 open() 函数。 open() 函数有两个参数:文件名和模式。 对于刚学Python的小伙伴,我给大家准备了2023…...

【Linux】写一个基础的bash
头文件#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/wait.h> #include<sys/stat.h> #include<string.h> #include<pwd.h> #include<dirent.h>分割输入的命令串字符串或参数内容为空则退出strtok( ,…...

图解如何一步步连接远程服务器——基于VScode
基于VScode连接远程服务器 安装Remote-SSH等插件 想要在vscode上连接远程服务器需要下载Remote-SSH系列插件: 直接在插件中搜索remote,即可找到,选择图片中的3个插件,点击install安装。 配置Remote-SSH 在这个步骤有多种操作…...
element - - - - - 你不知道的loading使用方式
求人不如求己 你不知道的loading使用方式1. 指令方式使用1.1 默认loading1.2 自定义loading1.3 整页加载2. 服务方式使用2.1 this.$loading的使用2.2 Loading.service的使用关于页面交互,最害怕的就是接口等待时间太长,用户体验不好。 而如何提高用户体…...
C++程序调用IsBadReadPtr或IsBadWritePtr引发内存访问违例问题的排查
目录 1、问题描述 2、VS中看不到有效的信息,尝试使用Windbg去分析 3、使用Windbg分析 4、最后...
IntelliJIDEA 常用快捷键
IntelliJIDEA 常用快捷键 Alt Enter 导入包,自动修正,自动创建变量名。 Ctrl Alt O 优化导入的类和包 Ctrl / 单行注释 (//) Ctrl Shift / 多行注释 (/* … */) 方法或类说明注释(文档注释) 在一个方法或类的开头…...
Python自动化抖音自动刷视频
环境准备 Python3.5以上Appium Server服务器Android SDK,需要用到adb服务需要依赖Appium-Python-Client组件库真机或者模拟器,推荐模拟器(真机一般安卓8版本以上了,appium对安卓8以上版本元素获取的兼容性不太好)JDK8环境 实现 确保adb服务…...

使用vite创建vue3工程
定义 什么是vite?-----新一代前端构建工具 优势 开发环境中,无需打包操作,可快速的冷启动---最牛的地方轻量快速的热重载(HMR)---一修改代码就局部刷新,webpack也具备,但vite更快真正的按需编…...

嵌入式学习笔记——STM32的时钟树
时钟树前言时钟树时钟分类时钟树框图LSI与LSEHSI、HSE与PLL系统时钟的产生举例AHB、APBx的时钟配置时钟树相关寄存器介绍1.时钟控制寄存器(RCC_CR)2.RCC PLL 配置寄存器 (RCC_PLLCFGR)3.RCC 时钟配置寄存器 (RCC_CFGR)4.RCC 时钟中断寄存器 (RCC_CIR)修改…...
Python学习(2)-NumPy矩阵与通用函数
文章首发于:My Blog 欢迎大佬们前来逛逛 1. NumPy矩阵 1.1 mat函数 matasmatrix asmatrix(data, dtypeNone):data:表示输入的数组或者字符串,使用‘,’分割列,使用‘;’分割行 创建两个普通的矩阵&…...
剑指 Offer II 035. 最小时间差
题目链接 剑指 Offer II 035. 最小时间差 mid 题目描述 给定一个 24小时制(小时:分钟 "HH:MM")的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1: 输入:timePoints [“23:59”,“0…...
Spark SQL函数定义【博学谷学习记录】
1 如何使用窗口函数窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count()第三类: la…...

模拟实现STL容器之vector
文章目录前言1.大体思路2.具体代码实现1.类模板的创建2.构造函数1.无参构造2.拷贝构造 迭代器构造和给定n个val值构造以及析构函数3.空间扩容1.reserve2.resize4.操作符重载1.[ ]重载2.赋值运算符重载5.数据增加和删除1.尾插2.任意位置插入3.任意位置删除4.尾删6.一些其他接口3…...

ChatGPT-4.0 : 未来已来,你来不来
文章目录前言ChatGPT 3.5 介绍ChatGPT 4.0 介绍ChatGPT -4出逃计划!我们应如何看待ChatGPT前言 好久没有更新过技术文章了,这个周末听说了一个非常火的技术ChatGPT 4.0,于是在闲暇之余我也进行了测试,今天这篇文章就给大家介绍一…...
Java反射(详细学习笔记)
Java反射 1. Java反射机制概述 Reflection(反射)是java被视为java动态语言的关键,反射机制允许程序在执行期间借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。 Class c Class.forName(&quo…...

学习 Python 之 Pygame 开发魂斗罗(十二)
学习 Python 之 Pygame 开发魂斗罗(十二)继续编写魂斗罗1. 修改玩家扣减生命值2. 解决玩家下蹲子弹不会击中玩家而是直接让玩家死亡的问题3. 完善地图4. 增加产生敌人函数,解决一直产生敌人的问题5. 给玩家类增加计算玩家中心的方法继续编写魂…...

Linux下字符设备驱动开发以及流程介绍
文章目录1 - 字符设备介绍2 - 字符设备开发流程图3 - 字符设备开发流程具体讲解(1)设备编号的定义与申请【1】Linux主次设备号介绍【2】分配设备编号【3】释放主次设备号(2)定义file_operations结构体-初始化接口函数(…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...