webpack5基础和配置

初步体验webpack打包

webpack是一个静态资源打包工具。

它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。

输出的文件就是编译好的文件,就可以在浏览器段运行了。
1.初始化最简单的一个目录文件,手动创建

main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";

console.log(count(2,1));
console.log(sum(1,2,3,4));

index.html

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h3>webpack</h3>
    <!-- 这里直接运行报错 浏览器不识别ES6模块化 -->
    <!-- <script src="../src/main.js"></script> -->
    <!-- 运行的时候改成这个路径,webpack打包好的js文件 -->
    <script src="../dist/main.js"></script>
</body>
</html>

2.下载依赖

npm init -y

初始化package.json文件 修改一下 main 的路径 ./src/main.js

javascript 复制代码
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "./src/main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

注意:package.json中name字段不能叫做webpack,否则下一步会报错

npm i webpack webpack-cli -D
3.启用webpack
开发模式

npx webpack ./src/main.js --mode=development
生产模式

npx webpack ./src/main.js --mode=production (生产环境会对代码压缩,文件非常小)

默认webpack会将文件打包输出到dist目录下,我们查看dist目录下文件情况就好了

npx webpack :是用来运行本地安装 webpack包的。
./src/main.js :指定webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来。
--mode=xxx:指定模式(环境)

webpack本身功能比较少,只能处理js资源,一旦遇到css等其他资源就会报错。

5大核心概念

1.entry (入口)

指示webpack从哪个文件开始打包
2.outpu (输出)

指示webpack打包完的文件输出到哪里去,如何命名等
3.loader (加载器)

webpack本身只能处理js、json等资源,其他资源需要借助loader,webpack才能解析
4.plugins (插件)

扩展webpack的功能
5.mode (模式)

主要由两种模式:

开发模式:development

生成模式:production
准备webpack配置文件

在项目 根目录 新建文件:webpack.config.js

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'dist'),//绝对路径
        //文件名
        filename:'main.js'
    },
     //加载器
    module:{
        rules:[
            //loader的配置
        ]
    },
     //插件
    plugins:[
        //plugin的配置
    ],
     //模式
    mode:'development',
}

运行打包:npx webpack

开发模式介绍

1.编译代码,使浏览器能识别运行

开发时我们有样式资源,字体图标,图片资源,html资源等,webpack默认都不能处理这些资源,所以我们要加载配置来编译这些资源

2.代码质量检查,树立代码规范

提前检查代码的一些隐患,让代码运行时能更加健壮。

提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
官方文档

处理样式资源Css资源

(less,sass也是这样的处理步骤)
1,下载包

npm i css-loader style-loader -D
css-loader :负责将css文件编译成webpack能识别的模块
style-loader:会动态创建一个style标签,里面放置webpack中css模块内容

2. 创建一个css资源引入

main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";
//想要webpack打包资源,必须引入该资源
import './css/index.css'
console.log(count(2,1));
console.log(sum(1,2,3,4));

3.webpack.config.js 配置 (如果有less,sass往rules里面添加即可)

处理图片资源 不需要下载和配置,如果想转换base64就需要配置一下

修改输出文件目录

处理字体图标资源

处理其他资源(比如视频,音频等等)

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:[ //执行顺序,从右到左(从下到上)
                    "style-loader", //将js中css通过创建style标签添加html文件中生效
                    "css-loader"  //将css资源编译成commonjs的模块到js中
                ]
            },
            {
                test: /\.less$/i,
                use: [
                  // 使用多个loader
                  'style-loader',
                  'css-loader',
                  'less-loader', //将less编译成css文件
                ],
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"public/index.html")
        })
    ],
    //开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:'localhost',//启动服务器域名
        port:'3000',//启动服务器端口
        open:true,//是否自动打开浏览器
    },
     //模式
    mode:'development',
}

eslint使用

它是用来检测js和jsx语法的工具,可以配置各项功能

使用eslint,关键是写eslint配置文件,里面写上各种rules规则,将来运行eslint时就会以写的规则对代码进行检查

配置文件由很多种写法:

.eslintrc.*:新建文件,位于项目根目录
配置说明
1.下载包

npm i eslint-webpack-plugin eslint -D

vscode 可以安装一个插件 ESLint

安装了这个插件就需要在配置一个文件 .eslintignore

忽略dist文件,里面的不检查

javascript 复制代码
dist

2.定义.eslintrc.js 配置文件

javascript 复制代码
module.exports={
    //继承Eslint规则
    extends:['eslint:recommended'],
    env:{
        node:true,//启用node中全局变量
        browser:true,//启用浏览器中全局变量
    },
    parserOptions:{
        ecmaVersion:6, //语法环境ES6
        sourceType:'module' //es  module
    },
    rules:{
        "no-var":2 ,//不能使用var定义变量
    }
}

babel使用

主要用于将ES6语法编写的代码转换为向后兼容的JavaScript语法,以便能够运行在当前和旧版本的浏览器或其他环境中
1.下载

npm i babel-loader @babel/core @babel/preset-env -D

2.定义babel配置文件 babel.config.js

javascript 复制代码
module.exports={
    //智能预设,能够编译ES6语法
    presets:["@babel/preset-env"]
}

处理html资源

1.下载

npm install --save-dev html-webpack-plugin
2.引入

javascript 复制代码
const HtmlWebpackPlugin=require('html-webpack-plugin')

自动化

每次写完代码都需要手动输入指令才能编译代码,太麻烦,希望一切自动化

1.下载

npm i webpack-dev-server -D

2.配置 webpack.config.js

javascript 复制代码
//开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:'localhost',//启动服务器域名
        port:'3000',//启动服务器端口
        open:true,//是否自动打开浏览器
    },

3.运行

npx webpack serve

生产模式

生产模式是开发完成代码后,需要得到代码将来部署上线

主要对代码进行优化,让其运行性能更好。

1,优化代码运行性能

2,优化代码打包速度

准备两个配置文件来放不同的配置

