webpack5 (四)

react-cli 中配置

开发环境

javascript 复制代码
const path = require('path')
const EslintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
//封装处理样式配置
const getStyleloaders = (pre)=>{
    return [
        'style-loader',
        'css-loader',
        // 处理 css 兼容性问题
        //需要配合 package.json 中的browserslist 来指定兼容性做到什么程度
        {
            loader: 'postcss-loader',
            options: {
                postcssOptions: {
                    plugins: 'postcss-preset-env'
                }
            }
        },
        pre
    ].filter(Boolean)
};
//要用 commonjs的方式以对象的模式暴露出去
module.exports = {
    // 入口文件
    entry: './src/main.js',
    // 出口文件
    output: {
        path: undefined,
        filename: 'static/js/[name].js',
        chunkFilename: 'static/js/[name].chunk.js',
        assetModuleFilename: 'static/media/[hash:10][etx][query]'
    },
    // 配置loader
    module: {
        rules: [
            // 处理 css 
            {
                test: /\.css$/,
                use: getStyleloaders()
            },
            {
                test: /\.less$/,
                use: getStyleloaders('less-loader')
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleloaders('sass-loader')
            },
            {
                test: /\.styl$/,
                use: getStyleloaders('stylus-loader')
            },
            // 处理 图片
            {
                test:/\.(jpe?g|png|gif|webp|svg)$/,
                type:'asset',
                parser:{
                    dataUrlCondition:{
                        maxSize:10*1024,
                    }
                }
            },
            //处理其他资源
            {
                test:/\.(woff2?|ttf)$/,
                type:'asset/resource'
            },
            // 处理 js
            {
                test:/\.jsx?$/,
                include:path.resolve(__dirname,'../src'),
                loader:'babel-loader',//babel 也需要有一个 babel 的配置文件
                options:{
                    catchDirectory:true,
                    catchCompression:false,
                    plugins:[
                        'react-refresh/babel',//用来解决react脚手架下 js不能热更新的问题
                    ]
                }
            }
        ]
    },
    // 配置plugin
    // 处理html 
    plugin:[
        //eslint 插件也是需要有自己的配置文件
        new EslintWebpackPlugin({
            context:path.resolve(__dirname,'../src'),
            exclude:'node_modules',
            cache:true,
            cacheLocation:path.resolve(__dirname,'../node_modules/.catch/.eslintcache'),
        }),
        new HtmlWebpackPlugin({
            template:path.resolve(__dirname,'../public/index.html'),
        }),
        new ReactRefreshWebpackPlugin()//用来解决react脚手架下 js不能热更新的问题
    ],
    // 环境设置
    mode:'development',
    devtool:'cheap-module-source-map',
    optimization:{
        splitChunks:{
            chunks:'all'
        },
        runtimeChunk:{
            name:(entrypoint)=>`runtime~${entrypoint.name}.js`,
        }
    },
    //webpack 解析模块加载选项 
    // 解决运行react项目时报错 Module not found:Error:can't resolve './App' in 'xx/xxx/xxx/x'
    resolve:{
        //自动补全文件扩展名
        extentions:['.jsx','.js','json']
    },
    devServer:{
        host:'localhost',
        port:3000,
        open:true,
        hot:true,
        historyApiFallback:true,//解决前端路由刷新404问题
    }
}

生产模式

javascript 复制代码
const path = require('path')
const EslintWebpackPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 生产模式下不需要激活热更新
// const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
// CSS提取为单独文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css 压缩文件
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
// js 压缩,使用css压缩后必须使用的插件
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 图片 压缩插件
const ImageMinimizerWebpackPlugin = require('image-minimizer-webpack-plugin')
// 如果出现 网站图标 需要用该复制插件将其复制到dist目录下
const CopyPlugin = require("copy-webpack-plugin");


