Webpack5常用配置

1、序言

Webpack属于构建工具,可以将开发者代码转化成浏览器能识别的代码,让开发者专注代码实现,不用过多关注浏览器兼容性问题。

Webpack常见功能:

  • 模块打包:Webpack 可以将项目中的所有模块(包括 JavaScript、CSS、图片等)打包成一个或多个 bundle。这有助于减少 HTTP 请求,提高页面加载速度。

  • 代码分割:Webpack 支持代码分割,可以将不同功能模块的代码分割成不同的 bundle,按需加载,从而提高应用的加载速度。

  • 模块热替换(HMR):Webpack 支持模块热替换,这意味着在开发过程中,当代码发生变化时,Webpack 可以自动重新打包并更新浏览器中的代码,而不需要刷新页面

  • Loader **翻译器:**Loader 允许你在打包过程中预处理文件,例如将less/scss转换成css、jsx/typescript转换成js、图片转换为 Base64 编码等等

  • 开发服务器:Webpack 提供了一个开发服务器,可以在开发过程中提供快速的实时重新加载功能

  • 树摇(Tree Shaking):Webpack 可以移除未引用的代码,这有助于减少最终打包文件的大小

  • ...

2、配置

2.1、初始化项目

bash 复制代码
#初始化仓库
npm init

#安装webpack、webpack-cli
npm i webpack
npm i webpack-cli

根目录下新建webpack.config.js:

javascript 复制代码
module.exports = {
    // 入口:entry:String | Object
    entry: '',
    // 出口
    output: {
    },
    // 各种loader配置
    module: {},
    // 各种插件配置
    plugins: [],
    // 优化配置
    optimization: {},
    // 开发服务器配置
    devServer: {},
    // development:开发模式,production:生产模式
    mode: 'development',
}

文件目录

math.js:加减乘除函数

main.js:

index.html

运行发现:浏览器不能识别esmodule,因此需要webpack打包构建成浏览器能识别的语言

2.2、配置出入口

javascript 复制代码
module.exports = {
  // 入口:entry:String | Object
  entry: path.resolve(__dirname, 'src/main.js'),
  // 出口
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
}
bash 复制代码
npx webpack --config webpack.config.js

打包成功:

所有的打包文件合在一起,变成定义的输出的文件名称main.js

修改public下的index.html的script标签地址为dist/main.js

待完善的点:

  • 每次重新打包,上次的打包结果会干扰本次打包结果

解决:

  1. webpack5:output: {clean: true}
  2. webpack4:安装clean-webpack-plugin插件
bash 复制代码
npm i clean-webpack-plugin
javascript 复制代码
const { CleanWebpackPlugin } = require("clean-webpack-plugin")

module.exports = {
    plugins: [
        new CleanWebpackPlugin()
    ]
}
  • 每次还要手动修改public/index.html的对应的script标签的引用地址
bash 复制代码
npm i html-webpack-plugin
javascript 复制代码
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  plugins: [
    // 以 public/index.html 为模板创建文件
    new HtmlWebpackPlugin({
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "public/index.html"),
    }),
  ],
};
  • 每次都要在cmd控制台输入一长串的npx webpack --config webpack.config.js

在package.json配置命令

  • 每次打包输出结果都是main.js,浏览器认为文件没发生改变,会走浏览器缓存,导致更新部署项目不生效
javascript 复制代码
output:{
    // 根据文件内容生成hash
    filename: '[contenthash].js'
}

2.3、开发服务器

解决:每次修改文件内容都要重新打包即手动执行npm run build操作,实现热更新:所见即所得;

原理:npm run build 打包至磁盘,webpack serve开发服务器会打包至内存

bash 复制代码
npm i webpack-dev-server -D

webpack.config.js

javascript 复制代码
module.exports = {
  // 开发服务器
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
}

package.json

javascript 复制代码
"scripts": {
    "dev": "npx webpack serve --config webpack.config.js --mode=development",
    "build": "npx webpack --config webpack.config.js --mode=production"
 }

tips:执行npm run dev会报错误,解决:升级node版本至18以上即可

2.4、区分环境