webpack.dev.js 文件

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //开发模式没有输出
        path:undefined,
        //入口文件打包输出文件名
        filename:'static/js/main.js',
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:[ //执行顺序,从右到左(从下到上)
                    "style-loader", //将js中css通过创建style标签添加html文件中生效
                    "css-loader"  //将css资源编译成commonjs的模块到js中
                ]
            },
            {
                test: /\.less$/i,
                use: [
                  // 使用多个loader
                  'style-loader',
                  'css-loader',
                  'less-loader', //将less编译成css文件
                ],
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        })
    ],
    //开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:'localhost',//启动服务器域名
        port:'3000',//启动服务器端口
        open:true,//是否自动打开浏览器
    },
     //模式
    mode:'development',
}

运行

npx webpack serve --config ./config/webpack.dev.js

webpack.prod.js 文件

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:[ //执行顺序,从右到左(从下到上)
                    "style-loader", //将js中css通过创建style标签添加html文件中生效
                    "css-loader"  //将css资源编译成commonjs的模块到js中
                ]
            },
            {
                test: /\.less$/i,
                use: [
                  // 使用多个loader
                  'style-loader',
                  'css-loader',
                  'less-loader', //将less编译成css文件
                ],
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        })
    ],
     //模式
    mode:'production',
}

打包

npx webpack --config ./config/webpack.prod.js

简化运行代码的长度 配置 package.json

javascript 复制代码
 "scripts": {
    "start":"npm run dev",
    "dev": "webpack serve --config ./config/webpack.dev.js",
    "build":"webpack  --config ./config/webpack.prod.js"
  },

提取css成单独文件

css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签来生成样式

这样对于网站来说,会出现闪屏现象,用户体验不好

应该是单独的css文件,通过link标签加载性能才好

1.下载

npm i mini-css-extract-plugin -D

2.配置webpack.prod.js文件

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:[ //执行顺序,从右到左(从下到上)
                   MiniCssExtractPlugin.loader, //提取css成单独文件
                    "css-loader"  //将css资源编译成commonjs的模块到js中
                ]
            },
            {
                test: /\.less$/i,
                use: [
                  // 使用多个loader
                  MiniCssExtractPlugin.loader, //提取css成单独文件
                  'css-loader',
                  'less-loader', //将less编译成css文件
                ],
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/main.css'
        })
    ],
     //模式
    mode:'production',
}

Css兼容性处理

1.下载包

npm i postcss-loader postcss postcss-preset-env -D

2.配置webpack.prod.js 文件

在css-loader后面 在less-loader前面 加代码

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:[ //执行顺序,从右到左(从下到上)
                   MiniCssExtractPlugin.loader, //提取css成单独文件
                    "css-loader",  //将css资源编译成commonjs的模块到js中
                    {
                        loader:"postcss-loader",
                        options:{ //配置项
                            postcssOptions:{
                                plugins:[
                                    "postcss-preset-env",//能解决大多数兼容性问题
                                ]
                            }
                        }
                      },
                ]
            },
            {
                test: /\.less$/i,
                use: [
                  // 使用多个loader
                  MiniCssExtractPlugin.loader, //提取css成单独文件
                  'css-loader',
                  {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                  },
                  'less-loader', //将less编译成css文件
                ],
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/main.css'
        })
    ],
     //模式
    mode:'production',
}

package.json 文件还需要做兼容那些处理

实际开发用的是这种

javascript 复制代码
 "browserslist":[
    "last 2 version",
    "> 1%",
    "not dead"
  ]

Css压缩

1.下载包

npm i css-minimizer-webpack-plugin -D

2.配置webpack.prod.js文件

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")

//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                MiniCssExtractPlugin.loader, //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/i, //只检测.css结尾的文件
                use:getStyleLoader(),
            },
            {
                test: /\.less$/i,
                use:getStyleLoader('less-loader'),
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
                generator:{
                    //输出图片名称
                    //[hash:10] hash值取前10位
                    filename:"static/images/[hash:10][ext][query]"
                }
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
                generator:{
                    //输出名称
                    filename:"static/media/[hash:10][ext][query]"
                }
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                // options:{
                //     presets:["@babel/preset-env"]
                // }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/main.css'
        }),
        new CssMinimizerPlugin(),
    ],
     //模式
    mode:'production',
}

html压缩

(默认生成模式已经开启了:html压缩和js压缩,不需要额外进行配置)

webpack高级配置

(其实就是进行webpack优化)

1.提升开发体验

2.提升打包构建速度

3.减少代码体积

4.优化代码运行性能

1.提升开发体验

SourceMap (源代码映射)是一个用来生成源代码与构建后代码一一映射的文件的方案。

它会生成一个xxx.map文件,里面包含源代码和构建后代码每一行,每一列的映射关系,当构建后代码出错了,会通过xxx.map文件,从构建后代码出错位置找到映射后源代码出错位置,从而让浏览器提示源代码文件出错位置,帮助我们更快的找到错误根源。

开发模式:cheap-module-source-map

优点:打包编辑速度快,只包含行映射

缺点:没有列映射
webpack.dev.js

javascript 复制代码
 //模式
    mode:'development',
    devtool:"cheap-module-source-map"

生产模式:source-map

优点:包含行/列映射

缺点:打包编辑速度更慢
webpack.prod.js

javascript 复制代码
  //模式
    mode:'production',
    devtool:"source-map"

2.提升打包构建速度

HotModuleReplacement (HMR/热模块替换):在程序运行中,替换,添加或删除模块,而无需重新加载整个页面。

基本配置 webpack.dev.js

javascript 复制代码
//开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:"localhost",//启动服务器域名
        port:"3000", //启动服务器端口号
        open:true,//是否自动打开浏览器
        hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true
    },

此时css样式经过style-loader处理,已经具备HMR功能了,但是js还不行。
main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";
//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));

if(module.hot){
    //判断是否支持热模块替换功能
    module.hot.accept("./js/count")
    module.hot.accept("./js/sum")
}

