webpack基础配置
1、webpack拆分配置和merge(拆分公共的配置进行引入dev和pro)
const {smart} = require('webpack-merge')
module.exports = smart(webpackCommcpnf, {
})
2、启动服务
安装webpack的dev-server,本地环境devServer配置,proxy本地代理去解决跨域问题
3、es6处理
rules: [
{
test: '/\.js$/', // 匹配js文件
loader: ['babel-loader'], // 处理es6
include: srcPath, // 包括的文件路径
exclude: /node_modules/ // 忽略的文件
}
]
需要配置.babelrc文件
{
'presets': ["@babel/preset-env"] // 处理es6,es7等文件
}
4、处理样式
rules: [
{
test: '/\.css$/',
loader: ['style-loader','css-loader','postcss-loader'], // 注意执行顺序从后往前
}
]
postcss-loader: 浏览器兼容性处理
less-loader:处理less文件的时候
postcss是一个比较大的集合。里面会引入一些插件
postcss.config.js
// autoprefixer:增加前缀 --> -webkit-
module.exports = {
plugins: [require['autoprefixer']]
}
5、处理图片
dev中:
rules: [
{
test: '/\.(png|jpg|jpeg|gif)/',
use: 'file-loader'
}
]
线上:
rules: [
{
test: '/\.(png|jpg|jpeg|gif)/',
use: {
loader: 'url-loader',
options: {
// 如果图片小于5mb就用base64位格式产出,否则打包到img1的目录下
limit: 5 * 1024,
outputPath: '/img1/'
}
}
}
]
// 文件内柔没有变化的话,hash就不会变,就能命中缓存加快渲染
output: {
filename:'bundle.[contentHash:8].js', // js文件打包时,加上8位的hash值
path: disPath
}
webpack高级配置
1、多入口配置
entry: {
index: path.join(srcPath, 'index.js'),
other: path.join(srcPact, 'other.js')
}
对应多出口
output: {
filename:'[name].[contentHash:8].js', // name即对应的入口的文件名称
path: disPath
}
// 多入口生成文件
plugins: {
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
chunks: ['index']
})
new HtmlWebpackPlugin({
template: path.join(srcPath, 'other.html'),
filename: 'other.html',
chunks: ['other']
})
}
总结:多入口需要entry配置多个入口,output配置多个出口,同时需要多个HtmlWebpackPlugin匹配生成文件
2、css线上处理(不能插入style中)
// 安装插件
const MiniCssExtractPlugin = require('min-css-extract-plugin')
// 抽离css
{
test: /\.css$/,
loader: [
MiniCssExtractPlugin.loader, // 生产环境不再用style-loader
'css-loader',
'postcss=loader'
]
}
// 抽离less
{
test: /\.less$/,
loader: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
'postcss=loader'
]
}
// 抽离css文件
plugins: [
new MiniCssextractPlugin({
filename: 'css/main.[contentHash:8].css'
})
]
// 压缩css
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCssAssetSPlugin({})]
}
总结:css线上处理需要在生产环境处理的基础上在loader上通过MiniCssExtractPlugin去进行抽离,同时对抽离css文件hash处理,最后再进行一步压缩进一步优化
3、抽离公共代码(线上环境抽离第三方库或者公共的资源代码)
optimization:[
// 分割代码块儿
splitChunks: {
chunks: 'all', // initial 入口chunk,对于异步导入的文件不处理;async异步chunk,只对异步导入的文件处理;all是都处理
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', //chunk名称
priority: 1, // 全县更高,优先抽离(优先命中)
test: '/node_modules/, // 判断文件的路径,是否能在这个文件夹中命中
minSize: 0, // 大小限制, // 最小的话就不用进行过度拆分
minChunks: 1 // 最少复用过几次
},
// 公共的模块
common: {
name: 'common',
priority: 0,
minSize: 0,
minChunks: 2
}
}
}
]
plugins: {
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
chunks: ['index', 'vendor', 'common'] // 对应的代码分割的name名称
})
}
总结:抽离公共代码块需要在optimization的splitChunks中进行拆分模块儿,然后在生成文件的时候需要用到哪些chunks自己引入对应的name
4、懒加载(引入动态数据)
js中引入动态数据
setTimeOut(() => {
// 定义一个chunk
import('./aaa.js').then(res => {
console.log(111)
})
}, 1500)
5、处理JSX和vue
处理jsx:安装breset-react,在babelrc中使用,然后loader配置下即可
处理vue:安装vue-loader,然后loader配置下即可
6、webpack概念总结
module、chunk、bundle区别
module:各个源码文件,webpack中一切皆模块 --- 所有的src引入的文件都是模块
chunk:多模块合并成的,如entry、import()、splitChunk --- 通过分析里面的内容可以生成一个代码的集合
budle:最终的输出文件 -- 一个chunk对应一个budle,chunk是整合的一个过程,budle是最终的结果
webpack的性能优化
1、优化babel-loader
{
test: '/\.js$/',
use:['babel-loader?cacheDirectory'], // 开启缓存
include: path.resolve(__dirname, 'src') // 明确范围
// include和exclud两者选一个即可
}
2、IgnorePlugin(忽略第三方包指定目录)
new webpack.IgnorePlugin({
resourceRegExp: /^./locale$/, // 匹配规则,文件目录中存在这个的全部忽略
contextRegExp: /moment$/, // 文件目录
})
注意:忽略文件后,如果需要用到里面的某个东西需要手动进行引入一下
3、noParse(过滤不需要解析的文件)
module: {
noParse: '/jquery|lodash/' // 不去解析引入的依赖库
}
4、happyPack多进程打包
rules: [
{
test: /\.js$/,
use: ['happypack/loader?id=babel'],
include: srcPath
}
]
plugins:{
new HappyPack({
id: 'babel', // 对应上面的唯一id,用来处理一类特定的文件
loaders: ['babel-loader?cacheDirectory']
})
}
5、parallelUglifyPlugin多进程压缩js
new ParallelUglifyPlugin({
uglifyJS: {
output: {
beautify: false, // 最紧凑的输出
comments: false // 删除所有的注释
},
compress: {
// 删除所有的console语句,可以兼容ie
drop_console: true,
// 内嵌定义了但是只用到了一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量的静态值
reduce_vars: true
}
}
})
补充:上述两个都是多进程,但是为什么速度没有提升呢?
-- 项目比较大,打包速度慢,能提高速度
-- 项目比较小的话,打包速度快,开启反而会降低速度
6、webpack配置热更新
自动刷新:(自动刷新整个网页刷新,速度慢;状态会丢失)
module.export = {
watch: true, // 开启监听,默认为false
// 注意,开启监听后,webpack-dev-server会自动开启刷新浏览器
watchOptions: {
ignore: /node_module/,
aggregateTimeout: 300, // 监听到文件发生变化后,300ms后再去执行,防止刷新频率过高
poll: 1000 // 每隔1000ms询问一次
}
}
热跟新:(新代码生效,网页不刷新,状态不丢失)
module.export = {
extry: {
index: [
'webpack-dev-server/client?http://localhost:8080/',
'webpack/hot/dev-server',
path.join(srcPath, 'index.js')
]
},
plugins: [
new HotModuleReplacementPlugin()
],
devServer: {
hot: true
}
}
监听范围外,需要热更新的js文件
if (module.hot) {
module.hot.accept(['./math'], () => {
console.log('热更新')
})
}
7、DllPlugin 动态链接库插件
-- 前端框架一般体积比较大,构建比较慢
-- 较稳定,不常升级版本
-- 同一个版本每次只构建一次就行,不用每次都重新构建
webpack已经内置了DllPlugin文件支持
① DllPlgin打包出dll文件
② DllReferencePlugin去使用dll文件,之后只要文件不变就会一直使用打包好的dll文件
新建一个webpack.dll.js
modules.export = {
mode: 'development',
entry: {
vendor: ['element-ui', vuex]
},
output: {
filename: '[name].dll.js',
path: disPath,
library: '[name]_[hash]'
},
plugins: [
new DllPlugin({
name: '[name]_[hash]',
path: path.join(disPath, '[name]-mainfest.json')
})
]
}
Package.json中去定义路径打包,然后在index中去引用dll.js
'dll': 'webpack --config ./webpack.dll.js'
webpack.dev.js
plugins:[
new DllReferencePlugin({
mainfast: require(path.join(disPath, 'vendor-manifest.json'))
})
]
8、webpack性能优化-产出代码
-- 体积更小
-- 合理分包,不重复加载
-- 速度更快,执行速度更小
方法
-- 小图片base64位编码
-- bundle + hash
-- 懒加载
-- 提取公共代码
-- ignorePlugin
-- 使用cdn加速
-- 使用production
-- Scope Hosting
使用production
mode:'production'
-- 自动压缩代码
-- vue React等会自动删掉调试代码
-- 自动启用Tree-Shaking
注意:ES6 Module才能让tree-shaking生效;commonjs不行
ES6 Module和commonjs区别
-- ES6 Module静态引入,编译时引入
-- Commonjs动态引入,执行时引入
-- 只有ES6 Module才能静态分析,实现Tree-Shaking
动态静态举例:require可以放在判断条件里面引入
Scope Hosting
-- 代码体积更小
-- 创建函数作用域更少
-- 代码可读性更好
module.exports = {
resolve: {
// 针对Npm中的第三方模块优先采用 jsnext:main中指向的ES6模块化语法的文件
mainFields: ['jsnext:main', 'browser','main']
},
plugins: [
new ModuleConcatenationPlugin()
]
}
babel
1、环境搭建和基本配置
.babelrc
// es6转换成es5语法
{
"presets": [
[
"@babel/preset-env" // 预设,包里面写了很多的plugin,插件的集合
]
],
“plugins":[
]
}
2、babel-polyfill(补丁,兼容低版本浏览器)
core.js库 -- 能满足绝大多数es6,es7语法的兼容(generator函数不能兼容,被async/await代替) regenerator库 -- 能支持generator语法
babel-polyfill就是这两个库的集合(7.4之后弃用,推荐直接使用core库,regenerator库)
3、babel-polyfill按需引入(文件较大,只用了部分功能)
-- babel只解析语法是否规范,至于是否有这个api或者浏览器是否支持不在解析范围内
-- babel不处理模块化(webpack处理)
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3 // corejs 版本
}
]
],
“plugins":[
]
}
4、babel-runtime
babel-polyfill问题
-- 会污染全局环境
-- 独立web系统无碍
pakeage.js
"devDependencies": {
"@babel/plugin-transform-runtime": ""
},
"dependencies": {
"babel/runtime": ''
}
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3 // corejs 版本
}
]
],
“plugins":[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": 3,
"helpers": true,
"regenerator": true,
"usaESModules"; false
}
]
}
下一篇:前端面试-webpack系列(webpack真题总结)