- 一:背景介绍
- 二:安装、打包过程
- 三:webpack实战、配置
- 1、entry 入口
- 2、output 输出
- 3、mode 模式
- 4、loader 加载器/解析器
- 7、处理图片
- 8、处理js
- 9、合并配置文件 区分本地还是开发环境
- 10、压缩代码
- 11、优化,删除无用的css
- 12、安装配置react
- 13、Tree-shaking && scope-Hosting
- 14、DllPlugin && DllReferencePlugin 主要开发环境下用
- 15、 动态加载组件
- 17、 打包文件分析工具
- 18、splitChunks
- 19、externals 如果cdn引入,这样引用不会加大体积
- 20、热更新
- 21、费时更新
- 22、 resolve 设置别名
- 23、 happypack 多线程打包
- 24、参考
一:背景介绍
工程化项目需要、前端要求提高
二:安装、打包过程
安装:npm i webpack webpack-cli -D 打包:npx webpack 、 全局webpack、package中设置
三:webpack实战、配置
1、entry 入口
2、output 输出
const path = require('path')output:{filename:'bundle.js',path:path.resolve(__dirname,"dist")}
3、mode 模式
可选: none、development、production
4、loader 加载器/解析器
webpack默认只能处理js和json文件,我们需要通过loader去转换成webpack可以处理的文件
test: 处理文件扩展名的正则表达式
use: 要使用的模块加载器的名称
include/exclude: 手动指定必须要处理的文件或者屏蔽的文件
options:为loaders配置额外设置选项
- 解析css文件 style-loader、css-loader 、postcss-loader // 处理css3私有前缀 , 需要配合autoprefixer(私有前缀插件)
- 解析less less 、less-loader
- 解析sass node-sass、sass-loader
- 解析stylus stylus、stylus-loader
- 分离css的插件 生产环境下 mini-css-extract-plugin
```javascript module:{ rules:[ {
] }test:/\.css$/,use:["style-loader",{loader:"css-loader",options:{importLoaders:1 // 添加一个加载器帮忙处理}},"postcss-loader","less-loader"]}
// postcss.config.js modules.exports ={ plugins:[{ require(‘autoprefixer’) }] } // .browserslistrc cover 99.5%
<a name="cp158"></a>#### 5、plugin 插件 —— 扩展功能- html-webpack-plugin 自动引入html,并产生打包后的文件,添加hash指纹等```javascriptconst HtmlWebpackPlugin = require('html-webpack-plugin')plugins:[new HtmlWebpackPlugin({template:"./index.html",hash:true,minify:{removeAttributeQuotes:true,collapseWhitespace:true,removeComments:true},filename:'index.html',chunks:["index"], // 应用于多入口时,指定引入的js文件名inject:"body"})]
webpack-dev-server 创建一个本地的开发服务,自动打开html文件
devServer:{port:6666,open:true,compress: true, // 开启gzip压缩contentBase: path.resolve(__dirname,'dist') // 修改访问静态资源的路径}
clean-webpack-plugin 清除输出目录,可以指定排除
const CleanWebpackPlugin = require('clean-webpack-plugin')plugins:[new CleanWebpackPlugin({cleanOnceBeforeBuildPatterns:["aa/**/*","!aa/c.js"] // 清理aa下的文件,排除aa下c.js})]
mini-css-extract-plugin 分离css,添加hash ```javascript
配合:然后把loader中的 style-loader换成{loader:MiniCssExtractPlugin.loader}
plugins:[ new MiniCssExtractPlugin({ filename:”css/[name].[contentHash:4].css” // 4 是设置hash长度 }) ]
<a name="oCMXc"></a>#### 6、配置多入口、多出口打包```javascriptentry:{index:'./src/index.js',other:'./src/other.js'}output:{filename:'[name].js',path:path.resolve(__dirname,"dist")}// 配置HtmlWebpackPlugin chunks, 很多的时候可以通过数组遍历插入let htmlPlugin = ['index','other'].map((chunkName)=>{return new HtmlWebpackPlugin({template:`./${chunkName}.html`,hash:true,minify:{removeAttributeQuotes:true,collapseWhitespace:true,removeComments:true},filename:`./${chunkName}.html`,chunks:[chunkName], // 应用于多入口时,指定引入的js文件名inject:"body"})})// 使用plugins:[...htmlPlugin]
7、处理图片
file-loader url-loader
使用file-loader,会将图片进行打包,并将打包后的路径返回
url-loader,会
/*{test:/\.(jpe?g|png|gif)$/,use:{loader:'file-loader',options:{name:`img/[name].[ext]`}}},*/{test:/\.(jpe?g|png|gif)$/,use:{loader:'url-loader',options:{// 小于30kb用base64的形式处理,大于30kb用file-loader处理limit:30*1024,name:`img/[name].[ext]`}}},
html-withimg-loader 处理, 图片的引用路径就不是之前的了,就变成之后的路径了
{test:/\.(html)$/i,use:{loader:'html-withimg-loader'}}
处理icon-font
// index.jsimport "./icon/iconfont.css";let i = document.createElement("i");i.className = "iconfont icon-course";document.body.appendChild(i);
{test:/\.(eot|svg|ttf|woff2)$/,use:"file-loader"}
8、处理js
@babel/core 核心模块
@babel/preset-env 将es6处理成es5插件的集合
babel-loader webpack和babel的桥梁
布丁
core-js@3 使用高版本js的布丁
@babel/plugin-proposal-class-properties 安装一下这个插件处理class
@babel/plugin-proposal-decorators 保留装饰器
优化 加快构建效率,减少冗余代码
@babel/plugin-transform-runtime
@babel/runtime
// index.jslet a1 = Object.assign({},{"a":1})console.log(a1)[1,2,3].includes(1)async function fn(){console.log(1)}@logclass People{a = 1;};function log(target){console.log(target);}new People();
// webpack.config.js{test:/\.js$/,use:"babel-loader",exclude:/node_modules/}// .babelrc 文件{"presets":[["@babel/preset-env",{"useBuiltIns":"usage", // 按需加载 使用了api就会转化哪个"corejs": 3}]],"plugins":["@babel/plugin-transform-runtime","@babel/runtime",["@babel/plugin-proposal-decorators",{ "legacy":true }], // 保留装饰器["@babel/plugin-proposal-class-properties",{"loose":true}], // 处理class]}
添加eslint
npm i eslint eslint-loader -D
可以去eslint选择配好在下载
也可以npx eslint —init 初始化配置文件 手动选择
// webpack.config.js{test:/\.js$/,use:"eslint-loader",enforce:"pre" // 优先处理}
9、合并配置文件 区分本地还是开发环境
webpack.base.js 公共的配置文件
webpack.dev.js 开发环境的配置文件
webpack.prod.js 生产环境下的配置文件
通过webpack-merge合并
npm i webpack-merge -D
"scripts":{"dev": "npx webpack --env.development --config webpack.base","build": "npx webpack --env.production --config webpack.base","dev:server":""}
// webpack.base.jsconst dev = require('./webpack.dev');const prod = require('./webpack.prod');const { merge } = require("webpack-merge");module.exports = (env) =>{console.log(env)const isDev = env.development;let base = {}if(isDev){// 合并base 和 devreturn merge(base,dev)}else{// 合并base 和 prodreturn merge(base,prod)}}




10、压缩代码
optimize-css-asstes-webpack-plugin 压缩css代码
terser-webpack-plugin 压缩js代码
// 生产环境下// webpack.prod.js 文件const OptimizeCsAsset = require('optimize-css-asstes-webpack-plugin')const TerserWebpackPlugin = require("terser-webpack-plugin")module.exports = {mode:"production",optimization:{minimizer:[new OptimizeCsAsset(),new TerserWebpackPlugin()]}}
11、优化,删除无用的css
purgecss-webpack-plugin
glob // 设置查找文件的路径和匹配的文件
// 生产环境下// webpack.prod.js 文件const PurgecssPlugin = require("purgecss-webpack-plugin")module.exports = {mode:"production",plugins:[new PurgecssPlugin({paths:glob.sync(`${path.resolve(__dirname,"src")}/**/*`,{nodir:true})})]}
12、安装配置react
安装@babel/preset-react -D
安装 react react-dom
// .babelrc 文件{"presets":[["@babel/preset-env",{"useBuiltIns":"usage", // 按需加载 使用了api就会转化哪个"corejs": 3},"@babel/preset-react"]],"plugins":["@babel/plugin-transform-runtime","@babel/runtime",["@babel/plugin-proposal-decorators",{ "legacy":true }], // 保留装饰器["@babel/plugin-proposal-class-properties",{"loose":true}], // 处理class]}
import './index.css';import React from "react";import ReactDOM from "react-dom";React.DOM.render(<h1 className="a1">zf</h1>,document.getElementById("root");
13、Tree-shaking && scope-Hosting
把没用的内容摇晃掉
// package.json中设置sideEffects唯一一个需要在package.json中去设置的"sideEffects":["**/*.css"]
// 引入不使用,不会打包进去import "./index.css"import "./count"
scope-Hosting (了解、自带)作用 减少代码体积,节约内存
webpack配置优化重点考虑 1)打包的大小 2)打包的速度 3)模块的拆分
14、DllPlugin && DllReferencePlugin 主要开发环境下用
DllPlugin 设置动态链接库(webpack自带)
DllReferencePlugin 引用动态链接库 mainfest.json
// 把js文件插入到html文件中
npm i add-asset-html-webpack -D
把第三模块或者第三方库单独打包成动态链接库,以后构建的时候只需要查找构建好的库就行了
// package.json"srcipts":{"dll":"npx webpack --config ./webapacl.dll"}
// webpack.dll.js 文件 动态链接库// 还需要一个缓存列表 指向打包后的文件const path = require("path")const Dllplugin = require("webpack").DllPlugin; // 动态链接库module.exports={mode:"development",//entry:"./src/count.js",entry:['react','react-dom'],output:{library:"react", // 用来接收打包后自执行函数返回值的名字libraryTarget:"commonjs2", // commonjs umd 默认var接收filename:'react.dll.js',path:path.resolve(__dirname,"dll")},plugins:[new DllPlugin({name:'react',path:path.resolve(__dirname,'dll/mainfest.json') // 缓存文件的路径})]}
// webpack.base.jsconst DllReferencePlugin = require('webpack').DllReferencePluginconst AddAsserHtmlPlugin = require('add-asser-html-plugin'plugins:[new DllReferencePlugin({mainfest: path.resolve(__dirname,"dll/mainfest.json") // 引入动态链接库缓存列表}),new AddAsserHtmlPlugin({filepath:path.resolve(__dirname,"dll/react.dll.js")})]


建议在开发环境下采用这种方案,有利于我们提升构建速度的,生产环境有更优的方案
dll这种方案在开发之前先抽离好,以后就不用打包了
15、 动态加载组件
实现点击后动态加载文件
- webpackChunkName
- webpackPrefetch 利用浏览器空闲时间把动态模块加载完成并引入进来
- webpackPreload 根主模块的代码同时加载
```javascript // count.js// index.jslet btn = document.createElement("button");btn.addEventListener("click",()=>{import(/* webpackChunkName:'count' */"./count").then(data=>{console.log(data.add(10,20))})})btn.innerHTML = "点我"document.body.appendChild(btn)
<a name="FGB9p"></a>#### 16、souce-map (代码排查错误)开发环境推荐 cheap-module-eval-source-map<br />生产环境推荐 cheap-module-source-map```javascriptdevtool:"cheap-module-eval-source-map"
17、 打包文件分析工具
bundle-analyzer-plugin
const { BundleAnalyzerPlugin} = require('bundle-analyzer-plugin')plugins:[new BundleAnalyzerPlugin()]
18、splitChunks
在编译时可以抽离第三方莫款或公共模块,不要根dllPlugin同时用,会出问题
和上面的分析工具一起用
optimization: {splitChunks: {chunks: 'async',minSize: 30000,maxSize: 0,minChunks: 1,maxAsyncRequests: 5,maxInitialRequests: 3,automaticNameDelimiter: '~',name: true,cacheGroups: {vendors: {test: /[\\/]node_modules[\\/]/,priority: -10},default: {minChunks: 2,priority: -20,reuseExistingChunk: true}}}
19、externals 如果cdn引入,这样引用不会加大体积
externals:{'jquery':'$'}
20、热更新
代码修改后不刷新就可以更改样式
devServer:{hot:true // 开发时需要,}
if(module.hot){module.hot.accept("./count",()=>{p.innerHTML = add(10,20)})}
21、费时更新
speed-measure-webpack-plugin
22、 resolve 设置别名
resolve:{extensions:['.js','.jsx','.json','.css'], // 按顺序解析后缀名alias:{} // 设置别名}
23、 happypack 多线程打包
npm i happypack -D