上面这样写很麻烦,所以实际开发我们会使用其他loader来解决(比如:vue-loader,react-hot-loader)
oneOf(就是只能匹配上一个loader,剩下的就不匹配了)

include/exclude(包含/排除)两者只能存在一个

javascript 复制代码
{
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    loader:'babel-loader',
                    //写这里也行,写外面babel.config.js里面也行
                    // options:{
                    //     presets:["@babel/preset-env"]
                    // }
                }

cache(对Eslint检查和Babel编译结果进行缓存)

javascript 复制代码
{
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    loader:'babel-loader',
                    //写这里也行,写外面babel.config.js里面也行
                    options:{
                        // presets:["@babel/preset-env"]
                        cacheDirectory:true,//开启babel缓存
                        cacheCompression:false,//关闭缓存文件压缩
                    }
                }
javascript 复制代码
//plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache")  //指定缓存文件
        }),

thead (多进程打包,开启电脑的多个进程同时干一件事,速度更快)

需要注意:请仅在特别耗时的操作中使用,因为每个进程启动就有大约为600ms左右开销。

我们启动进程的数量就是我们CPU的核数。

1.如何获取CPU的核数,因为每个电脑都不一样

javascript 复制代码
//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;

2.下载包

npm i thread-loader -D

3.配置

javascript 复制代码
 {
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    use:[
                        {
                            loader:"thread-loader", //开启多进程
                            options:{
                                works:threads, //进程数量
                            }
                        },
                        {
                            loader:'babel-loader',
                            //写这里也行,写外面babel.config.js里面也行
                            options:{
                                // presets:["@babel/preset-env"]
                                cacheDirectory:true,//开启babel缓存
                                cacheCompression:false,//关闭缓存文件压缩
                            }
                        }
                    ]
                }
javascript 复制代码
 //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"),  //指定缓存文件
            threads,//开启多进程和设置进程数量
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/main.css'
        }),
        // new CssMinimizerPlugin(),
        // new TerserWebpackPlugin({
        //     parallel:threads,//开启多进程和设置进程数量
        // })
    ],
    optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin({
                parallel:threads,//开启多进程和设置进程数量
            })
        ]
    },

3.减少代码体积

tree Shaking (用于描述移除js中的没有使用上的代码)

webpack已经默认开启了这个功能,无需其他配置

注意:它依赖 ES模块化
babel

1.下载包

npm i @babel/plugin-transform-runtime -D

@babel/plugin-transform-runtime(禁用了Babel自动对每个文件的runtime注入,而是引入,并且使所有辅助代码从这里引用)

javascript 复制代码
{
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    use:[
                        {
                            loader:"thread-loader", //开启多进程
                            options:{
                                works:threads, //进程数量
                            }
                        },
                        {
                            loader:'babel-loader',
                            //写这里也行,写外面babel.config.js里面也行
                            options:{
                                // presets:["@babel/preset-env"]
                                cacheDirectory:true,//开启babel缓存
                                cacheCompression:false,//关闭缓存文件压缩
                                plugins:['@babel/plugin-transform-runtime'],//减少代码体积
                            }
                        }
                    ]
                }

image Minimizer (用来压缩图片的插件)

注意:如果项目中图片都是在线连接,那么就不需要了,本地项目静态图片才需要进行压缩

1.下载包

npm i image-minimizer-webpack-plugin imagemin -D

还有剩下包需要下载,有两种模式:

无损压缩

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D

有损压缩

npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D

注意:有时候网络问题,需要多下载几次,不然就使用翻墙软件下载

2.配置,以无损压缩配置为例 打包的时候报错 不知道啥问题导致的

javascript 复制代码
 optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin({
                parallel:threads,//开启多进程和设置进程数量
            }),
            //压缩图片
            new ImageMinimizerPlugin({
                minimizer: {
                  implementation: ImageMinimizerPlugin.imageminGenerate,
                  options: {
                    plugins: [
                      ["gifsicle", { interlaced: true }],
                      ["jpegtran", { progressive: true }],
                      ["optipng", { optimizationLevel: 5 }],
                      [
                        "svgo",
                        {
                          plugins: [
                            "preset-default",
                            "prefixIds",
                            {
                              name: "sortAttrs",
                              params: {
                                xmlnsOrder: "alphabetical",
                              },
                            },
                          ],
                        },
                      ],
                    ],
                  },
                },
          }),
        ]
    },

4.优化代码运行性能

code split (代码分割)

1.分割文件:将打包生成的文件进行分割,生成多个js文件

单入口

javascript 复制代码
optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin({
                parallel:threads,//开启多进程和设置进程数量
            }),
           
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        }
    },

2.按需加载:需要哪个文件就加载哪个文件。
main.js 动态引入按需加载

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";

//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));

document.getElementById('btn').onclick=function(){
    //动态引入按需加载
    //eslint不能识别动态导入需要,需要额外追加配置
    import("./js/math").then(({mul})=>{
         console.log(mul(3,1));
    })
}

if(module.hot){
    //判断是否支持热模块替换功能
    module.hot.accept("./js/count")
    module.hot.accept("./js/sum")
}

.eslintrc.js 解决动态语法导入报错

javascript 复制代码
module.exports={
    //继承Eslint规则
    extends:['eslint:recommended'],
    env:{
        node:true,//启用node中全局变量
        browser:true,//启用浏览器中全局变量
    },
    parserOptions:{
        ecmaVersion:6, //语法环境ES6
        sourceType:'module' //es  module
    },
    rules:{
        "no-var":2 ,//不能使用var定义变量
    },
    plugins:['import']  //解决动态语法导入报错
}

给模块命名

1.main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";

//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));

document.getElementById('btn').onclick=function(){
    //动态引入按需加载
    //eslint不能识别动态导入需要,需要额外追加配置
    // /* webpackChunkName:"math" */  webpack魔法命名
    import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{
         console.log(mul(3,1));
    })
}