生产环境webpack5帮我们做了优化,如压缩js、html、开启tree-shaking,开发环境配置的devServer才生效;

写2套webpack.config.js问题

  • 重复配置多
  • 心智负担重

因此需要区分webpack环境

前面在package.json里面的script脚本已经设置了--mode=production 或者--mode=development了,然后发现process.env.NODE_ENV打印的结果始终是undefined,这里使用cross-env进行环境切换;

bash 复制代码
npm i cross-env -D

package.json

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

webpack.config.js中

javascript 复制代码
// 判断是否是生成环境
const isProduction = process.env.NODE_ENV === 'production'

module.exports = {
  // development:开发模式,production:生产模式
  mode: isProduction ? 'production' : 'development',
  // 入口:entry:String | Object
  entry: path.resolve(__dirname, 'src/main.js'),
  // 出口
  output: {
    filename: isProduction ? 'static/js/[contenthash:10].js' : 'static/js/[name].js',
    path: isProduction ? path.resolve(__dirname, 'dist') : undefined,
    clean: true
  },
  // 各种loader配置
  module: {},
  // 各种插件配置
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, 'public/index.html')
    })
  ],
  // 优化配置
  optimization: {},
  // 开发服务器配置
  devServer: {
    port: 8000,
    host: 'localhost',
    open: true
  },
}

2.5、处理样式文件

问题

  • js中引入css文件报错
  • 最后打包的静态资源不包含任何样式文件,即css代码不生效
bash 复制代码
npm i css-loader style-loader less less-loader -D

css-loader:负责将 Css 文件编译成 Webpack 能识别的模块

style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容

less-loader:将less转变成css

javascript 复制代码
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"]
      }
    ]
  },
}

2.5、处理图片资源

当图片小于一定大小时转变成base64,这样可以减少http请求

webpack5:

javascript 复制代码
module.exports = {
  // 各种loader配置
  module: {
    rules: [
      // 处理图片资源
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: 'asset',
        parser: {
          // 小于10kb
          dataUrlCondition: {
            maxSize: 10 * 1024
          }
        }
      }
    ]
  },
 
}

webpack4:

bash 复制代码
npm i  url-loader file-loader
javascript 复制代码
module.exports = {
  // 各种loader配置
   module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i, // 匹配png, jpg, jpeg, gif图片文件
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 10 * 1024, // 小于10KB的图片将被转换成Base64
              fallback: 'file-loader', // 大于10KB的图片使用file-loader处理
              outputPath: 'images/' // 输出路径
            }
          }
        ]
      }
    ]
  },
 
}

2.6、代码压缩

生产环境webpack5已经帮我们压缩js、html了,因此需要手动压缩css;

bash 复制代码
npm i css-minimizer-webpack-plugin
javascript 复制代码
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  // 优化配置
  optimization: {
    minimize: true,
    minimizer: [
      // css压缩
      new CssMinimizerPlugin(),
    ],
  },
}

2.7、兼容性处理

2.7.1、css

bash 复制代码
npm i postcss-loader postcss postcss-preset-env

webpack.config.js

javascript 复制代码
module.exports = {
  // 各种loader配置
    module: {
    rules: [
      // 处理css后缀文件
      {
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader",
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env"
                  ]
                ]
              }
            }
          }
        ]
      },
      // 处理less后缀文件
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", {
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: [
                [
                  "postcss-preset-env"
                ]
              ]
            }
          }
        }, "less-loader"]
      }
    ]
  },
}

package.json

javascript 复制代码
{
  // 其他省略
  "browserslist": ["last 2 version", "> 1%", "not dead"]
}

这样对低版本浏览器的css3语法就会加前缀,如-webkit

2.7.2、js

js兼容性处理主要使用babel,babel的主要作用如下

  • 将es6转化成es5
  • 将jsx语法转成js
bash 复制代码
npm i babel-loader @babel/core @babel/preset-env core-js -D

根目录下新建babel.config.js

