一:基本配置
1. webpack默认的配置只能解析js,和json
webpack启动配置 内置了很多的函数功能,目的是为了让浏览器能解析我们js(因为还有浏览器不支持require ecports module)
因为为了解决浏览器支持而内置的js功能,导致webpack不适合构建库;适合构建项目工程,用强大的编译功能提高效率
vue、react源码是用rollup 代码比较纯粹。
const path = require(‘path‘) module.exports = { entry:‘./src/index.js‘, mode:‘development‘, // mode:‘production‘, //会代码分割,会压缩,output后的文件是1.main.js output:{ path:path.resolve(__dirname,‘./dist‘), //path:绝对路径的字符串 filename:‘main.js‘ } }
2.webpack有默认的配置文件,叫webpack.config.js
"script":{ "dev":"webpack", //使用默认的配置文件 "build":"webpack --config webpack-config.js" // 或者通过--config webpack-config.js 来指定webpack使用哪个配置文件来执行构建 }
3.entry (入口) 可以是字符串、数组、对象
module.exports = { entry:‘./src/index.js‘ //可以是字符串 // 数组 entry:[‘./src/index.js‘] // 多个数组元素会被打包到一个文件 // 对象 entry:{ // index:‘./src/index.js‘ // } }
多入口多出口 如果多入口一个出口就会出错
entry:{ main:‘./src/index.js‘, other:‘./src/other.js‘ }, output:{ path:path.resolve(__dirname,"./dist"), filename:"[name].js" //name是占位符 }
4. mode:none、development、production
默认设置的是 production
开发阶段的开启有利于热更新的处理,识别哪个模块的变化;
生产阶段的开启有利于模块压缩、处理副作用等一些功能
5.output -> filename:[name]_[chunkhash:8].js
hash chunkhash contenthash
hash 整个文件hash值都相同 一处改变 其他都会变
chunkhash 对应的css和js文件改变 与其关联的hash值就会改变 但其内容并未改变 这样就达不到缓存的效果
contenthash(针对内容,只要内容不一样,hash值就会不一样)
js 推荐使用chunkhash
在使用chunkhash时候 css改变后 引入css的js打包后文件也会改变。所以contenthash就出来了,针对内容改变才会去改变
css 推荐contenthash 把css都抽离出对应的css文件加以引用
6.loader
module:{ rules:[ { test:/\.css$/, //loader的执行顺序 从右往左 // css-loader: 把样式代码写入js ,这一步还不够,样式不起作用 // style-loader:把写入的js样式,插入到index.html中 (html.head.style中) use:["style-loader","css-loader"] }, { test:/\.png$/, //use:["file-loader"] //给loader添加参数 use:{ loader:‘file-loader‘, options:{ name:"[name].[ext] } } } ] }
7.plugins
html-webpack-plugin
//会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到html中 const htmlWebpackPlugin = require("html-webpack-plugin-) plugins:[ new htmlWebpackPlugin({ title:‘测试标题‘, template:‘./index.html‘ ,//使用哪一个作为模板 filename:‘index.html‘, //打包后的filename }) // 设置完标题后需要在index.html中 将title更换掉 //<title> <%= htmlWebpackPlugin.options.title %></title> ]
clean-webpack-plugin
plugins:[ //在构建之前,将dist文件删除掉 new CleanWebpackPlugin() ]
mini-css-extract-plugin
//把css提取成独立文件 { test:/\.css$/, use:[MiniCssExtractPlugin.loader,"css-loader"] } new MiniCssExtractPlugin({ filename:"[name][chunkhash:8].css" })
8.sourceMap
// none 若要关闭配置,则设置为none // source-map:产生.map文件、 // eval:速度最快,使用eval包裹模块代码、 // cheap:较快,不包含列信息、 // Module:第三方模块,包含loader的sourcemap(比如jsx to js ,babel的sourcemap)、 // inline:将.map作为dataURI嵌入,不单独生产.map文件 配置推荐: devtool:"cheap-module-eval-source-map" //开发环境部署 //线上不推荐开启devtool:暴露代码&影响解析速度 devtool:‘cheap-module-source-map‘ //线上生成配置
二.热更新&热模块更新
热更新 每次修改后浏览器会自动刷新一次
热模块更新 修改css 时候 局部更新
webpack插件中自带了HotModuleReplacement (HMR)
plugins:[
webpack.HotModuleReplacementPlugin()
]
可以在devServer.hot 设置为true 就会开启热更新
hotOnly:true 无论代码如何改变 都不会刷新浏览器
但是当手动更改原生js时候 需要手动的去监听
if(module.hot){ module.hot.accept(‘./index.js‘,()=>{ //重新执行一遍操作 }) }
用到vue、react、angular时候 webpack提供了相应的loader 例如vue-loader 只有原生js需要手动去监听变化然后热更新
module:{ rules:[ { test:/\.vue$/, loader:[‘vue-loader‘] } ] }
//需要安装 npm i babel-loader @babel/core @babel/preset-env -D
1. babel-loader 是webpack与babel的通信桥梁,不会做 把es6转成es5的工作,这部分工作需要用到@babel/preset-env来做
2. @babel/core提供了核心的库和API。
3. @babel/preset-env 里包含了es6、7、8转es5的转换规则
{ test:/\.js$/, use:{ loader:‘babel-loader‘, options:{ presets:["@babel/preset-env‘] } } }
只转换了const let 箭头函数等一些基础的语法
但是promise等新特性 低版本浏览器不知道
方法:把新特性的语法引进来 polyfill (包含了所有新特性)
//需要安装 @babel/polyfill nom i @babel/polyfill -S
打包后的体积变大了,因为polyfill把所有新特性都引进来了,我们需要实现按需加载
{ test:/\.js$/, use:{ loader:‘babel-loader‘, options:{ presets:["@babel/preset-env‘,{ targets:{ edge:"17", firefox:"60", chrome:"67", safari:"11.1" }, corejs:2, // 新版本需要指定核心库版本 useBuiltIns:"usage" //按需注入 ,有3个可选值,推荐使用usage }] } } }
polyfill与transform-runtime的区别
polyfill是以什么方式引入新特性:直接挂在全局对象上 window 造成的后果:会污染全局变量
polyfill 不适合构建开源库 UI库
当我们开发组件库,工具库的时候 polyfill就不适合了,因为polyfill是注入到全局变量,window下会污染全局环境,所以推荐闭包方式:@babel/plugin-transform-runtime 它不会造成全局污染
transform-runtime
//需要安装 npm i @babel/plugin-transform-runtime -D npm i @babel/runtime -S { test:/\.js$/, use:{ loader:‘babel-loader‘, "plugins":[ [ "@babel/plugin-transform-runtime", { "absoluteRuntime":false, "corejs":false, "helpers":true, "regenreator":true, "useESModules":false }] ] } }
可以把上述代码抽出来,放在.babelrc文件中
{ "presets":[ ["@babel/preset-env‘,{ targets:{ edge:"17", firefox:"60", chrome:"67", safari:"11.1" }, corejs:2, // 新版本需要指定核心库版本 useBuiltIns:"usage" //按需注入 ,有3个可选值,推荐使用usage }] ], //plugins 当react代码不是用jsx的语法 而是 createElement的方式 ,需要将react转化一下 //vue 就用 transform-vue-jsx "plugins":["@babel/presets-react"] }
三.webpack 性能优化(能用绝对路径的就用绝对 绝对查询速度高于相对)
1.loader
include & exclude
2.
resolve:{ //用来配置webpack去哪里找第三方相关的模块 modules:[path.resolve(__dirname,"./node_modules")], //设置别名 来将原导入路径映射成一个新的导入路径 //默认情况下,webpack会从入口文件 ./node_modules/bin/react/index开始递归解析和处理依赖文件,我们可以直接指定文件,避免此处的耗时 alias:{ "@":path.join(__dirname,"src"), "react":path.resolve(__dirname,"./node_modules/react-dom/umd/react.production.min.js"), "react-dom"... }, //在导入语句没带后缀时,webpack会自动带上后缀后,去查找文件是否存在 // 后缀尝试列表尽量的少,导入语句尽量带上后缀 extensions:[".js",".json"] }
3.tree shaking
①.css
npm i glob-all purify-css purifycss-webpack --save-dev const PurifyCSS = require(‘purifycss-webpack‘) const glob = require(‘glob-all‘) plugins:[ new PurifyCSS({ path:glob.sync([ //要做css tree shaking的路径文件 path.resolve(__dirname,‘./src/*.html‘) //请注意,我们同样需要对html文件进行tree shaking path.resolve(__dirname,‘./src/*.js‘) ]) }) ]
②.js(只支持es module 的模块方式 import方式引入,不支持commonjs require的方式引入)
js tree shaking在开发模式下 是不生效的 只有在生产环境才会生效 为了方便调试
optimization:{ usedExports:true //哪些导出的模板被使用了 }
只要将mode设置为production 就会自动开启js 摇树功能