if(module.hot){
    //判断是否支持热模块替换功能
    module.hot.accept("./js/count")
    module.hot.accept("./js/sum")
}

2.配置webpack.prod.js文件

javascript 复制代码
//输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/main.js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].js",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },

统一命名 webpack.prod.js

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")

//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                MiniCssExtractPlugin.loader, //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
           {
              //每个文件只能被其中一个loader配置处理
            oneOf:[
                {
                    test:/\.css$/i, //只检测.css结尾的文件
                    use:getStyleLoader(),
                },
                {
                    test: /\.less$/i,
                    use:getStyleLoader('less-loader'),
                },
                {
                    test:/\.(png|jpe?g|glf|webp|svg)$/,
                    type:"asset",
                    parser:{
                        dataUrlCondition:{
                            //小于10kb的图片转base64
                            //优点,减少请求数量,缺点,体积会更大
                            maxSize:10 * 1024,//10kb
                        }
                    },
                    // generator:{
                    //     //输出图片名称
                    //     //[hash:10] hash值取前10位
                    //     filename:"static/images/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                    type:"asset/resource",
                    // generator:{
                    //     //输出名称
                    //     filename:"static/media/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    use:[
                        {
                            loader:"thread-loader", //开启多进程
                            options:{
                                works:threads, //进程数量
                            }
                        },
                        {
                            loader:'babel-loader',
                            //写这里也行,写外面babel.config.js里面也行
                            options:{
                                // presets:["@babel/preset-env"]
                                cacheDirectory:true,//开启babel缓存
                                cacheCompression:false,//关闭缓存文件压缩
                                plugins:['@babel/plugin-transform-runtime'],//减少代码体积
                            }
                        }
                    ]
                }
            ]
           }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"),  //指定缓存文件
            threads,//开启多进程和设置进程数量
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/[name].css',
            chunkFilename:'static/css/[name].chunk.css'
        }),
        // new CssMinimizerPlugin(),
        // new TerserWebpackPlugin({
        //     parallel:threads,//开启多进程和设置进程数量
        // })
       
    ],
    optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin({
                parallel:threads,//开启多进程和设置进程数量
            }),
            //压缩图片  以下代码打包报错  不知道哪里问题
        //     new ImageMinimizerPlugin({
        //         minimizer: {
        //           implementation: ImageMinimizerPlugin.imageminGenerate,
        //           options: {
        //             plugins: [
        //               ["gifsicle", { interlaced: true }],
        //               ["jpegtran", { progressive: true }],
        //               ["optipng", { optimizationLevel: 5 }],
        //               [
        //                 "svgo",
        //                 {
        //                   plugins: [
        //                     "preset-default",
        //                     "prefixIds",
        //                     {
        //                       name: "sortAttrs",
        //                       params: {
        //                         xmlnsOrder: "alphabetical",
        //                       },
        //                     },
        //                   ],
        //                 },
        //               ],
        //             ],
        //           },
        //         },
        //   }),
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        }
    },
     //模式
    mode:'production',
    devtool:"source-map"
}

preload (告诉浏览器立即加载资源) / prefetch(告诉浏览器在空闲时才开始加载资源)

共同点: 都只会加载资源,并不执行。都有缓存

区别:preload加载优先级高,prefetch加载优先级低。

preload只能加载当前页面需要使用的资源,prefetch可以加载当前页面资源,也可以加载下一个页面需要使用的资源。

下载包

npm install --save-dev @vue/preload-webpack-plugin

javascript 复制代码
const PreloadWebpackPlugin=require("@vue/preload-webpack-plugin") 
//插件
    plugins:[
        new PreloadWebpackPlugin({
            // rel:'preload',
            // as:'script',
            rel:'prefetch',
        })
    ],

core-js (是专门用来做ES6以及以上的API的polyfill(垫片/补丁,就是用社区上提供的一段代码,让我们在不兼容某些新特性的浏览器上,使用该新特性))

下载包

npm i core-js

main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";
//完整引入
// import 'core-js'
//按需加载
// import 'core-js/es/promise'

//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));

document.getElementById('btn').onclick=function(){
    //动态引入按需加载
    //eslint不能识别动态导入需要,需要额外追加配置
    // /* webpackChunkName:"math" */  webpack魔法命名
    import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{
         console.log(mul(3,1));
    })
}

if(module.hot){
    //判断是否支持热模块替换功能
    module.hot.accept("./js/count")
    module.hot.accept("./js/sum")
}

new Promise((resolve)=>{
    setTimeout(()=>{
        resolve();
    },1000)
})

自动引入
文档
babel.config.js

javascript 复制代码
module.exports={
    //智能预设,能够编译ES6语法
    presets:[
        [
            "@babel/preset-env",
            {
                useBuiltIns:'usage',//按需加载自动引入
                corejs:3
            }
        ]
    ]
}

PWA (渐进式网络应用程序,在离线时应用程序能够继续运行功能) 兼容性比较差

下载包

npm i workbox-webpack-plugin -D
文档

配置main.js

javascript 复制代码
import count from "./js/count";
import sum from "./js/sum";
//完整引入
// import 'core-js'
//按需加载
// import 'core-js/es/promise'

//想要webpack打包资源,必须引入该资源
import './css/index.css'
import './css/iconfont.css'
console.log(count(2,1));
console.log(sum(1,2,3,4,5));

document.getElementById('btn').onclick=function(){
    //动态引入按需加载
    //eslint不能识别动态导入需要,需要额外追加配置
    // /* webpackChunkName:"math" */  webpack魔法命名
    import(/* webpackChunkName:"math" */ "./js/math").then(({mul})=>{
         console.log(mul(3,1));
    })
}

if(module.hot){
    //判断是否支持热模块替换功能
    module.hot.accept("./js/count")
    module.hot.accept("./js/sum")
}

new Promise((resolve)=>{
    setTimeout(()=>{
        resolve();
    },1000)
})

const arr=[1,2,3,4];
console.log(arr.includes(1));

