webpack/vite配置

webpack配置

webpack.base.cjs

js 复制代码
// 导入 Node.js 内置的 path 模块,用于处理文件路径
const path = require('path');
// 导入 vue-loader 插件,用于处理 .vue 文件
const { VueLoaderPlugin } = require('vue-loader');
// 导入 HtmlWebpackPlugin,用于生成 HTML 文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 导入 unplugin-auto-import 的 webpack 版本,用于自动导入 Vue 组合式 API
const AutoImport = require('unplugin-auto-import/webpack');
// 导入 unplugin-vue-components 的 webpack 版本,用于自动导入 Vue 组件
const Components = require('unplugin-vue-components/webpack');
// 导入 ElementPlusResolver,用于自动导入 Element Plus 组件和样式
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');

// 导出 webpack 配置对象
module.exports = {
    // 入口文件配置
    entry: './src/main.ts',

    // 输出配置
    output: {
        // 输出目录,使用绝对路径
        path: path.resolve(__dirname, 'dist'),
    },

    // 解析配置
    resolve: {
        // 路径别名配置
        alias: {
            // 将 @ 别名指向 src 目录
            '@': path.resolve(__dirname, 'src'),
        },
        // 自动解析的扩展名列表,这样导入时可以省略扩展名
        extensions: ['.ts', '.tsx', '.js', '.jsx', '.vue', '.json'],
    },

    // 插件配置
    plugins: [
        // 自动导入配置
        AutoImport({
            // 解析器配置,使用 ElementPlusResolver 自动导入 Element Plus
            resolvers: [ElementPlusResolver()],
        }),
        // 自动组件导入配置
        Components({
            // 解析器配置,使用 ElementPlusResolver 自动导入 Element Plus 组件
            resolvers: [ElementPlusResolver()],
        }),
        // VueLoaderPlugin 必须配置,用于编译 Vue 单文件组件
        new VueLoaderPlugin(),
        // HtmlWebpackPlugin 配置,用于生成 HTML 文件
        new HtmlWebpackPlugin({
            // 使用 public/index.html 作为模板
            template: './public/index.html',
        }),
    ],

    // 模块配置
    module: {
        // 规则配置,用于处理不同类型的文件
        rules: [
            // 处理 .vue 文件的规则
            {
                // 匹配 .vue 文件
                test: /\.vue$/,
                // 使用 vue-loader 处理
                loader: 'vue-loader',
                // vue-loader 选项配置
                options: {
                    // 编译器选项
                    compilerOptions: {
                        // 不保留空格,减小文件体积
                        preserveWhitespace: false,
                    },
                },
            },
            // 处理 .ts 文件的规则
            {
                // 匹配 .ts 文件
                test: /\.ts$/,
                // 排除 node_modules 目录
                exclude: /node_modules/,
                // 使用多个 loader 处理
                use: [
                    // 首先使用 babel-loader 处理
                    {
                        loader: 'babel-loader',
                        // babel-loader 选项
                        options: {
                            // 使用 @babel/preset-env 预设,将 ES6+ 转换为 ES5
                            presets: ['@babel/preset-env'],
                            // 使用 @babel/plugin-transform-runtime 插件,避免重复注入 helper 函数
                            plugins: ['@babel/plugin-transform-runtime'],
                        },
                    },
                    // 然后使用 ts-loader 处理
                    {
                        loader: 'ts-loader',
                        // ts-loader 选项
                        options: {
                            // 为 .vue 文件添加 .ts 后缀,以便 ts-loader 处理
                            appendTsSuffixTo: [/\.vue$/],
                            // 只进行转译,不进行类型检查,提高构建速度
                            transpileOnly: true,
                        },
                    },
                ],
            },
            // 处理 .js 文件的规则
            {
                // 匹配 .js 文件
                test: /\.js$/,
                // 排除 node_modules 目录
                exclude: /node_modules/,
                // 使用 babel-loader 处理
                use: {
                    loader: 'babel-loader',
                    // babel-loader 选项
                    options: {
                        // 使用 @babel/preset-env 预设,将 ES6+ 转换为 ES5
                        presets: ['@babel/preset-env'],
                        // 使用 @babel/plugin-transform-runtime 插件,避免重复注入 helper 函数
                        plugins: ['@babel/plugin-transform-runtime'],
                    },
                },
            },
            // 处理 .css 文件的规则
            {
                // 匹配 .css 文件
                test: /\.css$/,
                // 使用 style-loader 和 css-loader 处理
                // 执行顺序:从右到左,先使用 css-loader 解析 CSS,再使用 style-loader 将 CSS 插入到页面
                use: ['style-loader', 'css-loader'],
            },
            // 处理 .scss 和 .sass 文件的规则
            {
                // 匹配 .scss 和 .sass 文件
                test: /\.s[ac]ss$/i,
                // 使用 style-loader、css-loader 和 sass-loader 处理
                // 执行顺序:从右到左,先使用 sass-loader 编译 Sass,再使用 css-loader 解析 CSS,最后使用 style-loader 将 CSS 插入到页面
                use: ['style-loader', 'css-loader', 'sass-loader'],
            },
            // 处理图片文件的规则
            {
                // 匹配 png、jpg、jpeg、gif 和 webp 格式的图片文件
                test: /\.(png|jpe?g|gif|webp)$/i,
                // 使用 file-loader 处理,将图片文件复制到输出目录并返回文件路径
                use: 'file-loader',
            },
        ],
    },
};

