本质上,Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图(Dependency Graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
在开发中一般会使用less,sass,vue等需要转化为浏览器可以识别的css,js,html,es6->es5
压缩代码,兼容处理
口指示webpack以哪个文件为入口起点开始打包,分析构建内部的依赖图。
输出指示 webpack打包后的资源bundles输出到哪里去,以及如何命名
让webpack去处理非JavaScript资源的文件,比如css、img等,将他们可以处理成一个webpack可以识别的资源,可以理解成一个翻译的过程。(webpack自身只能理解json和js)
插件可以用来执行更加广的任务,插件的范围包括打包优化和压缩
模式指示webpack使用相应模式的配置。
开发模式(development):配置比较简单,能让代码本地调试运行的环境。
生产模式(production):代码需要不断优化达到性能最好。能让代码优化上线运行的环境。
都会自动启用一些插件,生产模式使用插件更多
npm init -y
//生成package.json文件
npm i webpack webpack-cli --save-dev

//webpack.config.js
const path = require('path') // 引用path模块
module.exports = {
entry:"./src/index.js", // 入口文件
output:{ // 出口文件
path:path.resolve(__dirname,'build'),// 输出的路径 是绝对路径
filename:'build.js', // 输出的文件名称
},
mode:"production"// 使用生产
}
html-webpack-plugin 是 webpack 中的 HTML 插件,可以通过此插件自定制 index.html 页面的内容。
HTML 插件复制的 index.html 页面,到dist目录下,自动注入了打包的 bundle.js 文件

npm i --save-dev html-webpack-plugin
const path = require('path') // 引用path模块
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:"./src/index.js", // 入口文件
output:{ // 出口文件
path:path.resolve(__dirname,'./dist'),// 输出的路径 是绝对路径
filename:'build.js', // 输出的文件名称
clean:true,//清除之前遗留的旧的文件
},
mode:"production",// 使用生产
plugins:[
new HtmlWebpackPlugin({
template:'./index.html',//模板
filename:'app.html',//输出文件名
inject:'body'//打包生成的script所在html的位置,默认在head标签里面
})]
}
// webpack.config.js
mode:"development",// 使用开发
devtool:'inline-source-map',//在开发模式下正常显示build.js下的js代码
development模式下编译的build.js

转化完


npm install webpack-dev-server -D
devServer:{
static:'./dist',//devServer指向的路径
},

不输出物理文件,把打包好的文件放到内存里,把dist文件夹删掉也可以
module:{
rules:[//配置不同对象去加载不同类型的文件
{
test:/\.png$/,//通过正则表达式,判断加载文件的类型
type:'asset/resource',
generator:{//定义文件的名字和路径
filename:'images/[contenthash][ext]'
}
}
]
}
打包出来一个图片资源

//页面显示出来图片
import imgsrc from '../assets/1.png'//imgsrc 是一个url地址
const img=document.createElement('img')
img.src=imgsrc
document.body.appendChild(img)
不导出新的图片 ,生成base64格式路径
{
test:/\.jpg$/,//导入jpg文件
type:'asset/inline',
}
{
test:/\.txt$/,//导入文本文件
type:'asset/source',
},
默认大于8k就生成新文件
{
test:/\.jpg$/,//导入jpg文件
type:'asset',
parser:{//设置最大值,大于这个值就生成文件
dataUrlCondition:{
maxSize:4*1024*1024//4兆,默认4*1024
}
}
},
import './index.css';
//不配置会报错

npm install css-loader -D
npm install style-loader -D//帮助我们把css布局到页面
{
test:/\.css$/,//加载css文件
use:['style-loader','css-loader']//注意顺序
}
//在head标签里面加载出style