if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
      navigator.serviceWorker.register('/service-worker.js').then(registration => {
        console.log('SW registered: ', registration);
      }).catch(registrationError => {
        console.log('SW registration failed: ', registrationError);
      });
    });
  }
javascript 复制代码
 //插件
    plugins:[
        new WorkboxPlugin.GenerateSW({
            //这些选项帮助快速启用 ServiceWorkers
            //不允许遗留任何'旧的' ServiceWorkers
            clientsClaim:true,
            skipWaiting:true
        })
    ],

npm i serve -g 全局安装

serve dist 运行

Notwork------》开启 Offline 离线环境 看效果

webpack.prod.js完整代码

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const PreloadWebpackPlugin=require("@vue/preload-webpack-plugin")
const WorkboxPlugin=require('workbox-webpack-plugin')
//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                MiniCssExtractPlugin.loader, //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
           {
              //每个文件只能被其中一个loader配置处理
            oneOf:[
                {
                    test:/\.css$/i, //只检测.css结尾的文件
                    use:getStyleLoader(),
                },
                {
                    test: /\.less$/i,
                    use:getStyleLoader('less-loader'),
                },
                {
                    test:/\.(png|jpe?g|glf|webp|svg)$/,
                    type:"asset",
                    parser:{
                        dataUrlCondition:{
                            //小于10kb的图片转base64
                            //优点,减少请求数量,缺点,体积会更大
                            maxSize:10 * 1024,//10kb
                        }
                    },
                    // generator:{
                    //     //输出图片名称
                    //     //[hash:10] hash值取前10位
                    //     filename:"static/images/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                    type:"asset/resource",
                    // generator:{
                    //     //输出名称
                    //     filename:"static/media/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    use:[
                        {
                            loader:"thread-loader", //开启多进程
                            options:{
                                works:threads, //进程数量
                            }
                        },
                        {
                            loader:'babel-loader',
                            //写这里也行,写外面babel.config.js里面也行
                            options:{
                                // presets:["@babel/preset-env"]
                                cacheDirectory:true,//开启babel缓存
                                cacheCompression:false,//关闭缓存文件压缩
                                plugins:['@babel/plugin-transform-runtime'],//减少代码体积
                            }
                        }
                    ]
                }
            ]
           }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"),  //指定缓存文件
            threads,//开启多进程和设置进程数量
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/[name].css',
            chunkFilename:'static/css/[name].chunk.css'
        }),
        // new CssMinimizerPlugin(),
        // new TerserWebpackPlugin({
        //     parallel:threads,//开启多进程和设置进程数量
        // })
        new PreloadWebpackPlugin({
            // rel:'preload',
            // as:'script',
            rel:'prefetch',
        }),
        new WorkboxPlugin.GenerateSW({
            //这些选项帮助快速启用 ServiceWorkers
            //不允许遗留任何'旧的' ServiceWorkers
            clientsClaim:true,
            skipWaiting:true
        })
    ],
    optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin({
                parallel:threads,//开启多进程和设置进程数量
            }),
            //压缩图片  以下代码打包报错  不知道哪里问题
        //     new ImageMinimizerPlugin({
        //         minimizer: {
        //           implementation: ImageMinimizerPlugin.imageminGenerate,
        //           options: {
        //             plugins: [
        //               ["gifsicle", { interlaced: true }],
        //               ["jpegtran", { progressive: true }],
        //               ["optipng", { optimizationLevel: 5 }],
        //               [
        //                 "svgo",
        //                 {
        //                   plugins: [
        //                     "preset-default",
        //                     "prefixIds",
        //                     {
        //                       name: "sortAttrs",
        //                       params: {
        //                         xmlnsOrder: "alphabetical",
        //                       },
        //                     },
        //                   ],
        //                 },
        //               ],
        //             ],
        //           },
        //         },
        //   }),
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        }
    },
     //模式
    mode:'production',
    devtool:"source-map"
}

webpack.dev.js完整代码

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')

//nodejs核心模块,直接使用
const os=require('os');
//cpu核数
const threads=os.cpus().length;
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
           {
            //每个文件只能被其中一个loader配置处理
             oneOf:[
                {
                    test:/\.css$/i, //只检测.css结尾的文件
                    use:[ //执行顺序,从右到左(从下到上)
                        "style-loader", //将js中css通过创建style标签添加html文件中生效
                        "css-loader"  //将css资源编译成commonjs的模块到js中
                    ]
                },
                {
                    test: /\.less$/i,
                    use: [
                      // 使用多个loader
                      'style-loader',
                      'css-loader',
                      'less-loader', //将less编译成css文件
                    ],
                },
                {
                    test:/\.(png|jpe?g|glf|webp|svg)$/,
                    type:"asset",
                    parser:{
                        dataUrlCondition:{
                            //小于10kb的图片转base64
                            //优点,减少请求数量,缺点,体积会更大
                            maxSize:10 * 1024,//10kb
                        }
                    },
                    // generator:{
                    //     //输出图片名称
                    //     //[hash:10] hash值取前10位
                    //     filename:"static/images/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                    type:"asset/resource",
                    // generator:{
                    //     //输出名称
                    //     filename:"static/media/[hash:10][ext][query]"
                    // }
                },
                {
                    test:/\.js$/,  //处理字体图标资源或者其他资源
                    exclude:/node_modules/, //排除node_modules中的js文件(这些文件不处理)
                    //include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                    use:[
                        {
                            loader:"thread-loader", //开启多进程
                            options:{
                                works:threads, //进程数量
                            }
                        },
                        {
                            loader:'babel-loader',
                            //写这里也行,写外面babel.config.js里面也行
                            options:{
                                // presets:["@babel/preset-env"]
                                cacheDirectory:true,//开启babel缓存
                                cacheCompression:false,//关闭缓存文件压缩
                                plugins:['@babel/plugin-transform-runtime'],//减少代码体积
                            }
                        }
                    ]
                }
             ]
           }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/eslintcache"),  //指定缓存文件
            threads,//开启多进程和设置进程数量
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        })
    ],
    //开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:"localhost",//启动服务器域名
        port:"3000", //启动服务器端口号
        open:true,//是否自动打开浏览器
        hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true
    },
     //模式
    mode:'development',
    devtool:"cheap-module-source-map",
}

