webpack 打包配置

主要实现功能

  • 处理html、css、js、vue、jsx、图片等文件
  • 压缩处理好的文件
  • 分割压缩好的文件
  • 路由懒加载
  • 开启缓存和热更新
  • 开启多线程打包
  • ...

新建【webpack.config.js】

  • 新建【webpack.dev.js】开发打包配置
  • 新建【webpack.prod.js】生产打包配置
  • 新建【webpack.config.js】,合并开发和生产配置,并根据打包命令的指定环境变量的值,判断使用何种配置

目录结构

js 复制代码
const xxx = require("xxx")

module.exports ={
  entry:"",
  output:{},
  module:{},
  plugins:[],
  optimization:{},
  resolve:{},
  devServer{},
  mode:,
  devtool:,
  performance:,
  ...
}

详细解析

js 复制代码
//引入相关依赖、npm下载的插件、库
const xxx = require("xxx")

//接收【package.json】中【script】所运行的脚本命令指定的环境变量
const isP = process.env.NODE_ENV === "production";

//提取下面相同配置,进行复用,减少代码体积【如css、less、scss】
//【.filter(Boolean)】过滤没有参数时,产生的undefined
const xxx = (xxx) =>{  return[xxx].filter(Boolean);  }

module.exports ={
  //打包入口文件
  entry:"./src/main.js",
  //指定输出的文件
  output:{
    //输出的目录
    path:'',
    //输出的文件名,携带路径
    filename:'',
    //输出的chunk文件名,携带路径
    chunkFilename:'',
    //输出的图片等资源文件名,携带路径
    assetModuleFilename:''
  },
  module:{
   //处理html、css、js、jsx、vue、图片等的规则 
    rules:[ {  }, { }, ...  ]
  },
  plugins:[],		//插件的使用
  optimization:{},	//压缩、代码分割
  resolve:{},		//webpack解析模块加载选项
  devServer{},		//开发模式自动化配置
  mode:,			//开发环境变量
  devtool:,			//生成代码映射模式,辅助开发
  performance:,		//性能分析
  ...
}
js 复制代码
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");
const { DefinePlugin } = require("webpack");
const CopyPlugin = require("copy-webpack-plugin");

// 需要通过 cross-env 定义环境变量
const isProduction = process.env.NODE_ENV === "production";

const getStyleLoaders = (preProcessor) => {
  return [
    isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader",
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: ["postcss-preset-env"],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
  entry: "./src/main.js",
  output: {
    path: isProduction ? path.resolve(__dirname, "../dist") : undefined,
    filename: isProduction
      ? "static/js/[name].[contenthash:10].js"
      : "static/js/[name].js",
    chunkFilename: isProduction
      ? "static/js/[name].[contenthash:10].chunk.js"
      : "static/js/[name].chunk.js",
    assetModuleFilename: "static/js/[hash:10][ext][query]",
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
      },
      {
        test: /\.(jsx|js)$/,
        include: path.resolve(__dirname, "../src"),
        loader: "babel-loader",
        options: {
          cacheDirectory: true,
          cacheCompression: false,
          plugins: [
            // "@babel/plugin-transform-runtime" // presets中包含了
          ],
        },
      },
      // vue-loader不支持oneOf
      {
        test: /\.vue$/,
        loader: "vue-loader", // 内部会给vue文件注入HMR功能代码
        options: {
          // 开启缓存
          cacheDirectory: path.resolve(
            __dirname,
            "node_modules/.cache/vue-loader"
          ),
        },
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      context: path.resolve(__dirname, "../src"),
      exclude: "node_modules",
      cache: true,
      cacheLocation: path.resolve(
        __dirname,
        "../node_modules/.cache/.eslintcache"
      ),
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, "../public"),
          to: path.resolve(__dirname, "../dist"),
          toType: "dir",
          noErrorOnMissing: true,
          globOptions: {
            ignore: ["**/index.html"],
          },
          info: {
            minimized: true,
          },
        },
      ],
    }),
    isProduction &&
      new MiniCssExtractPlugin({
        filename: "static/css/[name].[contenthash:10].css",
        chunkFilename: "static/css/[name].[contenthash:10].chunk.css",
      }),
    new VueLoaderPlugin(),
    new DefinePlugin({
      __VUE_OPTIONS_API__: "true",
      __VUE_PROD_DEVTOOLS__: "false",
    }),
  ].filter(Boolean),
  optimization: {
    minimize: isProduction,
    // 压缩的操作
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserWebpackPlugin(),
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminGenerate,
          options: {
            plugins: [
              ["gifsicle", { interlaced: true }],
              ["jpegtran", { progressive: true }],
              ["optipng", { optimizationLevel: 5 }],
              [
                "svgo",
                {
                  plugins: [
                    "preset-default",
                    "prefixIds",
                    {
                      name: "sortAttrs",
                      params: {
                        xmlnsOrder: "alphabetical",
                      },
                    },
                  ],
                },
              ],
            ],
          },
        },
      }),
    ],
    splitChunks: {
      chunks: "all",
    },
    runtimeChunk: {
      name: (entrypoint) => `runtime~${entrypoint.name}`,
    },
  },
  resolve: {
    extensions: [".vue", ".js", ".json"],
  },
  devServer: {
    open: true,
    host: "localhost",
    port: 3000,
    hot: true,
    compress: true,
    historyApiFallback: true, // 解决vue-router刷新404问题
  },
  mode: isProduction ? "production" : "development",
  devtool: isProduction ? "source-map" : "cheap-module-source-map",
};
  • 如项目较大,可开启多进程打包,开启多进程耗费时间,项目小不考虑

  • Preload / Prefetch懒加载技术,兼容性不好,需考虑浏览器和用户群体

  • PWA:项目离线还可以通过缓存使用,存在兼容性问题

