webpack5 配置

294 阅读2分钟

配置

webpack是一种前端资源构建工具,一个静态模块打包器。
在webpack看来,前端的所有资源文件(js/css/img/less/...)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。

开发环境

const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin')
const os = require('os');
const threads = os.cpus().length;
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        fileName: 'static/js/main.js',
        chunkFilename: 'static/js/[name].chunk.js',
        assetModuleFilename: 'static/media/[hash:10].[ext][query]'
        // clean: true, // 自动清空上次打包结果 在打包前将path整个目录内容清空,再进行打包
    },
    module: {
        rules: [
            {
                oneOf: [
                    {
                        test: /\.(css|less)$/,
                        use: [
                            'style-loader', // 将js中css通过创建style标签添加到html中生效
                            'css-loader', // 将css资源编译成commonjs的模块到js中
                            'less-loader', // 将less编译成css
                        ]
                    },
                    {
                        test: /\.(png|jpg|gif|svg)$/,
                        type: 'asset',
                        parser: {
                            dataUrlCOndition: {
                                // 小于10KB的图片转base64
                                // 优点:减少请求数量 缺点:体积会更大
                                maxSize: 10 * 1024
                            }
                        },
                        generator: {
                            // 输出图片名称 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]'
                        // }
                    },
                    {
                        test: /\.js$/,
                        exclude: /node_modules/,
                        use: [
                            {
                                loader: 'thread-loader',
                                works: threads,
                            },
                            {
                            loader: 'babel-loader',
                            options: { // 可以写在babel.config.js
                                preset: [
                                    [
                                        '@babel/preset-env', 
                                        {
                                            useBuiltIns: 'usage',
                                            corejs: 3,
                                        }
                                    ]
                                ],
                                cacheDirectory: true, // 开启babel缓存
                                cacheCompression: false, // 关闭缓存压缩
                                plugins: ["@balel/plugin-transform-runtime"],
                            }
                        }]
                    }
                ]
            }
        ]
    },
    plugin: [
        new ESLintPlugin({
            // 检测哪些文件
            context: path.resolve(__dirname, 'src'),
            exclude: 'node_modules', // 默认值
            cache: true,
            cacheLocation: path.resolve(__dirname, 'node_modules/.cache/eslintcache'),
            threads,
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/index.html')
        }),
        new PreloadWebpackPlugin({
            // rel: 'preload',
            // as: 'script',
            rel: 'prefetch',
        })
    ],
    optimization: {
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin({
                parallel: threads
            })
        ],
        splitChunks: {
            chunks: 'all',
            cacheGroups: { // 单入口文件不需要配置
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            },
            // 一个文件改变,contenthash更新,所有依赖他的文件都会跟着变化,缓存失效
            // 把hash值保存在一个runtime文件
            runtimeChunk: (entrypoint) => `runtime~${entrypoint.name}.js`
        }
    },
    mode: 'development',
    // 不输出资源 在内存中编译打包
    devServer: {
        host: 'localhost', //启动服务器的域名
        port: 3000,
        open: true, // 是否自动打开浏览器,
        hot: true
    }
}

生产环境

const path = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin')
const os = require('os');
const threads = os.cpus().length;
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'static/js/main.js',
        chunkFilename: 'static/js/[name].chunk.js',
        assetModuleFilename: 'static/media/[hash:10].[ext][query]'
        // clean: true, // 自动清空上次打包结果 在打包前将path整个目录内容清空,再进行打包
    },
    module: {
        rules: [
            {
                oneOf: [
                    {
                        test: /\.(css|less)$/,
                        use: [
                            MiniCssExtractPlugin.loader,
                            // 'style-loader', // 将js中css通过创建style标签添加到html中生效
                            'css-loader', // 将css资源编译成commonjs的模块到js中
                            // 解决css兼容性问题 postcss-loader postcss postcss-preset-env
                            {
                                loader: 'postcss-loader',
                                options: {
                                    postcssOptions: {
                                        plugins: ['postcss-preset-env']
                                    }
                                }
                            },
                            'less-loader', // 将less编译成css
                        ]
                    },
                    {
                        test: /\.(png|jpg|gif|svg)$/,
                        type: 'asset',
                        parser: {
                            dataUrlCOndition: {
                                // 小于10KB的图片转base64
                                // 优点:减少请求数量 缺点:体积会更大
                                maxSize: 10 * 1024
                            }
                        },
                        generator: {
                            // 输出图片名称 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]'
                        // }
                    },
                    {
                        test: /\.js$/,
                        exclude: /node_modules/,
                        use: [
                            {
                                loader: 'thread-loader',
                                works: threads,
                            },
                            {
                            loader: 'babel-loader',
                            options: { // 可以写在babel.config.js
                                preset: [
                                    [
                                        '@babel/preset-env', 
                                        {
                                            useBuiltIns: 'usage',
                                            corejs: 3,
                                        }
                                    ]
                                ],
                                cacheDirectory: true, // 开启babel缓存
                                cacheCompression: false, // 关闭缓存压缩
                                plugins: ["@balel/plugin-transform-runtime"],
                            }
                        }]
                    }
                ]
            }
        ]
    },
    plugin: [
        new ESLintPlugin({
            // 检测哪些文件
            context: path.resolve(__dirname, 'src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, 'node_modules/.cache/eslintcache'),
            threads,
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/index.html')
        }),
        // 提取css成单独文件 css目前被打包到js文件中,当js文件加载时,会创建一个style标签
        // 来生成样式,这样对于网站来说,会出现闪屏现象,用户体验不好
        // 我们应该是单独的css文件,通过link标签加载性能才好
        new MiniCssExtractPlugin({
            filename: 'static/css/[name].[contenthash:10].css',
            chunkFilename: 'static/css/[name].chunk.[contenthash:10].css',
        })
        // css压缩 生产环境html js自动压缩
        // new CssMinimizerWebpackPlugin(),
        // new TerserWebpackPlugin({
        //     parallel: threads
        // })
        new PreloadWebpackPlugin({
            // rel: 'preload',
            // as: 'script',
            rel: 'prefetch',
        })
    ],
    optimization: {
        minimizer: [
            new CssMinimizerWebpackPlugin(),
            new TerserWebpackPlugin({
                parallel: threads
            })
        ],
        splitChunks: {
            chunks: 'all',
            cacheGroups: { // 单入口文件不需要配置
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            },
            // 一个文件改变,contenthash更新,所有依赖他的文件都会跟着变化,缓存失效
            // 把hash值保存在一个runtime文件
            runtimeChunk: (entrypoint) => `runtime~${entrypoint.name}.js`
        }
    },
    mode: 'production',
}