vueCli开发模式配置vue3

npm init -y

安装

npm install -D vue-loader vue-template-compiler
配置webpack.dev.js 开发模式

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const {DefinePlugin} =require("webpack")
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                "vue-style-loader", //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}
module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:undefined,//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]"
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/, //只检测.css结尾的文件
                use:getStyleLoader(),
            },
            {
                test: /\.less$/,
                use:getStyleLoader('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use:getStyleLoader('sass-loader'),
            },
            {
                test: /\.styl$/,
                use:getStyleLoader('stylus-loader'),
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                options:{
                    cacheDirectory:true,//开启babel缓存
                    cacheCompression:false,//关闭缓存文件压缩
                }
            },
            {
                test:/\.vue$/,
                loader:'vue-loader'
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),  //指定缓存文件
        }),
        new HtmlWebpackPlugin({
            //模板。以public/index.html文件创建新的html文件
            //新的html文件特点:1,结构和原来一致,2.自动引入打包输出的资源
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new VueLoaderPlugin(),
        //定义环境变量 cross-env定义的环境变量给打包工具使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],
    //开发服务器:不会输出资源,在内存中编译打包
    devServer:{
        host:"localhost",//启动服务器域名
        port:"4000", //启动服务器端口号
        open:true,//是否自动打开浏览器
        hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true
        historyApiFallback:true, //解决前端路由刷新404问题
    },
    optimization:{
       
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        }
    },
    //webpack解析模块加载选项
    resolve:{
        //自动补全文件扩展名
        extensions:['.js','.json','.vue']
    },
     //模式
    mode:'development',
    devtool:"cheap-module-source-map",
}

安装依赖

npm i eslint-webpack-plugin html-webpack-plugin vue-style-loader css-loader postcss-loader postcss-preset-env -D

npm i less-loader sass-loader sass stylus-loader babel-loader vue-loader webpack webpack-cli webpack-dev-server -D

.eslintrc.js 配置

javascript 复制代码
module.exports={
    root:true,
    env:{
        node:true,
    },
    extends:['plugin:vue/vue3-essential','eslint:recommended'],
    parserOptions:{
        parser:'@babel/eslint-parser'
    }
};

npm i @babel/eslint-parser -D
babel.config.js 配置

javascript 复制代码
module.exports={
    presets:["@vue/cli-plugin-babel/preset"]
}

npm i @vue/cli-plugin-babel -D

npm i vue (默认是vue3的版本)

npm i cross-env -D

npm i eslint-plugin-vue -D

npm i vue-router

生产模式 webpack.prod.js

npm i mini-css-extract-plugin css-minimizer-webpack-plugin copy-webpack-plugin -D

下载图片

npm i image-minimizer-webpack-plugin imagemin -D

无损下载

npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D

不知道为什么,下载图片老是下载失败

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")
//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                MiniCssExtractPlugin.loader, //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:path.resolve(__dirname,'../dist'),//绝对路径
        //入口文件打包输出文件名
        filename:'static/js/[name].[contenthash:10].js',
        //给打包输出的其他文件命名
        chunkFilename:"static/js/[name].[contenthash:10].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/, //只检测.css结尾的文件
                use:getStyleLoader(),
            },
            {
                test: /\.less$/,
                use:getStyleLoader('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use:getStyleLoader('sass-loader'),
            },
            {
                test: /\.styl$/,
                use:getStyleLoader('stylus-loader'),
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
             
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                options:{
                    cacheDirectory:true,//开启babel缓存
                    cacheCompression:false,//关闭缓存文件压缩
                }
            },
            {
                test:/\.vue$/,
                loader:'vue-loader'
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),  //指定缓存文件
         
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename:'static/css/[name].[contenthash:10].css',
            chunkFilename:'static/css/[name].[contenthash:10].chunk.css'
        }),
        new CopyPlugin({
            patterns:[
                {
                    from:path.resolve(__dirname,"../public"),
                    to:path.resolve(__dirname,"../dist"),
                    globOptions:{
                        //忽略index.html文件
                        ignore:["**/index.html"]
                    }
                }
            ]
        }),
        new VueLoaderPlugin(),
        //定义环境变量 cross-env定义的环境变量给打包工具使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ],
    optimization:{
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin(),
            //压缩图片  以下代码打包报错  不知道哪里问题
        //     new ImageMinimizerPlugin({
        //         minimizer: {
        //           implementation: ImageMinimizerPlugin.imageminGenerate,
        //           options: {
        //             plugins: [
        //               ["gifsicle", { interlaced: true }],
        //               ["jpegtran", { progressive: true }],
        //               ["optipng", { optimizationLevel: 5 }],
        //               [
        //                 "svgo",
        //                 {
        //                   plugins: [
        //                     "preset-default",
        //                     "prefixIds",
        //                     {
        //                       name: "sortAttrs",
        //                       params: {
        //                         xmlnsOrder: "alphabetical",
        //                       },
        //                     },
        //                   ],
        //                 },
        //               ],
        //             ],
        //           },
        //         },
        //   }),
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        },
    },
     //模式
    mode:'production',
    devtool:"source-map",
     //webpack解析模块加载选项
     resolve:{
        //自动补全文件扩展名
        extensions:['.js','.json','.vue']
    },
}

package.json

javascript 复制代码
 "scripts": {
    "start": "npm run dev",
    "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.dev.js",
    "build": "cross-env NODE_ENV=production webpack --config ./config/webpack.prod.js"
  },

合并配置
webpack.config.js

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")

const isProduction=process.env.NODE_ENV==='production';