安装依赖

  • 写入【package.json】即可npm i一键安装,但是会存在版本问题

  • 需要查看【webpack.config.js】具体使用的,单独安装【推荐】

    @babel/core
    @babel/eslint-parser
    @vue/cli-plugin-babel
    babel-loader
    copy-webpack-plugin
    cross-env
    css-loader
    css-minimizer-webpack-plugin
    eslint-plugin-vue
    eslint-webpack-plugin
    html-webpack-plugin
    image-minimizer-webpack-plugin
    imagemin
    imagemin-gifsicle
    imagemin-jpegtran
    imagemin-optipng
    imagemin-svgo
    less-loader
    mini-css-extract-plugin
    postcss-preset-env
    sass-loader
    stylus-loader
    vue-loader
    vue-style-loader
    vue-template-compiler
    webpack
    webpack-cli
    webpack-dev-server

修改【package.json】

​ 配置【scripts】脚本命令和【browserslist】浏览器适应规则

json 复制代码
{

  "scripts": {
  
    "start": "npm run dev",
    
    "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
    
    "build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
    
  },
  
  "browserslist": ["last 2 version", "> 1%", "not dead"]
  
}

新建【.eslinter.js】

使用Vue官方和Eslint官方推荐的配置即可,可根据团队需求调整

js 复制代码
module.exports = {
  root: true,
  env: {  node: true,  },
  extends: [
    "plugin:vue/vue3-essential","eslint:recommended"
  ],
  parserOptions: {  parser: "@babel/eslint-parser" },
};

新建【babel.config.js】

使用vue预设,即可

js 复制代码
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"],
};

总结

生产打包完,首次运行非首页,会出现404,原因是没有用上webpack-devServer的配置,后期项目上线部署,如通过nginx上线部署,可通过nginx配置解决

参考视频地址:https://www.bilibili.com/video/BV14T4y1z7sw

相关推荐
富贵2号18 小时前
从零开始理解 Webpack:构建现代前端工程的基石
webpack
Hashan3 天前
告别混乱开发!多页面前端工程化完整方案(Webpack 配置 + 热更新)
webpack
开心不就得了4 天前
构建工具webpack
前端·webpack·rust
鲸落落丶5 天前
webpack学习
前端·学习·webpack
闲蛋小超人笑嘻嘻5 天前
前端面试十四之webpack和vite有什么区别
前端·webpack·node.js
guslegend5 天前
Webpack5 第五节
webpack
海涛高软7 天前
qt使用opencv的imread读取图像为空
qt·opencv·webpack
行者..................7 天前
手动编译 OpenCV 4.1.0 源码,生成 ARM64 动态库 (.so),然后在 Petalinux 中打包使用。
前端·webpack·node.js
千叶寻-7 天前
package.json详解
前端·vue.js·react.js·webpack·前端框架·node.js·json
一直在学习的小白~7 天前
小程序开发:开启定制化custom-tab-bar但不生效问题,以及使用NutUI-React Taro的安装和使用
webpack·小程序·webapp