以下是本人学习webpack时做的笔记记录
/**
- HMR hot module replacement 热模块替换 / 模块热替换
- 作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
- 极大的提升了构建速度
- 样式文件可以使用HRM 因为style-loader内部实现了
- js:默认不使用HMR功能—>修改js代码,添加支持HMR功能的代码
- 注意:HMR功能对js的处理—>只能处理非入口js文件的其他文件。
- html:默认不能使用HRM功能,同时会导致问题:HTML文件不能热更新了~(
- 不需要做热更新功能,因为只有一个html文件)
- 解决: 修改entry入口,将html文件引入
- 注意:生产环境不能使用HMR,使用缓存
/
/* - 缓存
- babel缓存
- cacheDirectory:true
- 文件资源缓存
- hash:每次webpack会产生唯一一个hash值
- 问题:因为js和css使用同一个hash值。
- 如果重新打包,会导致所有缓存失效(可能我只改变一个文件)
- chunkhash:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值就一样
- 问题:js和css的值还是一样的,因为css是在js中被引入的,所以同属于一个chunk
- contenthash:根据文件的内容生成hash,不同文件hash值不一样;
*/
/**
-
tree shaking:去除无用代码
-
前提:1.必须使用ES6模块化 2.开启production环境
-
作用:减少代码体积
-
在package.json中配置
-
‘sideEffects’:false 所有代码都没有副作用(都可以进行 tree shaking )
-
问题:可能会把css/@babel/polyfill(副作用)文件干掉
-
“sideEffects”:["*.css"]//排除所有的css文件
*/
const HtmlWebpackPlugin = require(‘html-webpack-plugin’)
const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)
const PostcssPresetEnv = require(‘postcss-preset-env’)
const TerserWebpackPlugin=require(‘terser-webpack-plugin’)
const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
const WorkboxWebpackPlugin=require(‘workbox-webpack-plugin’)
const AddAssetHtmlWebpackPlugin=require(‘add-asset-html-webpack-plugin’)
const {
resolve
} = require(‘path’)
const webpack = require(‘webpack’)
process.env.NODE_ENV = ‘development’
module.exports = {
//单入口文件
entry: ‘./src/index.js’,
//代码分割
//多入口文件打包,将多入口文件分割成多个模块
//问题:不能将公共代码分割,导致公共代码重复加载,增大代码体积
// entry:{
// index:"./src/print.js",
// test:"./src/index.js"
// },
// entry: [’./src/index.js’,’./src/index.html’]//开启html文件的热更行
output: {
path: resolve(__dirname, ‘build’),
// filename: ‘bundle.js’
filename: ‘bundle.[hash:9].js’
// filename: ‘[name].js’//所有资源引入公共路径前缀---> img/a.jpg -->/img/a.jpg // ,publicPath:'/' ,chunkFileName:'[name]._chunk.js'//非入口chunk的名字(import动态引入)
},
module: {
rules: [
/**
* 正常来讲,一个文件只能被一个loader处理,
* 当一个文件被多个loader处理,那么一定要指定loader的执行顺序,
* 先执行eslint在执行babel
// */
{
//
test: /.js$/,/** * eslint是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具, * 它的目标是保证代码的一致性和避免错误。(官方翻译) * exclude排除node_moudles的检查,eslint语法检查需要 * eslint eslint-loader eslint-config-airbnb-base * eslint-plugin-import四个搭配使用,还需要在package.json中 * 配置eslintConfig--->"eslintConfig":{ "extends":"airbnb-bas" }, airbnb为编码规范(学习)github下载 fix:true为自动修改代码,使代码规范 enforce:'pre'指定哪个loader先执行 */ exclude: /node_moudles/, enforce: "pre", loader: 'eslint-loader', options: { fix: true } }, { /** * oneOf的意思是以下loader只会匹一个 * 不能有两个loader处理同一类型的文件, * 如果有多个loader要处理同一类型的文件,需要提取 * 出其他loader放到oneOf外面,直留一个loader在里面 * oneOf能够提升代码的构建速度 */ oneOf:[ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, /** * css-loader---->css-loader是从入口文件中将css文件转换成javascript *能够识别的文件,style-loader===>syle-loader是在html文件中创建style标签 */ 'css-loader', { loader: 'postcss-loader', options: { ident: 'postcss', plugins: () => [ /* postcss-preset-env---->是处理css3对浏览器兼容性的问题、 可以对css3的某些属性增加前缀,处理兼容问题, 还需要配置browserslist:{ "development":[ "last 2 chrome version", "last 2 firefox version", "last 2 safari version", ], production:[ ">0.1%", "not dead", "not op_mini all" ] } 指定browserslist在哪种环境下起作用,需要设置process.env.NODE_ENV的值 "development"在开发环境下起作用,"production"在生产环境下起作用 */ require('postcss-preset-env')() ] } } ] }, { test: /\.(jpg|png|gif)/, //url-loader--->url-loader是基于file-loader设计的,增加了limit //属性,对图片大小进行判断,然后选择对其进行编码操作 //esModule:false是关闭escript语法,因为html-loader采用的是commonjs //进行解析的,必须同步 //outputPath配置是将文件输出的路径 //hash:8文件名字使用8位的hash值命名,ext是源文件的扩展名 loader: 'url-loader', options: { limit: 8 * 1024, esModule: false, name: '[hash:8].[ext]' } }, /** * html-loader--->html-loader是为了解析html里面加载的图片 */ { test: /\.html$/, loader: "html-loader" }, { test: /\.(eot|svg|ttf|woff|woff2)/, loader: 'file-loader' }, /** * JS兼容处理安装babel-loader @babel/core @babel/preset-env * babel-loader--->babel-loader是npm的一个包,它使得webpack可以 * 通过babel转义javascript语句, * @babel/core---->@babel/core这是babel的核心库,负责解析。 * @babel/preset-env--->@babel/preset-env负责各种插件的打包组合, * 各种转义规则的统一设定,目的是告诉loader要以什么规则转来转化成对应的js版本 * 1、基本js的兼容处理--->@babel/preset-env只能转化基本语法,高级语法不能不能转换 * 2、全部js的兼容处理--->将全部兼容代码引入,会增大体积(不考虑使用) * 3、按需加载js的兼容处理--->core-js只加载需要处理的js兼容代码(配合@babel/preset-env使用) */ { test: /\.js$/, exclude: /node_modules/, use:[ { /** * 多进程打包 * 进程启动大概600ms,进程通信也有开销 * 只有工作时间消耗比较长,才需要多进程打包(比如有大量的js文件) */ loader:'thread-loader', options:{ workers:2 } }, { loader: 'babel-loader', //只使用@babel/preset-env处理兼容的代码 // options:{ // presets:['@babel/preset-env'] // } //使用@babel/preset-env和core-js处理js兼容 options: { //预设指示babel做怎样的兼容处理 presets: [ ['@babel/preset-env', { //按需加载 useBuiltIns: 'usage', //指定core-js版本 corejs: { version: 3 }, //指定兼容性做到哪个版本浏览器 targets: { chrome: '60', firefox: '60', ie: '9', safari: '10', edge: '17' } } ] ], //开启babel缓存, //会读取之前的缓存 //此方法会强制缓存文件,是的文件在缓存期间内无法被改变 //解决方法,每次要更新就给要更新的文件改变名字 cacheDirectory:true } }] } ] } ]
},
plugins: [
new webpack.DllReferencePlugin({
//告诉webpack哪些库不参与打包,同时使用是的名称也得变
manifest:resolve(__dirname,‘dill/manifest.json’)
}),
// //在HTML加载指定的资源
// new AddAssetHtmlWebpackPlugin({
// filepath:resolve(__dirname,‘dill/jquery.js’)
// })
// ,//生成HTML文件 new HtmlWebpackPlugin({ template: "./src/index.html", filename: "index.html", //压缩html代码 //压缩js代码只需要将mode改为production minify: { //清除空格 collapseWhitespace: true, //清除评论 removeComments: true } }), //将css从js文件抽取出来,//自带了一个loader分析处理css文件 new MiniCssExtractPlugin({ filename: "bundle.[hash:9].css" }), //压缩抽取出来的css文件 new OptimizeCssAssetsWebpackPlugin(), // new webpack.HotModuleReplacementPlugin() new WorkboxWebpackPlugin.GenerateSW({ /** * 1、帮助serviceworker快速启动 * 2、删除旧的serviceworker * 生成一个serviceworker配置文件 */ clientsClaim:true, skipWaiting:true })
],
/**-
代码分割
-
1.可以将node_modules中代码单独打包一个chunk最终输出
-
2.自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独的一个文件
/
optimization:{
splitChunks:{
chunks:‘all’,
minSie:301024 ,//分割的chunk最小为30kb
maxSize:0,//最大没有限制
minChunks:1,//要提取的chunk至少被引用一次
maxAsyncRequests:5 ,//按需加载时并行加载的文件的最大数目
maxInitialRequests:3,//入口js文件最大并行请求数量
automaticNameDelimiter:’~’,//名称连接符
name:true,//可以使用命名规则
cacheGroups:{//分割chunk的组
//node_modules文件会被打包到vender组的chunk中—>vender~xxx.js
//满足上面的公共规则
vendors:{
test:/[\/]node_modules[\/]/,
//优先级
priority:-10,}, default:{ //要提取的chunk至少被引用两次, minChunks:2, //优先级 priority:-20, //如果当前要打包的模块,和之前已经被提取的模块是同一个模块, //就会复用,而不是重新打包 reuseExistingChunk:true } }
},
//将当前模块的记录的其他模块的hash单独打包为一个文件runtime
runtimeChunk:{
name:entrypoint =>runtime-${entrypoint.name}
},
minimizer:[
//配置生产环境的压缩方案:js和cssnew TerserWebpackPlugin({ //开启缓存 cache:true, //开启多进程打包 parallel:true, //开启source-map sourceMap:true })
]
}
,
mode: ‘production’,
//解析模块规则
resolve:{
//配置解析模块路径别名:优点简写路径 缺点路径没提示
alias:{
css$:resolve(__dirname,‘src/css’)
},
//配合省略文件路径的后缀名
extensions:[’.js’,’.json’,‘jsx’],
//告诉webpack解析模块是去哪个目录找
modules:[resolve(__dirname,’./node_modules’),‘node_modules’]
},
externals:{
//当html使用cdn的方式引入第三方的库时,
//可以使用externals拒绝被引入的库进行打包,加快打包速度
jquery:‘jQuery’
},
devServer: {watchContentBase:true, watchOptions:{ //忽略文件,不监视node_modules中的文件 ignored:/node_modules/ }, //运行代码的目录 contentBase: resolve(__dirname, 'build'), port: 3000, open: true, compress: true, // hot:true//开启热更新功能 //不要显示启动服务器的日志信息 clientLogLevel:'none', //除了一些基本启动信息以外,其他内容都不要显示 quiet:true, //如果出错了,不要全屏提示 overlay:false, proxy:{ //一旦devserver服务器接受到/api/xxx的请求,就会把请求发送到另外一个服务器上 '/api':{ target:'http://localhost:3000', //发送请求时,路径重写:将/api/xxx--->/xxx(去掉/api) pathRewrite:{ '^/api':'' } } }
},
// devtool:‘inline-source-map’
} -
/**
- source-map:一种提供源代码到构建后代码的映射技术(如果构建后代码错了,通过映射
- 可以追踪到源代码错误的信息和错误位置)
- [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
- source-map:外部创建.map文件
- 错误代码准确信息,和源代码错误位置
- inine-source-map:内联,外部不生成.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、外部生成了.map文件,内联没有
- 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(速度快)
*/