javascript 复制代码
module.exports = {
   // 智能预设:能够编译ES6语法
   presets: [
    [
      "@babel/preset-env",
      // 按需加载core-js的polyfill
      { 
        // false: 不对当前的JS处理做 polyfill 的填充
        // usage: 依据用户源代码当中所使用到的新语法进行填充
        // entry: 依据我们当前筛选出来的浏览器.browserslistrc决定填充什么
        useBuiltIns: "usage", 
        corejs: { version: "3", proposals: true } 
      },
    ],
  ],
}

webpack.config.js

javascript 复制代码
module.exports = {
 // 各种loader配置
  module: {
    rules: [
      // 处理js后缀文件
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: [
          {
            loader: "babel-loader",
            options: {
              // Babel 在每个文件都插入了辅助代码,使代码体积过大,下面插件能减少代码体积
              plugins: ["@babel/plugin-transform-runtime"], 
            }
          }
        ]
      },
    ]
  },

}

2.8、提取css

问题:将网络调成3g,然后刷新页面,发现白屏

解决:将css提取到一个文件,通过 link 标签引入

bash 复制代码
npm i mini-css-extract-plugin -D

webpack.config.js

将style-loader替换成MiniCssExtractPlugin.loader

javascript 复制代码
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {

// 各种loader配置
  module: {
    rules: [
      // 处理css后缀文件
      {
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader",
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    "postcss-preset-env"
                  ]
                ]
              }
            }
          }
        ]
      },
      // 处理less后缀文件
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", {
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: [
                [
                  "postcss-preset-env"
                ]
              ]
            }
          }
        }, "less-loader"]
      },
    ]
  },
  // 各种插件配置
  plugins: [
    // 提取css成单独文件
    new MiniCssExtractPlugin(),
  ],
}

2.9、PWA

问题:一旦断网,应用无法打开

PWA:渐进式网络应用程序(progressive web application - PWA):是一种可以提供类似于 native app(原生应用程序) 体验的 Web App 的技术。其中最重要的是,在 离线(offline) 时应用程序能够继续运行功能。内部通过 Service Workers 技术实现的。

bash 复制代码
npm i workbox-webpack-plugin -D

webpack.config.js

javascript 复制代码
const WorkboxPlugin = require("workbox-webpack-plugin");
module.exports = {
   // 各种插件配置
  plugins: [
    // pwa
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何"旧的" ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
}

入口文件:main.js

javascript 复制代码
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);
      });
  });
}

2.10、Code Split

问题:打包代码时会将所有 js 文件打包到一个文件中,体积太大了。我们如果只要渲染首页,就应该只加载首页的 js 文件,其他文件不应该加载。

解决:我们需要将打包生成的文件进行代码分割,生成多个 js 文件,渲染哪个页面就只加载某个 js 文件,这样加载的资源就少,速度就更快。

2.10.1、多入口

javascript 复制代码
const path = require('path')

module.exports = {
    entry: {
        main: './src/main.js',
        app: './src/app.js'
    },
    output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "static/js/[name].js", // 入口文件打包输出资源命名方式
        clear: true,
    },
}

结果:dist/js目录下有main.js、app.js文件

2.10.2、多入口优化

问题:如果main.js、app.js都引入math.js,造成math.js被重复打包

解决:

javascript 复制代码
const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    entry: {
        main: './src/main.js',
        app: './src/app.js'
    },
    output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "static/js/[name].js", // 入口文件打包输出资源命名方式
        clear: true,
    },
    optimization: {
        splitChunks: {
            chunks: "all", // 对所有模块都进行分割
        }
    }
}

2.10.3、按需加载

按需加载:动态加载某个chunk

main.js:点击box元素,动态导入vue

javascript 复制代码
document.querySelector('.box').addEventListener('click', () => {
  import(/* webpackChunkName: "vue" */ 'vue').then((res)=>{
    console.log('res:', res)
  })
})

webpack.config.js

javascript 复制代码
const path = require('path')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    entry: {
        main: './src/main.js',
        app: './src/app.js'
    },
    output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "static/js/[name].js", // 入口文件打包输出资源命名方式
        chunkFilename: "static/js/[name].chunk.js", // 动态导入输出资源命名方式
        assetModuleFilename: "static/media/[name].[hash][ext]", // 图片、字体等资源命名方式(注意用hash)
        clear: true,
    },
    plugins: [
        // 提取css成单独文件
        new MiniCssExtractPlugin({
          // 定义输出文件名和目录
          filename: "static/css/[name].css",
          chunkFilename: "static/css/[name].chunk.css",
        }),
    ],
    optimization: {
        splitChunks: {
            chunks: "all", // 对所有模块都进行分割
        }
    }
}