const getStyleloaders = (pre) => {
    return [
        // 'style-loader',
        MiniCssExtractPlugin.loader,//将style-loader替换为插件loader,打包为单独文件
        'css-loader',
        {
            loader: 'postcss-loader',
            options: {
                postcssOptions: {
                    plugins: 'postcss-preset-env'
                }
            }
        },
        pre
    ].filter(Boolean)
};
module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, '../dist'),//设置出口文件路径
        filename: 'static/js/[name].[contenthash:10].js',//加入哈希值
        chunkFilename: 'static/js/[name].[contenthash:10].chunk.js',//加入哈希值
        assetModuleFilename: 'static/media/[hash:10][etx][query]',
        clean: true,//将上次打包内容清空
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: getStyleloaders()
            },
            {
                test: /\.less$/,
                use: getStyleloaders('less-loader')
            },
            {
                test: /\.s[ac]ss$/,
                use: getStyleloaders('sass-loader')
            },
            {
                test: /\.styl$/,
                use: getStyleloaders('stylus-loader')
            },
            {
                test: /\.(jpe?g|png|gif|webp|svg)$/,
                type: 'asset',
                parser: {
                    dataUrlCondition: {
                        maxSize: 10 * 1024,
                    }
                }
            },
            {
                test: /\.(woff2?|ttf)$/,
                type: 'asset/resource'
            },
            {
                test: /\.jsx?$/,
                include: path.resolve(__dirname, '../src'),
                loader: 'babel-loader',
                options: {
                    catchDirectory: true,
                    catchCompression: false,

                    // 生产模式下不需要激活热更新
                    // plugins:[
                    //     'react-refresh/babel',
                    // ]
                }
            }
        ]
    },
    plugin: [
        new EslintWebpackPlugin({
            context: path.resolve(__dirname, '../src'),
            exclude: 'node_modules',
            cache: true,
            cacheLocation: path.resolve(__dirname, '../node_modules/.catch/.eslintcache'),
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, '../public/index.html'),
        }),
        // new ReactRefreshWebpackPlugin(),// 生产模式下不需要激活热更新
        // css 打包为单独文件插件
        new MiniCssExtractPlugin({
            filename: 'static/css/name.[contenthash:10].css',
            chunkFilename: 'static/css/name.[contenthash:10].chunk.css'
        }),
        // 复制插件 处理public下其他资源 如网站图标
        new CopyPlugin({
            patterns: [
                // 设置从何处复制到何处
                {
                    from: path.resolve(__dirname,'../public'),
                    to: path.resolve(__dirname,'../dist')
                },
            ],
            globOptions: {
                //设置忽略 index.html 文件
                ignore: ['**/index.html']
            }
        }),
    ],
    mode: 'production', // 改为生产模式
    devtool: 'source-map',//使用 source-map
    optimization: {
        splitChunks: {
            chunks: 'all'
        },
        runtimeChunk: {
            name: (entrypoint) => `runtime~${entrypoint.name}.js`,
        },
        // 压缩插件放在 optimization 对象内
        minimizer: [
            new CssMinimizerWebpackPlugin(),//压缩 css 插件,
            new TerserWebpackPlugin(),//压缩 js 插件,
            //压缩图片插件,
            new ImageMinimizerWebpackPlugin({
                minimizerOptions: {
                    plugins: [
                        ["gifsicle", { interlaced: true }],
                        ["jpegtran", { progressive: true }],
                        ["optipng", { optimizationLevel: 5 }],
                        [
                            "svgo",
                            {
                                plugins: extendDefaultPlugins([
                                    {
                                        name: "removeViewBox",
                                        active: false,
                                    },
                                    {
                                        name: "addAttributesToSVGElement",
                                        params: {
                                            attributes: [{ xmlns: "http://www.w3.org/2000/svg" }],
                                        },
                                    },
                                ]),
                            },
                        ],
                    ],
                },
            }),
        ]
    },
    resolve: {
        extentions: ['.jsx', '.js', 'json']
    },

    //生产模式不需要devsever
    // devServer:{
    //     host:'localhost',
    //     port:3000,
    //     open:true,
    //     hot:true,
    //     historyApiFallback:true,
    // }
}

合并配置

将生产模式和开发模式的配置进行合并,通过 process.env.NODE_ENV 的值来判断当前为生产环境还是开发环境。

javascript 复制代码
const isProd = process.env.NODE_ENV ==='production'


//三元判断 加载哪一个插件
isProd ? MiniCssExtractPlugin.loader : 'style-loader',


//根据是否为生产模式来决定是否加载插件
plugins:[
    !isProd && 'react-refresh/babel',//用来解决react脚手架下 js不能热更新的问题
].filter(Boolean)
相关推荐
糕冷小美n8 小时前
elementuivue2表格不覆盖整个表格添加固定属性
前端·javascript·elementui
小哥不太逍遥8 小时前
Technical Report 2024
java·服务器·前端
沐墨染8 小时前
黑词分析与可疑对话挖掘组件的设计与实现
前端·elementui·数据挖掘·数据分析·vue·visual studio code
anOnion8 小时前
构建无障碍组件之Disclosure Pattern
前端·html·交互设计
threerocks8 小时前
前端将死,Agent 永生
前端·人工智能·ai编程
问道飞鱼9 小时前
【前端知识】Vite用法从入门到实战
前端·vite·项目构建
爱上妖精的尾巴9 小时前
8-10 WPS JSA 正则表达式:贪婪匹配
服务器·前端·javascript·正则表达式·wps·jsa
Aliex_git11 小时前
浏览器 API 兼容性解决方案
前端·笔记·学习
独泪了无痕11 小时前
useStorage:本地数据持久化利器
前端·vue.js
程序员林北北11 小时前
【前端进阶之旅】JavaScript 一些常用的简写技巧
开发语言·前端·javascript