webpack基础片(完毕)

133 阅读15分钟

1.webpack的安装

  1. 全局安装 npm i webpack webpack-cli —global ,通过全局进行安装(不推荐) 好处:无论是在哪个目录下面都可以访问到webpack 不推荐的原因是 1.会让你的webpack锁定在某个版本 2.在不同项目中使用同样的webpack可能会导致构建失败 3.团队协作中,构建也会出现问题
  2. 项目中安装npm i webpack webpack-cli —sava-dev,项目中安装(推荐)

在项目安装之前,我们要通过npm init -y进行package.json的文件初始化

2.运行webpack

1.要对我们的代码进行修改,通过es module的导入导出修改

function webpack(){
    console.log("webpack")
}

export default webpack


import webpack from './demo'

webpack()

2.在项目的根目录的终端中,直接使用 webpack(全局的webpack命令)或者npx webpack(项目本地) 命令项目打包,在项目的根目录上就会多一个dist的文件,这就是webpack对项目进行打包生成的文件

image.png

3.在终端中输入webpack —stats detailed会有webpack打包的详细信息

image.png

3.webpack配置命令

npx webpack —help查看webpack的options

image.png

npx webpack —entry ./src/index.js —mode production 设置webpack打包的入口

image.png

4.webpack自定义配置

通过 webpack.config.js进行自定义配置,并且是运行在node环境下的,所以要使用commonjs的方式进行配置,所以得使用module.exports = { } 模块

const path = require('path')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' )
    },
    mode:'none'
}

image.png

image.png

5.webpack工作流

image.png

6.webpack的plugins(插件)

1.HtmlWebpackPlugin

1.安装HtmlWebpackPlugin(自动引入资源文件)
npm install --save-dev html-webpack-plugin

2.配置webpack
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' )
    },
    mode:'none',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body'
        })
    ]
}

3.执行npx webpack

2.清理dist(打包之后的文件夹)— 原因:每一次打包都会生成对应html文件或者js文件,我们希望在打包的时候,把旧的文件全部清空,打包完成后,dist里面只有我们最新打包好的文件

需要在webpack.config.js中进行选项的配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true
    },
    mode:'none',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body'
        })
    ]
}

3.当我们编写的代码出错的时候,我们可以通过配置webpack.config.js进行精确定位的配置

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true
    },
    mode:'none',
    // source-map
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body'
        })
    ]
}

4.watch mode(观察者)

通过npx webpack --watch  实时编译打包

5.webpack-dev-server(似live-server的插件)

webpack-dev-server为你提供了一个基本的web server,并且具有live reloading(实时重新加载)功能

1.安装
npm install -- save-dev webpack-dev-server

2.配置webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body'
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    }
}

3.这个webpack.config.js是放在内存中的,无论你删不删dist/app.html,都会触发 热更新 以及 实时打包

7.资源模块

1.Resource资源

1.配置webpack.config.js(第一种方法)

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {
                test: /.png$/,             //以png结尾的图片资源
                type: 'asset/resource'      // 类型为Resource资源
            }
        ]
    }
}

2.配置webpack.config.js(第二种方法)
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {
                test: /.png$/,             // 以png结尾的图片资源
                type: 'asset/resource',     // 类型为Resource资源
                generator: {                // 和上面output一样的配置
                    // filename: 'images/test.png',
                    filename: 'images/[contenthash][ext]'
                }
            }
        ]
    }
}

注意:第二种配置的优先级比第一种的优先级高,因为该配置是在module模块里面的

2.inline资源

1.配置webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // Resource资源
            {
                test: /.png$/,             // 以png结尾的图片资源
                type: 'asset/resource',     // 类型为Resource资源
                generator: {                // 和上面output一样的配置
                    filename: 'images/[contenthash][ext]'
                }
            },
            // inline资源
            // 在dist目录下是看不到资源的,只能在浏览器中查看,并且是个base64的格式
            {
                test: /.svg$/, 
                type: 'asset/inline',     // inline资源
            }

        ]   
    }
}

3.source资源(导入资源的源代码)

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // Resource资源
            {
                test: /.png$/,             // 以png结尾的图片资源
                type: 'asset/resource',     // 类型为Resource资源
                generator: {                // 和上面output一样的配置
                    filename: 'images/[contenthash][ext]'
                }
            },
            // inline资源
            {
                test: /.svg$/, 
                type: 'asset/inline',     // inline资源
            },
            // source资源
            {
                test: /.txt$/, 
                type: 'asset/source',     // source资源
            }
        ]   
    }
}