webpack.dev.cjs

js 复制代码
// 导入 webpack-merge 模块,用于合并 webpack 配置
const { merge } = require('webpack-merge');
// 导入基础配置文件
const baseConfig = require('./webpack.base.cjs');
// 导入 Node.js 内置的 path 模块,用于处理文件路径
const path = require('path');

// 合并基础配置和开发环境配置
module.exports = merge(baseConfig, {
    // 模式设置为开发环境
    mode: 'development',

    // 输出配置
    output: {
        // 输出文件名,开发环境使用简单的 bundle.js
        filename: 'bundle.js',
    },

    // 开发工具配置,用于生成 source map
    // eval-cheap-module-source-map 能在开发时提供较好的性能和调试体验
    devtool: 'eval-cheap-module-source-map',

    // 开发服务器配置
    devServer: {
        // 静态文件目录配置
        static: {
            // 指定 public 目录为静态文件目录
            directory: path.join(__dirname, 'public'),
        },
        // 是否启用 gzip 压缩
        compress: true,
        // 开发服务器端口
        port: 8000,
        // 是否启用热模块替换(HMR)
        hot: true,
        // 构建完成后是否自动打开浏览器
        open: true,
        // 客户端配置
        client: {
            // 错误和警告的覆盖层配置
            overlay: {
                // 显示错误覆盖层
                errors: true,
                // 不显示警告覆盖层
                warnings: false,
            },
        },
        // 支持 SPA 路由,所有 404 请求都会返回 index.html
        historyApiFallback: true,
        // 代理配置,用于将 API 请求代理到后端服务器
        proxy: [
            {
                // 匹配需要代理的路径
                context: ['/test'],
                // 代理目标地址
                target: 'http://localhost:3000',
                // 是否验证 SSL 证书
                secure: false,
                // 是否修改请求头中的 Origin
                changeOrigin: true,
                // 路径重写配置(当前已注释)
                // pathRewrite: {
                //     '^/api': ''
                // }
            },
        ],
    },

    // 优化配置
    optimization: {
        // 启用 tree shaking,只打包使用到的代码
        usedExports: true,
    },
});

webpack.prod.cjs

js 复制代码
// 导入 webpack-merge 模块,用于合并 webpack 配置
const { merge } = require('webpack-merge');
// 导入基础配置文件
const baseConfig = require('./webpack.base.cjs');
// 导入 TerserPlugin,用于压缩 JavaScript 代码
const TerserPlugin = require('terser-webpack-plugin');
// 导入 CssMinimizerPlugin,用于压缩 CSS 代码
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// 导入 BundleAnalyzerPlugin,用于分析打包后的文件结构和大小
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