npm install less-loader less -D
{
test:/\.(css|less)$/,//加载css文件
use:['style-loader','css-loader','less-loader']//注意顺序,从右往左解析
}
import './style.less';
npm install mini-css-extract-plugin -D //抽离所以css文件组合成一个
npm install css-minimizer-webpack-plugin -D//css文件压缩
1.引入const MiniCssExtractPlugin=require('mini-css-extract-plugin')
const CssMinimizerPlugin=require('css-minimizer-webpack-plugin')
2.plugins中实例化
plugins:[
new MiniCssExtractPlugin({
filename:'styles/[contenthash].css'//修改打包出来的文件地址,contenthash根据css内容生成哈希字符串
})
],
3.删除style-loader,配置MiniCssExtractPlugin.loader
module:{
rules:[//配置不同对象去加载不同类型的文件
{
test:/\.(css|less)$/,//加载css文件
use:[MiniCssExtractPlugin.loader,'css-loader','less-loader']//注意顺序,从右往左解析
},
]
},
4. 修改 mode:"production",
5. optimization:{//和entry平级
minimizer:[
new CssMinimizerPlugin()
]
}
style.css
@font-face {
font-family: 'iconfont';
src: url('../assets/iconfont.ttf') format('truetype');
}
.icon{
font-family: 'iconfont';
}
{
test:/\.(woff|woff2|eot|ttf|otf)$/,//加载字体
}
npm install csv-loader xml-loader -D
{
test:/\.(csv|tsv|$)/,
use:'csv-loader'
},
{
test:/\.xml$/,
use:'xml-loader'
}
npm install toml yaml json5 -D
//导入
const toml=require('toml')
const yamo=require('yaml')
const json5=require('json5')
{
test:/\.toml$/,
type:'json',
parser:{//解析器
parse:toml.parse
}
},
{
test:/\.yaml$/,
type:'json',
parser:{//解析器
parse:yaml.parse
}
},
{
test:/\.json5$/,
type:'json',
parser:{//解析器
parse:json5.parse
}
}
npm install babel-loader @babel/core @babel/preset-env
npm install @babel/runtime -D
npm install @babel/plugin-transform-runtime -D
babel-loader :解析es6
@babel/core:核心模块
@babel/preset-env:预设,一组插件集合
{
test:/\.js$/,
exclude:/node_modules/,//排除node module里面的js代码
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
entry:{// 入口文件
index:{
import:'./src/index.js',
dependOn:'shared'//可以把共享的文件定义出啦
},
another:{
import:'./src/another-module.js',
dependOn:'shared'//可以把共享的文件定义出啦
},
shared:'lodash'//当两个模块都有lodash模块的时候,抽离出来,取名shared
},
entry:{ // 入口文件
index:'./src/index.js',
another:'./src/another-module.js'
},
optimization:{
splitChunks:{//代码分割,抽离公共的保存到一个文件
chunks:'all'
}
}
//懒加载
button.addEnentListener('click',()=>{
import(/*webpackChunkName:'math'*/'./1.js').then((res)=>{
res.add(2,3)
})
})
//预加载webpackPrefetch:true
button.addEnentListener('click',()=>{
import(/*webpackChunkName:'math',webpackPrefetch:true*/'./1.js').then((res)=>{
res.add(2,3)
})
})
当文件内容发生改变,而文件名没有改变的时候,浏览器会使用缓存,
所以要使用’[name].[contenthash].js’
output:{ // 出口文件
filename:'[name].[contenthash].js', // 输出的文件名称,contenthash根据文件内容生成哈希字符串,文件名随着文件内容变化而变化
},
optimization:{
minimizer:[
new CssMinimizerPlugin()
],
splitChunks:{//代码分割,抽离公共的保存到一个文件
cacheGroups:{
vendor:{
test:/[\\/]node_modules[\\/]/,
name:'vendors',
chunks:'all'
}
}
}
}
output:{ // 出口文件
publicPath:'http://localhost:8080/'//设置公共路径
},

消除开发和生产环境的差异
npx webpack --env production
//转成一个函数
module.exports =(env)=> {
//如果传入值了就用
mode:env.production?'production':'development',// 模式
}
因为 minimizer:[new CssMinimizerPlugin() ],配置css压缩所以手动配置
npm install terser-webpack-plugin -D //压缩js文件
const TerserPlugin=require('terser-webpack-plugin')
minimizer:[
new CssMinimizerPlugin(),
new TerserPlugin()
],
webpack.config.dev.js
webpack.config.prod.js
npm webpack -c ./config/webpack.config.dev.js//指定文件
//package.json
{
"scripts": {
"start": "npx webpack serve -c ./config/webpack.config.dev.js",
"build":"npx webpack -c ./config/webpack.config.prod.js"
}
}
npx run start

最终得出最好的两种方案 --> source-map(最完整) / cheap-module-souce-map(错误提示一整行忽略列)
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,//压缩
port: 9000,//端口号
headers:{},//设置请求头
proxy: {
'/api': {
target: 'https://api.github.com'
}
}
// ...
}