4.通用数据类型(通用资源类型asset ,在导出一个data URI和发送一个单独的文件之间自动选择(在asset /inline和asset /resource))

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // Resource资源
            {
                test: /.png$/,             // 以png结尾的图片资源
                type: 'asset/resource',     // 类型为Resource资源
                generator: {                // 和上面output一样的配置
                    filename: 'images/[contenthash][ext]'
                }
            },
            // inline资源
            {
                test: /.svg$/, 
                type: 'asset/inline',     // inline资源
            },
            // source资源
            {
                test: /.txt$/, 
                type: 'asset/source',     // source资源
            },
            // 通用资源
            {
                test: /.jpg$/, 
                type: 'asset',     // 通用资源
            },
        ]   
    }
}


2.为什么说它会做自动选择呢,默认当资源大于8k,走的是resource资源,小于8k,走的是inline资源

3.修改asset临界值
module:{
        // 资源模块规则
        rules:[
            // Resource资源
            {
                test: /.png$/,             // 以png结尾的图片资源
                type: 'asset/resource',     // 类型为Resource资源
                generator: {                // 和上面output一样的配置
                    filename: 'images/[contenthash][ext]'
                }
            },
            // inline资源
            {
                test: /.svg$/, 
                type: 'asset/inline',     // inline资源
            },
            // source资源
            {
                test: /.txt$/, 
                type: 'asset/source',     // source资源
            },
            // 通用资源
            {
                test: /.jpg$/, 
                type: 'asset',     // 通用资源
                // 解析器
                parsar:{
                    dataUrlCondition:{
                        // 4M
                        maxSize: 4 * 1024 * 1024
                    }
                }
            },

        ]   
    }

8.loader

1.loader加载CSS模块,并且要

1)安装npm i style-loader -D,作用帮助我们把CSS放在页面上

2)如果使用了sass,less等预处理器,要安装

npm i less-loader less

npm i sass-loader sass

1.普通的css
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // loader加载CSS模块
            {
                test: /.css$/,
                // 先执行css,再执行style,从后往前加载
                use: ['style-loader','css-loader']
            }
        ]   
    }
}


2.使用预编译sass,less
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // loader加载CSS模块
            {
                test: /.(css | less)$/,
                // 先执行css,再执行style,从后往前加载,如果存在的less或者sass
                use: ['style-loader','css-loader','less-loader']
            }
        ]   
    }

2.抽离和压缩CSS

抽离:npm i mini-css-extract-plugin -D (基于webpack5构建的)

压缩:npm i css-minimizer-webpack-plugin -D

1.抽离
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'none',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // loader加载CSS模块
            {
                test: /.css$/,
                use: [ MinCssExtractPlugin.loader,'css-loader' ]
            }
        ]   
    }
}

2.压缩
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // loader加载CSS模块
            {
                test: /.css$/,
                use: [ MinCssExtractPlugin.loader,'css-loader' ]
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

3.加载font字体

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // 加载font字体
            {
                test: /.(woff | woff2 | eot | tff | otf )$/,
                type: 'asset/resource'
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

4.加载数据

要先安装两个loader

npm i csv-loader xml-loader

data.xml会转化为对象

data.csv会转化为数组

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // 加载数据
            {   
                test: /.(csv | tsv )$/,
                use: 'csv-loader'
            },
            {   
                test: /.xml$/,
                use: 'xml-loader'
            },
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

5.自定义JSON模块parser

安装模块包:npm install toml yaml json5 -D

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const toml = require('toml')
const yaml = require('yaml')
const json5 = require('json5')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            // 加入toml
            {
                test:/.toml$/,
                type:'json',
                parser:{
                    parse:toml.parse
                }
            },
            // 加入yaml
            {
                test:/.yaml$/,
                type:'json',
                parser:{
                    parse:yaml.parse
                }
            },
            // 加入json5
            {
                test:/.json5$/,
                type:'json',
                parser:{
                    parse:json5.parse
                }
            },
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

image.png

9.babel-loader(ES6→ES5的解析器,比如Promise)

首先安装三个包

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

  1. bafel-loader :在webpack里应用babel解析ES6的桥梁
  2. ababel/core : babel核心模块
  3. ababel/preset-env : babel预设,一组babel插件的集合
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env']
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

2.regeneratorRuntime插件

regeneratorRuntime 是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法。regeneratorRuntime is not defined这个错误显然是未能正确配置babel

#这个包中包含了regeneratorRuntime,运行时需要
npm install --save @babel/runtime

#这个插件会在需要regeneratorRuntime的地方自动require导包,编译时需要
npm install --save-dev @babel/plugin-transform-runtime

#更多参考这里
https://babeljs.io/docs/en/babel-plugin-transform-runtime
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:'./src/index.js',
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

10.代码分离

1.入口起点

这是迄今为止最简单直观的分离代码的方式。不过,这种方式手动配置较多,并有一些隐患,我们将会解决这些问题。

存在问题:一个loadsh的包会分别打包到不同的html中

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'[name].bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

2.防止重复(本质就是对工具包的单独抽离)

1)第一种防止重复

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:{
            import:'./src/index.js',
            dependOn:'shared'
        },
        another:{
            import:'./src/another_module.js',
            dependOn:'shared'
        },
        // 共享包
        shared:'lodash'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'[name].bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ]
    }
}