//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                isProduction ?  MiniCssExtractPlugin.loader : 'vue-style-loader', //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre,
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:isProduction ? path.resolve(__dirname,'../dist') : undefined,//绝对路径
        //入口文件打包输出文件名
        filename:isProduction ?  'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:isProduction ?  "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/, //只检测.css结尾的文件
                use:getStyleLoader(),
            },
            {
                test: /\.less$/,
                use:getStyleLoader('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use:getStyleLoader('sass-loader'),
            },
            {
                test: /\.styl$/,
                use:getStyleLoader('stylus-loader'),
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
             
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                options:{
                    cacheDirectory:true,//开启babel缓存
                    cacheCompression:false,//关闭缓存文件压缩
                }
            },
            {
                test:/\.vue$/,
                loader:'vue-loader'
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),  //指定缓存文件
         
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"../public/index.html")
        }),
        isProduction && new MiniCssExtractPlugin({
            filename:'static/css/[name].[contenthash:10].css',
            chunkFilename:'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyPlugin({
            patterns:[
                {
                    from:path.resolve(__dirname,"../public"),
                    to:path.resolve(__dirname,"../dist"),
                    globOptions:{
                        //忽略index.html文件
                        ignore:["**/index.html"]
                    }
                }
            ]
        }),
        new VueLoaderPlugin(),
        //定义环境变量 cross-env定义的环境变量给打包工具使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        })
    ].filter(Boolean),
    optimization:{
        minimize:isProduction,
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin(),
            //压缩图片  以下代码打包报错  不知道哪里问题
        //     new ImageMinimizerPlugin({
        //         minimizer: {
        //           implementation: ImageMinimizerPlugin.imageminGenerate,
        //           options: {
        //             plugins: [
        //               ["gifsicle", { interlaced: true }],
        //               ["jpegtran", { progressive: true }],
        //               ["optipng", { optimizationLevel: 5 }],
        //               [
        //                 "svgo",
        //                 {
        //                   plugins: [
        //                     "preset-default",
        //                     "prefixIds",
        //                     {
        //                       name: "sortAttrs",
        //                       params: {
        //                         xmlnsOrder: "alphabetical",
        //                       },
        //                     },
        //                   ],
        //                 },
        //               ],
        //             ],
        //           },
        //         },
        //   }),
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        },
    },
     //模式
    mode:isProduction ? 'production' :'development',
    devtool:isProduction ? "source-map" :"cheap-module-source-map",
     //webpack解析模块加载选项
     resolve:{
        //自动补全文件扩展名
        extensions:['.js','.json','.vue']
    },
      //开发服务器:不会输出资源,在内存中编译打包
      devServer:{
        host:"localhost",//启动服务器域名
        port:"4000", //启动服务器端口号
        open:true,//是否自动打开浏览器
        hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true
        historyApiFallback:true, //解决前端路由刷新404问题
    },
}

package.json

javascript 复制代码
 "scripts": {
    "start": "npm run dev",
    "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
  },

优化配置

npm install element-plus --save

按需引入

npm install -D unplugin-vue-components unplugin-auto-import

报错解决

报错 1:AutoImport is not a function

解决:是 unplugin-auto-import版本高了,我用的0.17.3。后面降版本,改成0.16.7,这个问题就不报错了。

报错2:Components is not a function

解决:unplugin-vue-components 版本也高了,从0.27.0 降到了 0.25.2 ,就能正常运行了
webpack.config.js