实际应用:vue-router的按需加载

  • 路由匹配
javascript 复制代码
const routes = [
    {

        path: '/test',
        component: () => import(/* webpackChunkName: "test" */'@/views/test.vue')
    }
]
  • 加载相应的webpackChunkName

2.10.4、按需加载优化

问题:如果动态导入的chunk非常大或者网络极差,就会有明显卡顿的问题

解决:提前加载想要加载的资源

Preload:告诉浏览器立即加载资源;加载优先级高;兼容性好一些;只能加载当前页面需要使用的资源;

Prefetch:告诉浏览器在空闲时才开始加载资源;加载优先级低;兼容性差一些;可以加载当前页面资源,也可以加载下一个页面需要使用的资源;

bash 复制代码
npm i @vue/preload-webpack-plugin -D
javascript 复制代码
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");
module.exports = {
    plugins: [
       new PreloadWebpackPlugin({
         rel: "preload", // preload兼容性更好
         as: "script",
         // rel: 'prefetch' // prefetch兼容性更差
       }), 
    ]
}

打包结果:

2.11、 提升构建速度

2.11.1、include/exclude

node_modules下的依赖无须下载直接使用,babel不需要对他们进行处理

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                include: path.resolve(__dirname, "../src"),
                exclude: /node_modules/, // 排除node_modules代码不编译
                use: [
                  {
                    loader: "babel-loader",
                    options: {
                        plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                    }
                  }
                ]
            },
        ]
    }
}

2.11.2、oneof

打包时每个文件都会经过所有 loader 处理,尽管有test正则原因实际没有处理上,但是都要过一遍;比较慢。oneof只要匹配上一个 loader, 剩下的就不匹配了

javascript 复制代码
const path = require('path')

module.exports = {
  module: {
    rules: [
      {
        oneOf: [
          ...其它loader
          // 处理js
          {
            test: /\.js$/,
            // exclude: /node_modules/,
            include: path.resolve(__dirname, 'src'),
            use: [
              {
                loader: 'thread-loader',
                options: {
                  workers: threads
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true,
                  cacheCompression: false,
                  plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                }
              }
            ]
          }
        ]
      }
    ]
  },
  
}

2.11.3、cache

作用:缓存之前的Babel 编译结果,只打包变化部分的内容

javascript 复制代码
const path = require('path')

module.exports = {
  // 各种loader配置
  module: {
    rules: [
      // 处理js后缀文件
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: [
          {
            loader: "babel-loader",
            options: {
              plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
              cacheDirectory: true, // 开启babel编译缓存
              cacheCompression: false, // 缓存文件不要压缩
            }
          }
        ]
      },
    ]
  },
}

2.11.4、Thead

问题:项目越来越庞大时,打包速度越来越慢

解决:开启多进程打包

tips:小型项目使用Thread提升打包速度不显著,反而会延长打包时间,大型项目效果会更加显著

bash 复制代码
npm i thread-loader terser-webpack-plugin -D

webpack.config.js

javascript 复制代码
const path = require('path')
const os = require("os");
// cpu核数
const threads = os.cpus().length;

// js压缩工具,只在生产环境生效
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        oneOf: [
          // 处理js
          {
            test: /\.js$/,
            // exclude: /node_modules/,
            include: path.resolve(__dirname, 'src'),
            use: [
              {
                loader: 'thread-loader',
                options: {
                  workers: threads
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true,
                  cacheCompression: false,
                  plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                }
              }
            ]
          }
        ]
      }
    ]
  },
  // 压缩
  optimization: {
    minimize: true,
    minimizer: [
      // js压缩
      new TerserPlugin({
        parallel: threads,
      }),
    ],
    splitChunks: {
      chunks: 'all',
    },
  },
}

3、完整配置

webpack.config.js

