美文网首页
webpack配置一览(个人笔记)

webpack配置一览(个人笔记)

作者: kevision | 来源:发表于2022-10-30 22:18 被阅读0次

官方文档:https://www.webpackjs.com/guides/

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  /* --------------------------------------- mode ----------------------------------------- */
  // 告知 webpack 使用相应模式的内置优化
  mode: "production", // "production" | "development" | "none"
  
  /* --------------------------------------- entry ----------------------------------------- */
  // 起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。如果传递一个数组,那么数组的每一项都会顺序执行。
  entry: "./app/entry", // string | object | array
  entry:  ["./app/entry1",  "./app/entry2"], // -->会把这两个入口文件打包到一个默认main.js里面
  entry:  { a:  "./app/entry-a", b:  ["./app/entry-b1",  "./app/entry-b2"]  }, // -->打包输出a.js和b.js 
  // 把第三方库(如lodash)提取出来打包,同时又不让依赖这个库的文件重复打包lodash
  entry: {
    main: {
      import: ["./app/entry1",  "./app/entry2"],
      filename: 'channel1/[name].js', // 会把main.js打包到channel1文件夹下
      dependOn: 'lodash' // 这里的lodash与下面的key保持一致(key可以随便命名)
    },
    main2: {
      import: "./app/entry3",
      filename: 'channel2/[name].js', // 会把main2.js打包到channel2文件夹下
      dependOn: 'lodash' // 这里的lodash与下面的key保持一致(key可以随便命名)
    },
    lodash: 'lodash'
  }, // -->打包会输出main.js和lodash.js

  // 这里应用程序开始执行
  // webpack 开始打包

  /* --------------------------------------- output ----------------------------------------- */
  // 指示 webpack 如何去输出、以及在哪里输出你的打包内容
  output: {
    // webpack 如何输出结果的相关选项

    // 所有输出文件的目标路径
    // 必须是绝对路径(使用 Node.js 的 path 模块)
    path: path.resolve(__dirname, "dist"), // string

    // 每个输出 bundle 的名称
    filename: "bundle.js", // string  用于单个入口起点
    filename:  "[name].js",  // 使用入口名称,用于多个入口点(entry point)
    filename: "[id].bundle.js", // 使用内部 chunk id
    filename: "[name].[hash].bundle.js", // 使用每次构建过程中,唯一的 hash 生成
    filename:  "[chunkhash].bundle.js",  // 使用基于每个 chunk 内容的 hash, 用于长效缓存
    filename:  "js/[name].js", // 将所有js文件放到一个js文件夹当中
    // 「入口分块(entry chunk)」的文件名模板(出口分块?)
    
    // 资源的公共路径,默认为"",一般以/结尾
    publicPath: "/assets/", // string
    publicPath:  "", 
    publicPath:  "https://cdn.example.com/",
    // 输出解析文件的目录,url 相对于 HTML 页面

    // 导出库(exported library)的名称
    library: "MyLibrary", // string,
    
    // 导出库(exported library)的类型
    libraryTarget: "umd", // 通用模块定义
    libraryTarget:  "umd2",  // 通用模块定义
    libraryTarget:  "commonjs2",  // exported with module.exports
    libraryTarget:  "commonjs-module",  // 使用 module.exports 导出 
    libraryTarget:  "commonjs",  // 作为 exports 的属性导出
    libraryTarget:  "amd",  // 使用 AMD 定义方法来定义
    libraryTarget:  "this",  // 在 this 上设置属性  
    libraryTarget:  "var",  // 变量定义于根作用域下
    libraryTarget:  "assign",  // 盲分配(blind assignment)  
    libraryTarget:  "window",  // 在 window 对象上设置属性
    libraryTarget:  "global",  // property set to global object
    libraryTarget:  "jsonp",  // jsonp wrapper

  },

  /* --------------------------------------- module ----------------------------------------- */
  // 这些选项决定了如何处理项目中的不同类型的模块
  module: {
    // 关于模块配置

    rules: [
      // 模块规则(配置 loader、解析器等选项)

      {
        test: /\.jsx?$/,
        include: [
          path.resolve(__dirname, "app")
        ],
        exclude: [
          path.resolve(__dirname, "app/demo-files")
        ],
        // 这里是匹配条件,每个选项都接收一个正则表达式或字符串
        // test 和 include 具有相同的作用,都是必须匹配选项
        // exclude 是必不匹配选项(优先于 test 和 include)
        // 最佳实践:
        // - 只在 test 和 文件名匹配 中使用正则表达式
        // - 在 include 和 exclude 中使用绝对路径数组
        // - 尽量避免 exclude,更倾向于使用 include

        issuer: { test, include, exclude },
        // issuer 条件(导入源)

        enforce: "pre",
        enforce: "post",
        // 标识应用这些规则,即使规则覆盖(高级选项)

        loader: "babel-loader",
        // 应该应用的 loader,它相对上下文解析
        // 为了更清晰,`-loader` 后缀在 webpack 2 中不再是可选的
        // 查看 webpack 1 升级指南。

        options: {
          presets: ["es2015"]
        },
        // loader 的可选项
      },

      {
        test: /\.html$/,
        test: "\.html$"

        use: [
          // 应用多个 loader 和选项
          "htmllint-loader",
          {
            loader: "html-loader",
            options: {
              /* ... */
            }
          }
        ]
      },

      { oneOf: [ /* rules */ ] }, // 只使用这些嵌套规则之一
      { rules: [ /* rules */ ] }, // 使用所有这些嵌套规则(合并可用条件)
      { resource: { and: [ /* 条件 */ ] } }, // 仅当所有条件都匹配时才匹配
      { resource: { or: [ /* 条件 */ ] } },
      { resource: [ /* 条件 */ ] }, // 任意条件匹配时匹配(默认为数组)
      { resource: { not: /* 条件 */ } } // 条件不匹配时匹配
    ],
  },

  /* --------------------------------------- resolve ----------------------------------------- */
  // 这些选项能设置模块如何被解析
  resolve: {
    // 解析模块请求的选项
    // (不适用于对 loader 解析)

    // 用于查找模块的目录
    modules: [
      "node_modules",
      path.resolve(__dirname, "app")
    ],

    // 使用的文件扩展名
    extensions: [".js", ".json", ".jsx", ".css"], // 当我们引入文件时没有写文件扩展名,遇到同名文件时会按数组先后顺序进行匹配文件

    // 模块别名列表
    alias: {
      "@": path.resolve(__dirname, "./src"), // 常用
      "module": "new-module",
      // 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file"

      "only-module$": "new-module",
      // 起别名 "only-module" -> "new-module",但不匹配 "only-module/path/file" -> "new-module/path/file"

      "module": path.resolve(__dirname, "app/third/module.js"),
      // 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误
      // 模块别名相对于当前上下文导入
    },
    /* 可供选择的别名语法 */
    alias:  [
      {
        name: "module",
        // 旧的请求

        alias: "new-module",
        // 新的请求

        onlyModule: true
        // 如果为 true,只有 "module" 是别名
        // 如果为 false,"module/inner/path" 也是别名
      }
    ],
    /* ---------高级解析选项-------- */ 
    symlinks:  true,  // 遵循符号链接(symlinks)到新位置
    descriptionFiles:  ["package.json"],  // 从 package 描述中读取的文件
    mainFields:  ["main"],  // 从描述文件中读取的属性  // 当请求文件夹时
    aliasFields:  ["browser"],  // 从描述文件中读取的属性  // 以对此 package 的请求起别名
    enforceExtension:  false,  // 如果为 true,请求必不包括扩展名  // 如果为 false,请求可以包括扩展名  
    moduleExtensions:  ["-module"],
    enforceModuleExtension:  false,  // 类似 extensions/enforceExtension,但是用模块名替换文件  
    unsafeCache:  true, 
    unsafeCache:  {},  // 为解析的请求启用缓存  // 这是不安全,因为文件夹结构可能会改动  // 但是性能改善是很大的
    cachePredicate:  (path, request)  =>  true,  // predicate function which selects requests for caching  
    plugins:  [  // ...  ]  // 应用于解析器的附加插件

  },

  /* --------------------------------------- optimization ----------------------------------------- */
  // 优化
  optimization: {
    chunkIds: false,
    usedExports: true, // 进行tree-shaking摇树,基于ESM,将没有使用的代码过滤掉
    splitChunks: {
      chunks: 'async', // 有效值为 all,async 和 initial。initial同步,async异步,all同步或者异步
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1, 
      maxAsyncRequests: 30, // 按需加载时的最大并行请求数
      maxInitialRequests: 30, // 入口点的最大并行请求数
      cacheGroups: { // 缓存组。满足这些条件就会打包输出一个chunk
        element: {
          name: 'element',
          test: /[\\/]node_modules[\\/](element-ui)[\\/]/, // 将element再从node_modules拆分出来
          priority: 20, // 权重
          reuseExistingChunk: true,
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2, // 所有引用超过两次的模块分配到 default的bundle中
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },

  /* --------------------------------------- performance ----------------------------------------- */
  // 性能
  performance: {
    hints: "warning", // 枚举
    hints:  "error",  // 性能提示中抛出错误
    hints:  false,  // 关闭性能提示

    maxAssetSize: 200000, // 整数类型(以字节为单位)
    maxEntrypointSize: 400000, // 整数类型(以字节为单位)
    assetFilter: function(assetFilename) {
      // 提供资源文件名的断言函数
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
    }
  },

  /* ----------------------------------------- devtool ------------------------------------------- */

  // 此配置可以生成source map文件,和在浏览器中定位源代码位置。开发环境建议使用cheap-module-source-map,生产环境建议关闭此配置 
  devtool: "source-map", // enum  // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
  devtool:  "inline-source-map",  // 嵌入到源文件中
  devtool:  "eval-source-map",  // 将 SourceMap 嵌入到每个模块中 
  devtool:  "hidden-source-map",  // SourceMap 不在源文件中引用
  devtool:  "cheap-source-map",  // 没有模块映射(module mappings)的 SourceMap 低级变体(cheap-variant)  
  devtool:  "cheap-module-source-map",  // 有模块映射(module mappings)的 SourceMap 低级变体
  devtool:  "eval",  // 没有模块映射,而是命名模块。以牺牲细节达到最快。
  // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
  // 牺牲了构建速度的 `source-map' 是最详细的。

  /* ----------------------------------------- context ------------------------------------------- */
  context: __dirname, // string(绝对路径!)
  // webpack 的主目录
  // entry 和 module.rules.loader 选项
  // 相对于此目录解析

  /* ----------------------------------------- target ------------------------------------------- */
  target: "web", // 枚举
  target:  "webworker",  // WebWorker
  target:  "node",  // node.js 通过 require
  target:  "async-node",  // Node.js 通过 fs and vm
  target:  "node-webkit",  // nw.js 
  target:  "electron-main",  // electron,主进程(main process)
  target:  "electron-renderer",  // electron,渲染进程(renderer process) 
  target:  (compiler)  =>  {  /* ... */  },  // 自定义
  // 包(bundle)应该运行的环境
  // 更改 块加载行为(chunk loading behavior) 和 可用模块(available module)

  /* ---------------------------------------- externals ------------------------------------------ */
  // 外部扩展
  // 不要遵循/打包这些模块,而是在运行时从环境中请求他们。
  // 为了减小bundle体积,从而把一些不变的第三方库用cdn的形式引进来(index.html中script标签引入)
  // 能实现类似已经install到项目中的方式来引用这些库
  externals: { // 常用方式
    jquery: 'jQuery' // key的值必须与我们引入库的名称一致(与import $ from 'jquery'中的jquery一致)
                     // value的值来源于引入cdn链接后暴露在window对象中的变量名称:jQuery(或$)
  },

  // 不需要在index.html中手动引入cdn链接的方式
  externalsType: 'script',
  externals: {
    jquery: [
      'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js', // 第一个参数是cdn链接
      'jQuery' // 第二个参数是引入cdn链接后暴露在window对象中的变量名称:jQuery(或$)
    ]
},

  /* ----------------------------------------- stats ------------------------------------------- */
  // 配置构建命令行时的显示日志
  stats: "errors-only",
  stats:  {  //object
    assets: true,
    colors: true,
    errors: true,
    errorDetails: true,
    hash: true,
    // ...
  },
  // 精确控制要显示的 bundle 信息

  /* ----------------------------------------- devServer ------------------------------------------- */
 // webpack-dev-server 能够用于快速开发应用程序
  devServer: {
    proxy: { // 开启代理
       '/api': {
            target: 'localhost:3000',
            ws: false,
            changeOrigin: true,
            pathRewrite: {
                '^/api': '' //重写接口访问
            }
        }
    },
    port: 3000,  // 端口号
    host: '0.0.0.0', // 开发服务器主机,通过此配置,同一局域网下其他人也可以访问你本地开启的服务,或者手机调试pc端(通过ip+端口访问)
    contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
    compress: true, // 一切服务都启用gzip压缩
    headers: { // 添加响应头
        'x-access-token': 'abc123'
    },
    historyApiFallback: true, // 在使用history路由时,任意的 404 响应都可以被替代为 index.html
    hot: true, // 模块热替换,页面修改时,实现局部更新
    https: false, // true for self-signed, object for cert authority
    // ...
  },

 /* ----------------------------------------- plugins ------------------------------------------- */
  // 附加插件列表
 // plugins 选项用于以各种方式自定义 webpack 构建过程
 // 下面是多页面配置,传入了两个HtmlWebpackPlugin实例,并且配置不同,会打包输出index.html和index2.html。
 // 如果只配置一个HtmlWebpackPlugin实例则会打包成一个html(默认叫index.html)
  plugins: [
    new HtmlWebpackPlugin({  // 传入插件的new实例,还可以进行更多配置
      template: './index.html',
      inject: 'body',
      filename: '/channel1/index.html', // 打包成index.html并放到channel1文件夹里面(这就与上面对应的入口文件打包到一起了)
      chunks: ['main', 'lodash'],  // chunks决定打包后的index.html引入哪些chunk(entry对象的每一项打包后就是一个对应的chunk)
    }),
    new HtmlWebpackPlugin({  // 传入插件的new实例,还可以进行更多配置
      template: './index2.html',
      inject: 'body',
      filename: '/channel2/index2.html', // 打包成index2.html并放到channel2文件夹里面
      chunks: ['main2', 'lodash'], // index2.html会引入main2.js和lodash.js
    }),
  ],
}

更详细配置请参阅官方文档。

相关文章

网友评论

      本文标题:webpack配置一览(个人笔记)

      本文链接:https://www.haomeiwen.com/subject/jslbartx.html