2)使用优化配置

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'[name].bundle.js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ],
        // 拆分代码
        splitChunks:{
            chunks:'all'
        }
    }
}

3.动态引入

当涉及到动态代码拆分时, webpack提供了两个类似的技术。第一种,也是推荐选择的方式是,使用符合 ECMAScript提案的 import()语法来实现动态导入。第二种,则是webpack的遗留功能,使用webpack'特定的require.ensure。

4.懒加载

懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。

image.png

5.预获取/预加载模块

Webpack v4.6.0+增加了对预获取和预加载的支持。 在声明import时,使用下面这些内置指令,可以让webpack输出"resource hint(资源提示)",来告知浏览器:

  • prefetch(预获取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源

image.png

image.png

11.缓存

1.输出文件的文件名

我们可以通过替换output.filename 中的substitutions 设置,来定义输出文件的名称。webpack提供了一种使用称为 substitution(可替换模板字符串)的方式,通过带括号字符串来模板化文件名。其中,[contenthash]substitution将根据资源内容创建出唯一hash。当资源内容发生变化时, [contenthash]也会发生变化。

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        // another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'[name].[contenthash].js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ],
        // 拆分代码
        // splitChunks:{
        //     chunks:'all'
        // }
    }
}

2.缓存第三方库

将第三方库(library)(例如 lodash)提取到单独的 vendor chunk文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用client 的长效缓存机制,命中缓存来消除请求,并减少向server获取资源,同时还能保证client代码和server代码版本一致。我们在 optimization.splitChunks 添加如下cacheGroups参数并构建

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        // another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'[name].[contenthash].js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ],
        //拆分代码
        splitChunks:{
            cacheGroups:{
                vendor: {
                    // 通过文件目录的名字去识别
                    test: /[\/]node_modules[\/]/,
                    // 打包的名字
                    name:'vendors',
                    // 对所有的chunks做处理
                    chunks:'all'
                }
            }
        }
    }
}

3.将js文件放到一个文件夹中 目前,全部js文件都在dist文件夹根目录下,我们尝试把它们放到一个文件夹中,这个其实也简单,修改配置文件,在output修改filename

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        // another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'scripts/[name].[contenthash].js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    },
    // 资源模块
    module:{
        // 资源模块规则
        rules:[
            {   
                // 打包的文件
                test:/.js$/,
                // 除去node_modules里面的包
                exclude:/node_modules/,
                use:{
                    loader:'babel-loader',
                    options:{
                        presets:['@babel/preset-env'],
                        plugins:[
                            [
                                '@babel/plugin-transform-runtime'
                            ]
                        ]
                    }
                }
            }
        ]   
    },

    // 优化配置
    optimization: {
        minimizer: [
          new CssMinimizerWebpackPlugin()  
        ],
        //拆分代码
        splitChunks:{
            cacheGroups:{
                vendor: {
                    test: /[\/]node_modules[\/]/,
                    name:'vendors',
                    chunks:'all'
                }
            }
        }
    }
}

12.拆分开发环境和生产环境

1.公共路径

publicPath配置选项在各种场景中都非常有用。你可以通过它来指定应用程序中所有资源的基础路径。 ·基于环境设置 在开发环境中,我们通常有一个assets/文件夹,它与索引页面位于同一级别。这没太大问题,但是,如果我们将所有静态资源托管至CDN,然后想在生产环境中使用呢? 想要解决这个问题,可以直接使用一个environment variable(环境变量)。假设我们有一个变量ASSET_PATH:

const path = require('path')