javascript 复制代码
const path = require('path')
const os = require("os");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");
const WorkboxPlugin = require("workbox-webpack-plugin");

// 判断是否是生成环境
const isProduction = process.env.NODE_ENV === 'production'
// cpu核数
const threads = os.cpus().length;

module.exports = {
  entry: path.resolve(__dirname, 'src/main.js'),
  output: {
    filename: isProduction ? 'static/js/[contenthash:10].js' : 'static/js/[name].js',
    path: isProduction ? path.resolve(__dirname, 'dist') : undefined,
    chunkFilename: 'static/js/[name].[contenthash:8].chunk.js',
    assetModuleFilename: 'static/media/[name].[hash][ext]',
    clean: true
  },
  module: {
    rules: [
      {
        oneOf: [
          // 处理css后缀文件
          {
            test: /\.css$/,
            // 从右到左、从下到上使用loader
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      [
                        "postcss-preset-env"
                      ]
                    ]
                  }
                }
              }
            ]
          },
          // 处理less后缀文件
          {
            test: /\.less$/,
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      [
                        "postcss-preset-env"
                      ]
                    ]
                  }
                }
              },
              'less-loader'
            ]
          },
          // 处理图片
          {
            test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
            type: 'asset',
            parser: {
              dataUrlCondition: {
                maxSize: 20 * 1024
              }
            }
          },
          // 处理js
          {
            test: /\.js$/,
            // exclude: /node_modules/,
            include: path.resolve(__dirname, 'src'),
            use: [
              {
                loader: 'thread-loader',
                options: {
                  workers: threads
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  cacheDirectory: true,
                  cacheCompression: false,
                  plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                }
              }
            ]
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      // 自动帮我们引入打包生成的js资源
      template: path.resolve(__dirname, 'public/index.html'),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/[name].[contenthash:8].css",
      chunkFilename: "static/css/[name].[contenthash:8].chunk.css",
    }),
    new PreloadWebpackPlugin({
      rel: 'preload',
      as: 'script'
    }),
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何"旧的" ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
  // 压缩
  optimization: {
    minimize: true,
    minimizer: [
      // js压缩
      new TerserPlugin({
        parallel: threads,
      }),
      // css压缩
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      chunks: 'all',
    },
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`
    },
  },
  devServer: {
    port: 3000,
    host: 'localhost',
    open: true,
    hot: true,
    compress: true
  },
  mode: isProduction ? 'production' : 'development'
}

babel.config.js

javascript 复制代码
module.exports = {
  presets: [
    ["@babel/preset-env",
      // 按需加载core-js的polyfill
      {
        useBuiltIns: "usage",
        corejs: {
          version: 3
        },
      },]
  ],
}

package.json

javascript 复制代码
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack serve --config webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^3.5.12",
  },
  "devDependencies": {
    "core-js": "^3.38.1",
    "css-loader": "^7.1.2",
    "less": "^4.2.0",
    "less-loader": "^12.2.0",
    "style-loader": "^4.0.0",
    "terser-webpack-plugin": "^5.3.10",
    "webpack": "^5.95.0",
    "webpack-cli": "^5.1.4",
    "@babel/core": "^7.26.0",
    "@babel/plugin-transform-runtime": "^7.25.9",
    "@babel/preset-env": "^7.26.0",
    "@vue/preload-webpack-plugin": "^2.0.0",
    "babel-loader": "^9.2.1",
    "cross-env": "^7.0.3",
    "css-minimizer-webpack-plugin": "^7.0.0",
    "html-webpack-plugin": "^5.6.3",
    "mini-css-extract-plugin": "^2.9.1",
    "postcss": "^8.4.47",
    "postcss-loader": "^8.1.1",
    "postcss-preset-env": "^10.0.8",
    "thread-loader": "^4.0.4",
    "webpack-dev-server": "^5.1.0",
    "workbox-webpack-plugin": "^7.1.0"
  },
  "browserslist": [
    "last 2 version",
    "> 1%",
    "not dead"
  ]
}
相关推荐
ZJ_.2 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
GIS开发特训营7 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood33 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端34 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_8538 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_748248941 小时前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235612 小时前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js