javascript 复制代码
const path=require('path');//nodejs核心模块,专门用来处理路径问题
//安装的插件需要引入
const ESLintPlugin=require('eslint-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const CssMinimizerPlugin=require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin=require("terser-webpack-plugin")
// const ImageMinimizerPlugin=require("image-minimizer-webpack-plugin")
const CopyPlugin=require('copy-webpack-plugin')
const { VueLoaderPlugin}=require('vue-loader')
const {DefinePlugin} =require("webpack")

const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

const isProduction=process.env.NODE_ENV==='production';


//定义一个函数抽取重复的代码  用来获取处理样式的loader
function getStyleLoader(pre){
    return [ //执行顺序,从右到左(从下到上)
                isProduction ?  MiniCssExtractPlugin.loader : 'vue-style-loader', //提取css成单独文件
                "css-loader",  //将css资源编译成commonjs的模块到js中
                {
                    loader:"postcss-loader",
                    options:{ //配置项
                        postcssOptions:{
                            plugins:[
                                "postcss-preset-env",//能解决大多数兼容性问题
                            ]
                        }
                    }
                },
                pre && {
                    loader:pre,
                    options:
                     pre === 'sass-loader'
                      ? {
                         additionalData : `@use "@/styles/element/index.scss" as *;`,
                      }
                      : {},
                },
            ].filter(Boolean);
}


module.exports={
     //入口
    entry:'./src/main.js', //相对路径
     //输出
    output:{
        //所有文件的输出路径
        //__dirname  nodejs的变量,代表当前文件的文件夹目录
        path:isProduction ? path.resolve(__dirname,'../dist') : undefined,//绝对路径
        //入口文件打包输出文件名
        filename:isProduction ?  'static/js/[name].[contenthash:10].js' : 'static/js/[name].js',
        //给打包输出的其他文件命名
        chunkFilename:isProduction ?  "static/js/[name].[contenthash:10].chunk.js":"static/js/[name].chunk.js",
        //图片,字体等通过type:asset处理资源命名方式
        assetModuleFilename:"static/media/[hash:10][ext][query]",
        //原理,在打包前,将path整个目录内容清空,再进行打包
        clean:true, //自动清空上次打包内容
    },
     //加载器
    module:{
        rules:[
            //loader的配置
            {
                test:/\.css$/, //只检测.css结尾的文件
                use:getStyleLoader(),
            },
            {
                test: /\.less$/,
                use:getStyleLoader('less-loader'),
            },
            {
                test: /\.s[ac]ss$/,
                use:getStyleLoader('sass-loader'),
            },
            {
                test: /\.styl$/,
                use:getStyleLoader('stylus-loader'),
            },
            {
                test:/\.(png|jpe?g|glf|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb的图片转base64
                        //优点,减少请求数量,缺点,体积会更大
                        maxSize:10 * 1024,//10kb
                    }
                },
            },
            {
                test:/\.(ttf|woff2?|mp3|mp4|avi)$/,  //处理字体图标资源或者其他资源
                type:"asset/resource",
             
            },
            {
                test:/\.js$/,  //处理字体图标资源或者其他资源
                include:path.resolve(__dirname,"../src"),//只处理src下的文件,其他文件不出来
                loader:'babel-loader',
                //写这里也行,写外面babel.config.js里面也行
                options:{
                    cacheDirectory:true,//开启babel缓存
                    cacheCompression:false,//关闭缓存文件压缩
                }
            },
            {
                test:/\.vue$/,
                loader:'vue-loader',
                options:{
                    //开启缓存
                    cacheDirectory:path.resolve(__dirname,"../node_modules/.cache/vue-loader"),
                }
            }
        ]
    },
     //插件
    plugins:[
        //plugin的配置
        new ESLintPlugin({
            //检测哪些文件
            context:path.resolve(__dirname,"../src"),
            exclude:"node_modules", //默认值  
            cache:true,//开启缓存
            cacheLocation:path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),  //指定缓存文件
         
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,"../public/index.html")
        }),
        isProduction && new MiniCssExtractPlugin({
            filename:'static/css/[name].[contenthash:10].css',
            chunkFilename:'static/css/[name].[contenthash:10].chunk.css'
        }),
        isProduction && new CopyPlugin({
            patterns:[
                {
                    from:path.resolve(__dirname,"../public"),
                    to:path.resolve(__dirname,"../dist"),
                    globOptions:{
                        //忽略index.html文件
                        ignore:["**/index.html"]
                    }
                }
            ]
        }),
        new VueLoaderPlugin(),
        //定义环境变量 cross-env定义的环境变量给打包工具使用
        //DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题
        new DefinePlugin({
            __VUE_OPTIONS_API__:true,
            __VUE_PROD_DEVTOOLS__:false
        }),
        //按需加载element-plus
        AutoImport({
             resolvers: [ElementPlusResolver()],
        }),
        Components({
             resolvers: [ElementPlusResolver({
                //自定义主题,引入sass
                importStyle:'sass'
             })],
        }),
    ].filter(Boolean),
    optimization:{
        minimize:isProduction,
        //压缩的操作
        minimizer:[
            //压缩css
            new CssMinimizerPlugin(),
            //压缩js
            new TerserWebpackPlugin(),
            //压缩图片  以下代码打包报错  不知道哪里问题
        //     new ImageMinimizerPlugin({
        //         minimizer: {
        //           implementation: ImageMinimizerPlugin.imageminGenerate,
        //           options: {
        //             plugins: [
        //               ["gifsicle", { interlaced: true }],
        //               ["jpegtran", { progressive: true }],
        //               ["optipng", { optimizationLevel: 5 }],
        //               [
        //                 "svgo",
        //                 {
        //                   plugins: [
        //                     "preset-default",
        //                     "prefixIds",
        //                     {
        //                       name: "sortAttrs",
        //                       params: {
        //                         xmlnsOrder: "alphabetical",
        //                       },
        //                     },
        //                   ],
        //                 },
        //               ],
        //             ],
        //           },
        //         },
        //   }),
        ],
        //代码分割配置
        splitChunks:{
            chunks:"all",
            //其他都用默认值
            cacheGroups:{
                vue:{
                   test:/[\\/]node_modules[\\/]vue(.*)?[\\/]/,
                   name:'vue-chunk',
                   priority:40,
                },
                elementPlus:{
                    test:/[\\/]node_modules[\\/]element-plus[\\/]/,
                    name:'elementPlus-chunk',
                    priority:30,
                },
                libs:{
                    test:/[\\/]node_modules[\\/]/,
                    name:'libs-chunk',
                    priority:20,
                },
            }
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        },
    },
     //模式
    mode:isProduction ? 'production' :'development',
    devtool:isProduction ? "source-map" :"cheap-module-source-map",
     //webpack解析模块加载选项
     resolve:{
        //自动补全文件扩展名
        extensions:['.js','.json','.vue'],
        //路径别名
        alias:{
            '@':path.resolve(__dirname,'../src'),
        }
    },
      //开发服务器:不会输出资源,在内存中编译打包
      devServer:{
        host:"localhost",//启动服务器域名
        port:"4000", //启动服务器端口号
        open:true,//是否自动打开浏览器
        hot:true,//开启HMR功能(只能用于开发环境,生成环境不需要了)默认值是true
        historyApiFallback:true, //解决前端路由刷新404问题
    },
    //关闭性能分析,提升打包速度
    performance:false,
}

自定义主题 styles/element/index.scss

javascript 复制代码
// styles/element/index.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  ),
);
相关推荐
liangshanbo12158 天前
面试题:Webpack 的 publicPath 有什么作用?
前端·webpack·node.js
liangshanbo121511 天前
Webpack vs Vite 底层原理高频追问的问题
前端·webpack·node.js
liangshanbo121511 天前
面试题:AI 对话上下文超限怎么办?
面试·webpack·devops
liangshanbo121511 天前
Webpack 文件指纹面试题整理
前端·webpack·node.js
liangshanbo121512 天前
Webpack 常见 Plugin 面试题
前端·webpack·node.js
liangshanbo121512 天前
Webpack Tree Shaking 面试题整理
前端·webpack·node.js
陪我一起学编程12 天前
vue3笔记
前端·webpack·vue3·vite·脚手架·vue3笔记·组件式
liangshanbo121512 天前
Webpack的分包策略面试题
前端·webpack·node.js
liangshanbo121513 天前
面试题:如何优化 Webpack 的打包速度?
前端·webpack·node.js
晚风醉蝶15 天前
webpack 模块提取
前端·webpack·node.js·ast·逆向分析