module.exports = {
    // 打包的入口文件
    entry:{
        index:'./src/index.js',
        // another:'./src/another_module.js'
    },
    // 打包输出文件
    output:{
        // 打包完成的文件名
        filename:'scripts/[name].[contenthash].js',
        // 存放目录
        path: path.resolve( __dirname,'./dist' ),
        // 清理dist的旧文件
        clean:true,
        // Resource资源的文件名
        // assetModuleFilename: 'images/test.png',
        // 不可能所有的资源的文件名都是一样的
        assetModuleFilename: 'images/[contenthash][ext]',
        publicPath:'http://localhost:8080'
    },
    mode:'production',
    devtool: 'inline-source-map',
    plugins:[
        new HtmlWebpackPlugin({
            // 以index.html为模板
            template:'./index.html',
            // 打包出来的名字
            filename:'app.html',
            // 自动引入资源的script标签  注入在html中的body里面
            inject:'body',
        }),
        // 实例化MinCssExtractPlugin
        new MinCssExtractPlugin({
            // 打包出来的名字
            filename:'style/[contenthash].css',
        })
    ],
    // live-server
    devServer:{
        // 需要热更新的目录
        static: './dist'
    }
}

2.环境变量

想要消除 webpack.config.js在开发环境和生产环境之间的差异,你可能需要环境变量(environmentvariable)。 webpack 命令行环境配置的--env 参数,可以允许你传入任意数量的环境变量。而在 webpack.config.js中可以访问到这些环境变量。例如,--env production或--env goal=local。 npx webpack --env goal=local --env production --progress 对于我们的webpack配置,有一个必须要修改之处。通常, module.exports指向配置对象。要使用env变量,你必须将module.exports转换成一个函数︰

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

// 使用npx webpack --env production --env name:'zhangsan'
// 在env中打印 env.name 就可以打印出zhangsan

module.exports = (env) => {
    return {
        // 打包的入口文件
        entry:{
            index:'./src/index.js',
            // another:'./src/another_module.js'
        },
        // 打包输出文件
        output:{
            // 打包完成的文件名
            filename:'scripts/[name].[contenthash].js',
            // 存放目录
            path: path.resolve( __dirname,'./dist' ),
            // 清理dist的旧文件
            clean:true,
            // Resource资源的文件名
            // assetModuleFilename: 'images/test.png',
            // 不可能所有的资源的文件名都是一样的
            assetModuleFilename: 'images/[contenthash][ext]',
            publicPath:'http://localhost:8080'
        },
        mode:env.production ? 'production' : 'development',
        devtool: 'inline-source-map',
        plugins:[
            new HtmlWebpackPlugin({
                // 以index.html为模板
                template:'./index.html',
                // 打包出来的名字
                filename:'app.html',
                // 自动引入资源的script标签  注入在html中的body里面
                inject:'body',
            }),
            // 实例化MinCssExtractPlugin
            new MinCssExtractPlugin({
                // 打包出来的名字
                filename:'style/[contenthash].css',
            })
        ],
        // live-server
        devServer:{
            // 需要热更新的目录
            static: './dist'
        },
        // 资源模块
        module:{
            // 资源模块规则
            rules:[
                {   
                    // 打包的文件
                    test:/.js$/,
                    // 除去node_modules里面的包
                    exclude:/node_modules/,
                    use:{
                        loader:'babel-loader',
                        options:{
                            presets:['@babel/preset-env'],
                            plugins:[
                                [
                                    '@babel/plugin-transform-runtime'
                                ]
                            ]
                        }
                    }
                }
            ]   
        },
    
        // 优化配置
        optimization: {
            minimizer: [
              new CssMinimizerWebpackPlugin()  
            ],
            //拆分代码
            splitChunks:{
                cacheGroups:{
                    vendor: {
                        test: /[\/]node_modules[\/]/,
                        name:'vendors',
                        chunks:'all'
                    }
                }
            }
        }
    }
}

打包好了之后,发现我们代码没有进行压缩,这时候我们要对代码进行压缩,可以通过
安装terser插件:npm install terser-webpack-plugin -D

配置webpack
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 优化配置
optimization: {
  minimizer: [
    new CssMinimizerWebpackPlugin(),
    new TerserWebpackPlugin ()
  ],
}

3.拆分配置文件