// 合并基础配置和生产环境配置
module.exports = merge(baseConfig, {
    // 模式设置为生产环境
    mode: 'production',

    // 输出配置
    output: {
        // 输出文件名,使用 contenthash 确保文件内容变化时文件名变化,有利于缓存
        filename: 'bundle.[contenthash].js',
        // 构建前清理输出目录
        clean: true,
    },
    devtool: 'hidden-source-map',
    // 优化配置
    optimization: {
        // 启用代码压缩
        minimize: true,
        // 配置压缩器
        minimizer: [
            // JavaScript 压缩器配置
            new TerserPlugin({
                // Terser 配置选项
                terserOptions: {
                    // 压缩配置
                    compress: {
                        // 删除所有 console 语句
                        drop_console: true,
                        // 删除所有 debugger 语句
                        drop_debugger: true,
                    },
                },
            }),
            // CSS 压缩器
            new CssMinimizerPlugin(),
            // 打包分析工具配置
            new BundleAnalyzerPlugin({
                // 分析模式设置为静态文件
                analyzerMode: 'static',
                // 不自动打开分析报告
                openAnalyzer: false,
            }),
        ],
        // 代码分割配置
        splitChunks: {
            // 对所有类型的 chunk 进行拆分(包括异步和同步)
            chunks: 'all',
            // 控制生成 chunk 的最小大小(20KB)
            minSize: 20000,
            // 剩余大小的最小值,确保拆分后剩余部分不会过小
            minRemainingSize: 0,
            // 模块被引用的最小次数
            minChunks: 1,
            // 异步加载时的最大请求数
            maxAsyncRequests: 30,
            // 初始加载时的最大请求数
            maxInitialRequests: 30,
            // 强制执行大小阈值(50KB),超过此值的 chunk 会被强制拆分
            enforceSizeThreshold: 50000,
            // 缓存组配置,用于将不同类型的模块分割到不同的 chunk 中
            cacheGroups: {
                // Element Plus 组件库缓存组
                elementPlus: {
                    // 输出文件名
                    name: 'element-plus',
                    // 匹配 Element Plus 模块
                    test: /[\/]node_modules[\/]element-plus[\/]/,
                    // 优先级,数字越大优先级越高
                    priority: 20,
                    // 对所有类型的 chunk 生效
                    chunks: 'all',
                    // 重用已存在的 chunk,避免重复打包
                    reuseExistingChunk: true,
                },
                // Vue Router 路由库缓存组
                vueRouter: {
                    name: 'vue-router',
                    test: /[\/]node_modules[\/]vue-router[\/]/,
                    priority: 20,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // Pinia 状态管理库缓存组
                pinia: {
                    name: 'pinia',
                    test: /[\/]node_modules[\/]pinia[\/]/,
                    priority: 20,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // Axios HTTP 客户端库缓存组
                axios: {
                    name: 'axios',
                    test: /[\/]node_modules[\/]axios[\/]/,
                    priority: 20,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // Vue 核心库缓存组
                vue: {
                    name: 'vue',
                    test: /[\/]node_modules[\/]vue[\/]/,
                    priority: 20,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // VueUse 工具库缓存组
                vueUse: {
                    name: 'vue-use',
                    test: /[\/]node_modules[\/]@vueuse[\/]/,
                    priority: 20,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // 公共代码缓存组
                common: {
                    name: 'common',
                    // 至少被引用 2 次的模块才会被打包到这个 chunk
                    minChunks: 2,
                    priority: 5,
                    chunks: 'all',
                    reuseExistingChunk: true,
                },
                // 其他第三方依赖缓存组
                vendors: {
                    name: 'vendors',
                    // 匹配所有 node_modules 中的模块
                    test: /[\/]node_modules[\/]/,
                    priority: 10,
                    // 只对初始加载的 chunk 生效
                    chunks: 'initial',
                    reuseExistingChunk: true,
                    // 强制执行缓存组,即使不符合其他条件
                    enforce: true,
                },
            },
        },
        // 运行时代码分割配置
        runtimeChunk: {
            // 运行时代码的输出文件名
            name: 'runtime',
        },
    },
});

vite配置

vite.base.ts

js 复制代码
// 导入Vite的defineConfig函数,用于定义Vite配置
import { defineConfig } from 'vite';
// 导入Vue插件,用于支持Vue组件
import vue from '@vitejs/plugin-vue';
// 导入自动导入插件,用于自动导入Vue API和其他库
import AutoImport from 'unplugin-auto-import/vite';
// 导入组件自动注册插件,用于自动注册Vue组件
import Components from 'unplugin-vue-components/vite';
// 导入Element Plus解析器,用于自动导入Element Plus组件和API
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
// 导入Node.js的path模块,用于处理文件路径
import path from 'path';

// 导出公共配置
export default defineConfig({
    // 设置项目基础路径,使用相对路径
    base: './',

    // 配置Vite插件
    plugins: [
        // 使用Vue插件
        vue(),

        // 配置自动导入插件
        AutoImport({
            // 使用Element Plus解析器
            resolvers: [ElementPlusResolver()],
            // 生成类型声明文件
            dts: true,
            // 自动导入的库
            imports: ['vue', 'vue-router', 'pinia'],
        }),

        // 配置组件自动注册插件
        Components({
            // 使用Element Plus解析器
            resolvers: [ElementPlusResolver()],
            // 生成类型声明文件
            dts: true,
            // 组件所在目录
            dirs: ['./src/components'],
        }),
    ],

    // 配置模块解析
    resolve: {
        // 配置路径别名
        alias: {
            // 将@符号指向src目录
            '@': path.resolve(__dirname, './src'),
        },
        // 配置文件扩展名,导入时可以省略
        extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    },

    // 配置CSS
    css: {
        // 配置预处理器选项
        preprocessorOptions: {
            // SCSS预处理器配置
            scss: {
                // 移除了additionalData,因为style.css已经在main.ts中导入
            },
        },
    },

    // 配置开发服务器
    server: {
        // 服务器端口
        port: 9000,
        // 自动打开浏览器
        open: true,
        // 允许外部访问
        host: '0.0.0.0',
        // 配置代理
        proxy: {
            // 将/test路径代理到http://localhost:3000
            '/test': {
                // 代理目标地址
                target: 'http://localhost:3000',
                // 改变请求头中的Origin
                changeOrigin: true,
                // 允许HTTPS证书无效
                secure: false,
            },
        },
    },

    // 配置依赖优化
    optimizeDeps: {
        // 预构建的依赖列表
        include: ['vue', 'vue-router', 'pinia', 'axios', 'element-plus', '@vueuse/core'],
    },
});

vite.dev.ts

js 复制代码
// 导入Vite的defineConfig和mergeConfig函数
// defineConfig用于定义Vite配置,mergeConfig用于合并配置
import { defineConfig, mergeConfig } from 'vite';

// 导入公共配置
import baseConfig from './vite.base.ts';

// 导出开发环境配置
export default defineConfig(
    // 使用mergeConfig合并公共配置和开发环境配置
    mergeConfig(
        // 公共配置
        baseConfig,
        // 开发环境特定配置
        defineConfig({
            // 设置环境模式为development
            mode: 'development',
            // 配置全局常量替换
            define: {
                // Vue feature flag for hydration mismatch details
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
            },
            // 配置构建选项
            build: {
                // 构建输出目录
                outDir: 'dist',
                // 静态资源输出目录
                assetsDir: 'assets',
                // 开发环境启用sourcemap,便于调试
                sourcemap: true,
                // 开发环境不压缩代码,提高构建速度
                minify: false,
            },
        })
    )
);

vite.prod.ts

js 复制代码
// 导入Vite的defineConfig和mergeConfig函数
// defineConfig用于定义Vite配置,mergeConfig用于合并配置
import { defineConfig, mergeConfig } from 'vite';

// 导入构建分析工具,用于生成构建包大小分析报告
import { visualizer } from 'rollup-plugin-visualizer';

// 导入Gzip压缩插件,用于压缩静态资源
import Compression from 'vite-plugin-compression';

// 导入公共配置
import baseConfig from './vite.base.ts';

// 导出生产环境配置
export default defineConfig(
    // 使用mergeConfig合并公共配置和生产环境配置
    mergeConfig(
        // 公共配置
        baseConfig,
        // 生产环境特定配置
        defineConfig({
            // 设置环境模式为production
            mode: 'production',
            // 配置全局常量替换
            define: {
                // Vue feature flag for hydration mismatch details
                __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true,
            },
            // 配置生产环境特定插件
            plugins: [
                // 构建分析工具配置
                visualizer({
                    // 构建完成后不自动打开报告
                    open: false,
                    // 显示gzip压缩后的大小
                    gzipSize: true,
                    // 显示brotli压缩后的大小
                    brotliSize: true,
                    // 报告生成路径
                    filename: 'dist/stats.html',
                }),

                // Gzip压缩插件配置
                Compression({
                    // 输出压缩信息
                    verbose: true,
                    // 启用压缩
                    disable: false,
                    // 压缩阈值,大于10KB的文件才会被压缩
                    threshold: 10240,
                    // 压缩算法
                    algorithm: 'gzip',
                    // 压缩文件扩展名
                    ext: '.gz',
                }),
            ],

            // 配置构建选项
            build: {
                // 构建输出目录
                outDir: 'dist',
                // 静态资源输出目录
                assetsDir: 'assets',
                // 生产环境禁用sourcemap,减少文件大小
                sourcemap: false,
                // 生产环境使用terser进行代码压缩
                minify: 'terser',

                // terser压缩配置
                terserOptions: {
                    // 压缩选项
                    compress: {
                        // 移除console语句
                        drop_console: true,
                        // 移除debugger语句
                        drop_debugger: true,
                    },
                },

                // 输出配置(使用rolldown替代rollup)
                rollupOptions: {
                    output: {
                        // 入口文件命名规则
                        entryFileNames: 'assets/js/[name].[hash].js',
                        // 代码块命名规则
                        chunkFileNames: 'assets/js/[name].[hash].js',
                        // 静态资源命名规则
                        assetFileNames: 'assets/[ext]/[name].[hash].[ext]',

                        // 手动代码分割配置
                        manualChunks: {
                            // 将Vue相关库打包到vue-vendor chunk
                            'vue-vendor': ['vue', 'vue-router', 'pinia'],
                            // 将Element Plus打包到element-plus chunk
                            'element-plus': ['element-plus'],
                            // 将Axios打包到axios chunk
                            axios: ['axios'],
                            // 将@vueuse/core打包到@vueuse/core chunk
                            '@vueuse/core': ['@vueuse/core'],
                        },
                    },
                },
            },
        })
    )
);
相关推荐
hhcccchh16 小时前
学习vue第八天 Vue3 模板语法和内置指令 - 简单入门
前端·vue.js·学习
yyf1989052516 小时前
Vue 框架相关中文文献
前端·javascript·vue.js
粥里有勺糖16 小时前
开发一个美观的 VitePress 图片预览插件
前端·vue.js·vitepress
陟上青云16 小时前
一篇文章带你搞懂原型和原型链
前端
我的写法有点潮16 小时前
推荐几个国外比较流行的UI库(上)
前端·javascript·css
鹏多多16 小时前
jsx/tsx使用cssModule和typescript-plugin-css-modules
前端·vue.js·react.js
ssshooter17 小时前
复古话题:Vue2 的空格间距切换到 Vite 后消失了
前端·vue.js·面试
IamZJT_17 小时前
拒绝做 AI 的“饲养员” ❌:前端程序员在 AI 时代的生存与进化指南 🚀
前端·ai编程
MM_MS17 小时前
Halcon控制语句
java·大数据·前端·数据库·人工智能·算法·视觉检测