概念
本质上,webpack是一个现代javascript应用程序的静态模块打包器
核心webpack.config.js
- 入口 entry
- 出口 output
- filename 文件名称
- path 地址
- mode模式
- development 开发模式
- production 产品模式
- plugins 插件
- html-webpack-plugin 处理html文件
- 使用 --const htmlWebpackPlugin = require(“html-webpack-plugin”);—plugins:[new htmlWebpackPlugin({})]
- 配置 模板template:__dirname+"/public/index.html";title:“firstPage”;minify:true压缩
- 模板语法 <%= htmlWebpackPlugin.options.title %>
- clean-webpack-plugin 清理dist目录
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
new CleanWebpackPlugin()
- copy-webpack-plugin 拷贝文件(设置静态资源目录)
const CopyWebpackPlugin = require('copy-webpack-plugin');
new CopyWebpackPlugin({
patterns:[
{from:xxx,to:xxx},
{from:yyy,to:yyy}
]
})
- devServer本地服务器
- host域名
- port端口
- hot热更新
- open 打开浏览器
- 安装 npm i webpack-dev-server -D
- 配置 “serve”:“webpack-dev-server --mode development”
//配置本地服务器
devServer:{
host:"localhost",//域名
port:8080,//端口
hot:true,//热更新
open:true //打开浏览
}
- loader —module rules规则
module:{
rules:[
{
test:/\.css$/,
use:["style-loader","css-loader"]
}
]
},
- resolve 配置
- alias别名
const path = require("path")
resolve:{
alias:{
'@':path.resolve(__dirname,'./src'),//设置@为src的别名
}
},
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// mode:"development",//配置模式
entry:"./src/index.js",//入口index.js文件
output:{
filename:"main.js",//文件名
path:__dirname+"/dist" //地址
},
//定义出口
plugins:[
new htmlWebpackPlugin({
title:"我的第一个webpack",
minify:true,
template:__dirname+"/public/index.html"
})
]
}
命令配置 在package.json下的script
- “dev”:“webpack --mode development” 配置开发模式命令
- “start”:“webpack” 运行
- “build”:“webpack --mode production” 配置产品模式命令
- 执行
- npm run dev
- npm run build
{
"name": "mypack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start":"webpack",
"dev":"webpack --mode development",
"build":"webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
loader和plugin的区别
- loader让webpack有处理非js文件的能力
- webpack运行时plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果
loader
处理css
- css-loader 分析css关系,需要加载哪些css文件
- style-loader 把css插入到html head标签里面
- mini-css-extract-plugin.loader css抽取为单独文件
const minCssExtractPlugin = require("mini-css-extract-plugin");
plugins:[
new htmlWebpackPlugin({
title:"我的第一个webpack",
minify:true,
template:__dirname+"/public/index.html"
}),
new minCssExtractPlugin({
filename:'style.css'
})
],
- optimize-css-assets-webpack-plugin 压缩css
const optimizeCss = require("optimize-css-assets-webpack-plugin");
optimization:{
//压缩器
minimizer:[new optimizeCss()]
},
- less 处理less文件||less-loader 加载less文件
{
test:/\.less$/,
use:[minCssExtractPlugin.loader,"css-loader","less-loader"]
}
- 处理css前缀
postcss-loader—autoprefixer
处理文件(图片)
- file-loader
- url-loader
- 将小的图片转换为base64格式
- 处理字体
{
test:/\.(eot|woff2|woff|ttf|svg)$/,
use:[{loader:'url-loader',options:{limit:10,name:'font/[name].[hash:5].[ext]'}}]
},
- 处理图片
{
test:/\.(png|gif|bmp|jpg|jpeg|svg|ico)$/,
use:[{loader:'url-loader',options:{limit:100000,name:'images/[name].[hash:5].[ext]'}}],
//使用url-loader (加载文件,渲染为低于1000b 就压缩为base64个)
//文件的名称 存放咋images文件夹名称原来一致[name].添加hash[hash:5].默认后缀ing.[ext]
//esModule:不采用模块
}
浏览器的缓存机制
文件名没有改变。默认浏览器会自动缓存这个文件,第二次去访问网站的时候,浏览器发起http请求前会先从缓存列表查询,如果有就直接从缓存读取,这样加快网页的加载
我的文件内容以及修改,浏览器还使用的缓存文件(会发生不可期的结果)
只有文件内容发生改变,修改下文件名称(文件指纹)通常hash算法
三个hash
- hash 只要项目里有文件更改,整个项目构建的hash值都会更改
- chunkhash 每一次构建后生成的哈希值都不一样
- [name]默认的chunkname
- [contenthash:7]截取7位
包版本管理
- ^3.145不会超过4.0
- ^0.2.3不会超过0.3
- ~3.1.2不会超过3.2
- @指定版本
npm安装
产品模式
- npm install xxxx --save
- npm i XXX -S
开发模式 - npm install xxx --save-dex
- npm i xxx -D
- devDependencies 开发依赖 工具文件不会被打包上传
react webpack环境
- 安装
- babel-loader 处理es6文件
- @babel/core babel核心模块
- @babel/preset-env 环境预设
- @babel/preset-react react运行环境jsx语法支持
- babel/polyfill 把es6的方法转换为ES5
- @babel/plugin-transform-runtime"按需加载polyfill方法
- 安装 -S
- react react方法
- react-dom 渲染dom
- babelrc配置
{
"presets":["@babel/preset-env","@babel/preset-react"],
}
- 写index.js
import ReactDom from 'react-dom'
import React,{Component} from 'react'
//导入react reactdom
class App extends Component{//定义app组件
constructor(props) {
super(props)
this.state = {name:"mumu",age:18}
//定义 状态state
}
render(){
return (<div><h1>我的名字是:{this.state.name},今年{this.state.age}</h1>
<button onClick={()=>{this.setState({age:this.state.age+1})}}>一年过去了</button>
</div>
)
}
}
ReactDom.render(<App/>,document.getElementById("root"))
//把app组件渲染到 rootdiv里面
优化optimization
- minimizer压缩
- new optimizeCSS()压缩优化css
- new UglifyjsWebpackPlugin()压缩优化js
- 分割js代码
解释:把import导入的代码单独打一个文件,如果这个文件超过3k又会再被分割
splitChunk分割模块
- chunks模块名
- splitChunks:{chunks:“all”//“initial”}
devtools开发工具
- cheap-module-eval-source-map 开发模式
- cheap-module-source-map 产品模式
动态加载
import("xxx")
.then(({default:$})=>{})
- webpack魔法注释
/*webpackChunkName:"jquery"*/
分割文件名
/*webpackPrefetch: true*/
提前加载
webpack环境变量 配置文件切换 动态加载
- 关于目录
path.resolve(__dirname,'../public/index.html')
- path解决路径的文件
- __dirname 当前所在目录
../public/index.html
- 结果 c:/mypack/public/index.html
- 配置文件
- 基础 config/webpack.com.js
- 开发 config/webpack.dev.js
mode:"development"
devtool:"cheap-module-eval-source-map"
- 产品 config/webpack.prod.js
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
//导入基础配置
module.exports = {
devtool:'cheap-module-source-map',
mode:'production',
plugins:[new CleanWebpackPlugin()]
}
- 配置入口文件 webpack.config.js
const {merge} = require("webpack-merge");
//两个配置 合并到一个配置文件里面
const commonConfig = require("./config/webpack.com.js");
//导入基础配置
const devConfig = require("./config/webpack.dev.js");
const prodConfig = require("./config/webpack.prod.js");
module.exports = (env,args)=>{
console.log(args,"args");
if(env.production){
return merge(commonConfig,prodConfig);
}else{
return merge(commonConfig,devConfig);
}
}
- script的传值
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"dev": "webpack --env.development",
"build": "webpack --env.production",
"serve": "webpack-dev-server --env.production"
},
webpack优化方式
- 懒加载import,提前加载prefetch
- 通过hash文件指纹增强浏览器缓存
- 压缩图片、css、js
- splitChunks 分割比较大的依赖包
- 按需加载 treeshake
切换配置
- script里面传递参数
- merge导入合并 配置文件
- 根据参数的不一致,实现生产环境,与产品环境配置的切换
如何传递参数
- script --mode production
- 如果想在前端代码中获取当前的开发环境
- process.env(只能在开发环境中)
- 根据env的不同,配置不同的http请求域名
- 使用
- 安装cross-env 苹果系统和windows系统设置环境变量方式不一样
- script传递参数
"serve":"cross-env http_env=development webpack-dev-server --env.development"
- 设置哪些变量可以在前端访问
const webpack = require("webpack")
new webpack.DefinePlugin({
'process.env':{
'http_env':JSON.stringify(process.env.http_env)
}
})
- 前端获取
const ENV = process.env.http_env
console.log("根据env",ENV,"切换域名实现相关业务")
vue运行环境
- 安装
- vue
- vue-loader 处理.vue文件
- vue-style-loader 处理vue style样式
- vue-temolate-compiler 编译模块文件
- vue-hot-reload-api 热更新
- babel
- babel es6转es5
- babel-loader@7 处理loader 指定版本7
- babel-core 核心
- babel-plugin-transform-runtime 按需加载
- babel-preset-es2015 es2015 ES6运行环境
- babel-runtime
- babel-polyfill es6-es5函数
- .babelrc
{
"presets":["@babel/preset-env","@babel/preset-react"],
}
- loader
{
test:/\.vue$/,
loader:'vue-loader',
options:{
loaders:{
css: [minCssExtractPlugin.loader,'style-loader', 'css-loader'],
less: [minCssExtractPlugin.loader,'css-loader', 'less-loader'],
}
}
},
- plugin
const UglifyjsWebpackPlugin = require("uglifyjs-webpack-plugin");
//获取vue-loader
new VueLoaderPlugin(),
多文件入口
- entry入口
vue:path.resolve(__dirname,'../src/main.js'),
react:path.resolve(__dirname,'../src/index.js')
- output出口
filename:"[name]-[hash:7].js",//文件名
path:path.resolve(__dirname,"../dist") //地址
- plugin
new htmlWebpackPlugin({
title:"vue,我的第一个webpack",//标题
minify:true,//压缩
chunks:['vue'],
template:path.resolve(__dirname,"../public/index.html")
}),
new htmlWebpackPlugin({
title:"react,我的第一个webpack",//标题
minify:true,//压缩
chunks:['react'],
template:path.resolve(__dirname,"../public/react.html"),
filename:'react.html'
}),
new VueLoaderPlugin(),