目前,生产环境和开发环境使用的是一个配置文件,我们需要将这两个文件单独放到不同的配置文件中。如webpack.config.dev.js(开发环境配置)和 webpack.config.prod.js (生产环境配置)。在项目根目录下创建一个配置文件夹config来存放他们。 webpack.config.dev.js 配置如下:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
        // 打包的入口文件
        entry:{
            index:'./src/index.js',
            another:'./src/another_module.js'
        },
        // 打包输出文件
        output:{
            // 打包完成的文件名
            filename:'scripts/[name].js',
            // 存放目录
            path: path.resolve( __dirname,'../dist' ),
            // 清理dist的旧文件
            clean:true,
            // Resource资源的文件名
            // assetModuleFilename: 'images/test.png',
            // 不可能所有的资源的文件名都是一样的
            assetModuleFilename: 'images/[contenthash][ext]'
        },
        mode:'development',
        devtool: 'inline-source-map',
        plugins:[
            new HtmlWebpackPlugin({
                // 以index.html为模板
                template:'./index.html',
                // 打包出来的名字
                filename:'app.html',
                // 自动引入资源的script标签  注入在html中的body里面
                inject:'body',
            }),
            // 实例化MinCssExtractPlugin
            new MinCssExtractPlugin({
                // 打包出来的名字
                filename:'style/[contenthash].css',
            })
        ],
        // live-server
        devServer:{
            // 需要热更新的目录
            static: './dist'
        },
        // 资源模块
        module:{
            // 资源模块规则
            rules:[
                {   
                    // 打包的文件
                    test:/.js$/,
                    // 除去node_modules里面的包
                    exclude:/node_modules/,
                    use:{
                        loader:'babel-loader',
                        options:{
                            presets:['@babel/preset-env'],
                            plugins:[
                                [
                                    '@babel/plugin-transform-runtime'
                                ]
                            ]
                        }
                    }
                }
            ]   
        },
    
        // 优化配置
        optimization: {
            //拆分代码
            splitChunks:{
                cacheGroups:{
                    vendor: {
                        test: /[\/]node_modules[\/]/,
                        name:'vendors',
                        chunks:'all'
                    }
                }
            }
        }
    }

webpack.config.prod.js 配置如下:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')

module.exports = {
        // 打包的入口文件
        entry:{
            index:'./src/index.js',
            // another:'./src/another_module.js'
        },
        // 打包输出文件
        output:{
            // 打包完成的文件名
            filename:'scripts/[name].[contenthash].js',
            // 存放目录
            path: path.resolve( __dirname,'../dist' ),
            // 清理dist的旧文件
            clean:true,
            // Resource资源的文件名
            // assetModuleFilename: 'images/test.png',
            // 不可能所有的资源的文件名都是一样的
            assetModuleFilename: 'images/[contenthash][ext]',
            publicPath:'http://localhost:8080'
        },
        mode:'production',
        plugins:[
            new HtmlWebpackPlugin({
                // 以index.html为模板
                template:'./index.html',
                // 打包出来的名字
                filename:'app.html',
                // 自动引入资源的script标签  注入在html中的body里面
                inject:'body',
            }),
            // 实例化MinCssExtractPlugin
            new MinCssExtractPlugin({
                // 打包出来的名字
                filename:'style/[contenthash].css',
            })
        ],
        // 资源模块
        module:{
            // 资源模块规则
            rules:[
                {   
                    // 打包的文件
                    test:/.js$/,
                    // 除去node_modules里面的包
                    exclude:/node_modules/,
                    use:{
                        loader:'babel-loader',
                        options:{
                            presets:['@babel/preset-env'],
                            plugins:[
                                [
                                    '@babel/plugin-transform-runtime'
                                ]
                            ]
                        }
                    }
                }
            ]   
        },
    
        // 优化配置
        optimization: {
            minimizer: [
              new CssMinimizerWebpackPlugin()  
            ],
            //拆分代码
            splitChunks:{
                cacheGroups:{
                    vendor: {
                        test: /[\/]node_modules[\/]/,
                        name:'vendors',
                        chunks:'all'
                    }
                }
            }
        }
    }

4.提取公共配置

这时,我们发现这两个配置文件里存在大量的重复代码,可以手动的将这些重复的代码单独提取到一个文件里,创建webpack.config.common.js,配置公共的内容:

把env,prod公共的文件提取出来到common中
保留env,prod私有的

// 合并并配置文件,并在项目目录下创建webpack.config.js
1.npm i webpack-merge -D

// 配置webpack.config.js
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.config.common ");
const productionConfig = require("./webpack.config.prod ");
const developmentConfig = require("./webpack.config.dev ");
module.exports = (env) => {
  switch (true) {
    case env.development:
      return merge(commonConfig, developmentConfig);
    case env.production:
      return merge(commonConfig, productionconfig);
    default:
      return new Error("No matching configuration was found");
  }
};