webpack常用配置

万高畅
2023-12-01

webpack.config.js 

/* 未使用脚手架打包 
  //开发环境
  webpack '输入文件' -o '输出文件' --mode=development
  //生产环境
  webpack '输入文件' -o '输出文件' --mode=production      
*/

const { resolve } = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin  = require('optimize-css-assets-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

/* 
  ## 懒加载
  ## import动态导入能将导入的文件单独打包,跟多入口文件效果类似
  webpackChunkName: 'test'
  import('./test')
    .then(res => {
      // 成功引入后执行的步骤
    })
    .catch(err => {
      console.log('文件加载失败~')
    })
*/

  // ## 预加载
  // import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then()
  // ## 懒加载
  // import(/* webpackChunkName: 'test' */'./test').then()

module.exports = {
  // 单入口打包(打包成一个chunk)
  entry: './src/index.js',
  /*
  另外的写法:
    // 单文件入口(打包成一个chunk),add.js加到index.js上,仅用于HMR HTML文件热更新
    entry: ['./src.index.js', './src/add.js'],
    // 多入口打包(打包成多个chunk,也可以进行代码分割)
    entry: {
      index: './src.index.js',
      add: './src/add.js'
    },
    // 多入口加文件合并(打包成多个chunk)
    entry: {
      index: ['./src.index.js', './src/count.js'],
      add: './src/add.js'
    },
  */

  output: {
    // 文件名称(指定名称+目录)
    /* 
      ## hash 每次打包都会生成一个唯一的hash值
      ## chunkhash: 根据输出的不同的chunk生成不同的chunk值,
      ## contenthash: 根据 不同的文件生成不同的hash值(推荐)
    */
    filename: 'js/[name].[contenthash: 8].js',
    // 输出所有文件的公共目录
    path: resolve(__dirname, 'build'),
    // 所有资源的引入公共路径前缀,相当于跨域中的前缀
    publicPath: '/',
    // 非入口chunk的名称,不设置都会走filename的方式命名,例如import('../xxx.js')导入的文件
    chunkFilename: '[name]_chunk.js',
    // 打包后要引用其中的文件,通过library暴露一个对象,达到调用的目的,一般结合dll使用
    library: '[name]',
    // 暴露的对象名添加到哪个地方去,window/global/commomjs
    libraryTarget: 'window'
  },

  module: {
    rules: [
      /* 检查js文件格式 */
      {
        // 在package.json中配置eslintConfig
        test: /\.js$/,
        include: resolve(__dirname, 'src'),
        exclude: /node_modules/,
        // 多个loader
        loader: 'eslint-loader',
        // 优先执行
        enforce: 'pre',
        // 具体的配置选项
        options: {
          // 自动修复
          fix: true,
          // 指定错误报告的格式规范
          formatter: require('eslint-friendly-formatter')
        }
      },
      /* 处理HTML文件中引入的图片 */
      {
        test: /\.html$/,
        include: resolve(__dirname, 'src'),
        exclude: /node_modules/,
        loader: 'html-withimg-loader',

      },
      /* 打包图片和其他资源 */
      {
        exclude: /\.(css|html|js|json)$/,
        loader: 'file-loader',
        options: {
          name: '[hash: 10].[ext]',
          outputPath: 'static/media/'
        }
      },
      {
        // 以下配置对每个检查的文件只会生效一个
        oneOf: [
          /* 打包图片资源 */
          {
            test: /\.(jpg|png|gif|bmp|jpeg)$/,
            include: resolve(__dirname, 'src'),
            exclude: /node_modules/,
            loader: 'url-loader',
            options: {
              // 图片大小限制,小于8kb使用base64处理
              limit: 8 * 1024,
              // 关闭url-loader es6模块化,使用commonJs解析
              esModule: false,
              // 图片重命名
              name: '[hash: 10].[ext]',
              // 指定打包输出路径
              outputPath: 'static/imgs/'
            }
          },
          /* 打包css资源 */
          {
            test: /\.css$/,
            // 指定检查的文件路径
            include: resolve(__dirname, 'src'),
            // 排除不需要检查的文件路径
            exclude: /node_modules/,
            // 多个loader
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              // css兼容性处理,配合package.json中的browswerlist使用
              {
                loader: 'postcss-loader',
                options: {
                  execute: true,
                  postcssOptions: {
                    plugins: [
                      [
                        'postcss-preset-env'
                      ]
                    ]
                  }
                }
              }
            ]
          },
          {
            test: /\.less$/,
            // 指定检查的文件路径
            include: resolve(__dirname, 'src'),
            // 排除不需要检查的文件路径
            exclude: /node_modules/,
            // 多个loader
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              // css兼容性处理
              {
                loader: 'postcss-loader',
                options: {
                  execute: true,
                  postcssOptions: {
                    plugins: [
                      [
                        'postcss-preset-env'
                      ]
                    ]
                  }
                }
              },
              'less-loader'
            ]
          },
          {
            test: /\.scss$/,
            // 指定检查的文件路径
            include: resolve(__dirname, 'src'),
            // 排除不需要检查的文件路径
            exclude: /node_modules/,
            // 多个loader
            use: [
              MiniCssExtractPlugin.loader,
              'css-loader',
              // css兼容性处理
              {
                loader: 'postcss-loader',
                options: {
                  execute: true,
                  postcssOptions: {
                    plugins: [
                      [
                        'postcss-preset-env'
                      ]
                    ]
                  }
                }
              },
              'sass-loader'
            ]
          },
          /* js兼容性处理 */
          {
            test: /\.js$/,
            include: resolve(__dirname, 'src'),
            exclude: /node_modules/,
            use: [
              /* 
                开启多进程打包
                多进程需启动(约600ms),只有打包时间长的时候适用
                {
                  loader: 'thread-loader',
                  options: {
                    workers: 2  //开启进程2个
                  }
                }
               */
              'thread-loader',
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        // 按需加载
                        useBuiltIns: "usage", // or "entry"
                        // 指定core-js版本
                        corejs: {
                          version: 3
                        },
                        // 指定兼容到哪个版本的浏览器
                        targets: {
                          chrome: '90',
                          firefox: '60',
                          ie: '9'
                        }
                      }
                    ]
                  ],
                  // 开启babel缓存
                  cacheDirectory: true
                }
              }
            ]
          }
        ]
      }
    ]
  },

  plugins: [
    /* 创建并复制index.html文件 */
    new HtmlWebpackPlugin({
      // 引入项目的根HTML文件
      template: './src/index.html',
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true
      }
    }),
    /* 抽离css成单独文件 */
    new MiniCssExtractPlugin({
      filename: 'css/[contenthash: 10].css'
    }),
    /* 压缩css文件 */
    new OptimizeCssAssetsWebpackPlugin(),
    /* 告诉webpack,根据mainfest映射,哪些库不用再打包 */
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/mainfest.json')
    }),
    // 配合dll, 引入dll中已经压缩的库
    new AddAssetHtmlWebpackPlugin({
      filepath: resolve(__dirname, 'dll/jquery.js')
    })
  ],

  // 解析模块的规则
  resolve: {
    // 配置解析模块的路径别名,例如 src别名是@
    alias: {
      $css: resolve(__dirname, 'src/css'),
      $assets: resolve(__dirname, 'src/assets')
    },
    // 配置省略文件路径的后缀名,文件引入可以省略后缀名
    extensions: ['.js', '.json'],
    // 告诉 webpack 解析模块是去找哪个目录,不配置默认会逐层向上找
    modules: [resolve(__dirname, './node_modules'), 'node_modules']
  },

  devServer: {
    // 运行代码的目录
    contentBase: resolve(__dirname, 'build'),
    // 监视contentBase目录下的所有文件,一旦文件变化就会reload
    watchContentBase: true,
    // 监视配置
    watchOptions: {
      // 忽略文件
      ignored: /node_modules/
    },
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 8888,
    // 指定域名
    host: 'localhost',
    // 自动打开浏览器
    open: true,
    // 开启HMR功能
    hot: true,
    // 不显示启动服务日志信息
    clientLogLevel: 'none',
    // 除基本启动信息,其他内容不显示
    quiet: true,
    // 如果出错不要全屏提示
    overlay: false,
    // 服务器代理 --> 解决开发环境下跨域问题,与vue相似
    proxy: {
      // 一旦遇到/api,就转到target这个路径下,并且路径重写,去掉/api
      '/api': {
        target: 'http://localhost:8080',
        // 路径重写
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },

  // 将node_modules中的代码单独打包成一个chunk输出,单/多入口都适用
  optimization: {
    /* 代码分割 */
    splitChunks: {
      chunks: 'all',
      // 分割的chunk最小为30kb
      minSize: 30 * 1024,
      // 无最大限制
      maxSize: 0,
      // 要提取的chunks最少被引用1次
      minChunks: 1,
      // 按需加载时并行加载的文件的最大数量
      maxAsyncRequests: 5,
      // 入口js文件最大并行请求数量
      maxInitialRequests: 3,
      // 名称连接符
      automaticNameDelimiter: '~',
      // 可以使用命名规则
      name: true,
      // 分割chunk的组
      cacheGroups: {
        // node_modules文件会被打包到vendors组的chunk中 --> vendors~xxx.js
        // 满足上边的公共规则
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          // 优先级
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          // 如果当前要打包的模块,和之前已经提取的模块是同一个,就不在重新打包
          reuseExistingChunk: true
        }
      }
    },
    // 将当前模块记录其他模块的hash值单独打包成一个文件,
    // 解决被引用文件修改,hash值改变,引用文件跟着重新打包的问题(缓存失效)
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    },
    // 配置生产环境的压缩方案: js和css
    minimizer: [
      new TerserWebpackPlugin({
        // 开启缓存
        cache: true,
        // 开启多进程打包
        parallel: true,
        // 启动source-map
        sourceMap: true
      })
    ]
  },

  devtool: source-map,

  externals: {
    // 忽略库名 -- 忽略包名
    jquery: 'jQuery'  // 忽略打包jQuery
  },
  // 指定模式: 开发/生产(production)
  /* 
    ## tree shaking:去除无用代码
    ## 前提: 1. 必须使用ES6模块化    2.开启production环境
    ## package.json中配置"sideEffects": ["*.css","*.less"]   -->不将设置的文件类型tree shaking
  */
  mode: 'development'
}

 webpack.dll.js

const { resolve } = require("path");
const webpack = require('webpack')
/* 
  使用dll技术对某些第三方库进行单独打包
  webpack --config webpack.dll.js
*/
module.exports = {
  entry: {
    // 最终打包生成的[name]  -->jquery
    // ['jquery']  --> 要打包的库是jQuery
    jquery: ['jquery']
  },
  output: {
    filename: '[name].js',
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash: 8]'
  },
  plugins: [
    // 打包生成一个mainfest.json文件 ,提供与要打包文件的映射关系
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射库的暴露的内容名称
      path: resolve(__dirname, 'dll/mainfest.json') // 输出文件路径
    })
  ]
}

 类似资料: