webpack5配置解析

2023-11-20

webpack

  • 配置文件 webpack.config.js
  • entry output loader plugins mode
  • webpack 命令即可打包

entry

entry: 入口起点
  1. string --> './src/index.js'
    单入口
    打包形成一个chunk。 输出一个bundle文件。
    此时chunk的名称默认是 main
  2. array  --> ['./src/index.js', './src/add.js']
    多入口
    所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
      --> 只有在HMR功能中让html热更新生效~
  3. object
    多入口
    有几个入口文件就形成几个chunk,输出几个bundle文件
    此时chunk的名称是 key

    --> 特殊用法
      {
        // 所有入口文件最终只会形成一个chunk, 输出出去只有一个bundle文件。
        index: ['./src/index.js', './src/count.js'],
        // 形成一个chunk,输出一个bundle文件。
        add: './src/add.js'
      }

output

  output: {
    // 文件名称(指定名称+目录)
    filename: 'js/[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    // 所有资源引入公共路径前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
    publicPath: '/',
    chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称
    // library: '[name]', // 整个库向外暴露的变量名
    // libraryTarget: 'window' // 变量名添加到哪个上 browser
    // libraryTarget: 'global' // 变量名添加到哪个上 node
    // libraryTarget: 'commonjs'
  },

module

module.exports = {
  module: {
    rules: [
      // loader的配置
      {
        test: /\.css$/,
        // 多个loader用use
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.js$/,
        // 排除node_modules下的js文件
        exclude: /node_modules/,
        // 只检查 src 下的js文件
        include: resolve(__dirname, 'src'),
        // 优先执行
        enforce: 'pre',
        // 延后执行
        // enforce: 'post',
        // 单个loader用loader
        loader: 'eslint-loader',
        options: {}
      },
      {
        // 以下配置只会生效一个
        oneOf: []
      }
    ]
  }
};

resolve

module.exports = {
  // 解析模块的规则
  resolve: {
    // 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
    alias: {
      $css: resolve(__dirname, 'src/css')
    },
    // 配置省略文件路径的后缀名
    extensions: ['.js', '.json', '.jsx', '.css'],
    // 告诉 webpack 解析模块是去找哪个目录
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
  }

  // index.js
  import '$css/index';
};

webpack.config.js

  • 作用: 指示 webpack 干哪些活(当你运行 webpack 指令时,会加载里面的配置)
  • 所有构建工具都是基于 nodejs 平台运行的~模块化默认采用 commonjs。
  • loader: 1.下载 2.使用(配置 loader)
  • plugins:1.下载 2.引入 3.使用

打包样式资源

  • sass 配置
  npm i node-sass sass-loader -D
  import './index.scss'
  {
     test:/\.(sass|scss)$/,
     use:['style-loader','css-loader','sass-loader']
  }
  • less 配置
  npm i style-loader css-loader less less-loader -D
  import './index.less'
  {
    test:/\.less$/,
    use:['style-loader','css-loader','less-loader']
  }
  • loader 配置
// resolve用来拼接绝对路径的方法
const { resolve } = require('path')

module.exports = {
  // webpack配置
  // 入口起点
  entry: './src/index.js',
  output: {
    // 输出文件名
    filename: 'index.js',
    // 输出路径 __dirname nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build'),
  },
  // loader的配置
  module: {
    rules: [
      // 详细loader配置
      {
        // 匹配哪些文件
        test: /\.css$/,
        // 使用哪些loader进行处理
        use: [
          // use数组中loader执行顺序:从右到左,从下而上,依次执行
          // 创建style标签,将js中的样式资源插入进行,添加到head中生效
          'style-loader',
          // 将css文件变成common.js模块加载js中,里面的内容是样式字符串
          'css-loader',
        ],
      },
      {
        test: /\.(sass|scss)$/,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'sass-loader' }],
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
    ],
  },
  // plugins的配置
  plugins: [],
  // 模式
  mode: 'development',
  // mode:'production'
}

打包 html 资源

npm i html-webpack-plugin -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'index.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template:'./src/index.html'
    })
  ],
  mode: 'development',
}

打包图片资源

npm i url-loader file-loader -D
npm i html-withimg-loader -D
module.exports = {
  module: {
    rules: [
      {
        /*
          处理不了html中的img图片 需要用html-loader
        */
        test: /\.(jpg|png|gif)$/,
        // 使用一个loader  url-loader依赖file-loader
        loader: 'url-loader',
        options: {
          /*
            图片小于12kb,会被base64处理
            优点:减少请求数量(减轻服务器压力)
            缺点:图片体积会更大(文件请求速度更慢)
          */
          limit: 12 * 1024,
          /*
            问题:url-loader默认使用es6模块化解析,而html-withimg引入图片是common.js
            解析时会出现问题:[object Module]
            解决:关闭url-loader的es6模块化,使用common.js解析
          */
          esModule: false,
          name: 'images/[hash:8][name].[ext]',
        },
      },
      {
        test: /\.html$/,
        // loader: 'html-loader',
        // !!!!!注意:webpack5需要用html-withimg-loader打包才能显示
        loader: 'html-withimg-loader',
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template:'./src/index.html'
    })
  ],
  mode: 'development',
}

打包其他资源

npm i file-loader -D
module.exports = {
  module: {
    rules: [
      // 打包其他资源(除了html/js/css资源以外的资源)
      {
        // 排除html/js/css资源
        exclude:/\.(html|js|css|scss|sass)$/,
        loader: 'file-loader',
        options:{
          name:'[hash:8].[ext]'
        }
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template:'./src/index.html'
    })
  ],
  mode: 'development',
}

devServer

const { resolve } = require('path');
module.exports = {
  mode: 'development',
  // 设置开发服务器
  devServer: {
    // 只会在内存中编译打包,不会有任何输出文件,终止运行会删除内存
    // 开发时可直接访问到 ./build 下的静态资源,这些资源在开发中不必打包
    // 运行代码的目录
    contentBase: resolve(__dirname, 'build'),
    // 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
    watchContentBase: true,
    watchOptions: {
      // 忽略文件
      ignored: /node_modules/,
    },
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 5000,
    // 域名
    host: 'localhost',
    // 自动打开浏览器
    open: true,
    // 开启HMR功能
    hot: true,
    // 不要显示启动服务器日志信息
    clientLogLevel: 'none',
    // 除了一些基本启动信息以外,其他内容都不要显示
    quiet: true,
    // 如果出错了,不要全屏提示~
    overlay: false,
    // 服务器代理 --> 解决开发环境跨域问题
    proxy: {
      // 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)
      '/api': {
        target: 'http://localhost:3000',
        // 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },
};

提取 css 成单独文件

npm i mini-css-extract-plugin -D
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 创建style标签,将样式放入
          // 'style-loader',
          // 取代style-loader,提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          'css-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename:'css/index.css'
    })
  ],
  mode: 'development',
}

css 兼容性处理

  1. npm i postcss postcss-loader postcss-preset-env -D
  'css-loader',
  // 一般兼容靠loader,压缩靠plugins
  // 添加兼容样式
  {
    loader: 'postcss-loader',
    options: {
      postcssOptions: {
        plugins: ['postcss-preset-env'],
      },
    },
  },
  ],
  1. 在 package.json 中添加 browseslist
// 默认是生产环境,开发环境需要设置环境标量 process.env.NODE_ENV ='development'
"browserslist": {
  "development": [
  "last 1 chrome version",
  "last 1 firefox version",
  "last 1 safari version"
  ],
  "production": [
  ">0.2%",
  "not dead",
  "not op_mini all"
  ]
},
  1. 也可以新建.browserslistrc 文件配置兼容性
[production]

> 0.2%
> not dead
> not op_mini all

[development]
last 1 chorme version
last 1 firefox version
last 1 safari version

压缩 css

npm i css-minimizer-webpack-plugin -D
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
  plugins: [
    new CssMinimizerWebpackPlugin(),
  ],
  mode: 'development',
}

js 语法检查 eslint

  1. eslint 包
npm i eslint-loader eslint -D
  1. eslint 格式标准选了 airbnb
npm eslint eslint-config-airbnb-base eslint-plugin-import -D
  1. 配置
  • package.json
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css",
    "*.less",
    "*.scss"
  ]
  • 或创建 .eslintrc 文件
{
  "extends": "airbnb-base",
  "env": {
    "browser": true
  },
  "rules": {
    "no-console": 0 // 不禁用console
  }
}
  1. 调用
{
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'eslint-loader',
  options: {
    fix: true,
  },
},

js 兼容性处理

  1. 安装开发依赖处理兼容问题 es6->es5
 npm i babel-loader @babel/core @babel/preset-env -D
  1. 处理全部 js 兼容问题 es7 等更高级语法
npm i @babel/polyfill -S

// 入口文件引入即可
import '@babel/polyfill';

  1. 按需引入
npm i core-js -S
  1. 调用
  • rules 配置
  /**
    * js兼容性处理:babel-loader @babel/core @babel/preset-env
    * 1. 基本js兼容性处理 --> @babel/preset-env
    *    问题:只能转换基本语法,如promise不能转换
    * 2. 全部兼容性处理 --> @babel/polyfill
    *    问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
    * 3. 需要做兼容性处理的就做:按需加载 --> core-js
    *
    */
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    presets: [
      [
        '@babel/preset-env',
        {
          targets: {
            ie: 9,
            edge: 17,
            firefox: 60,
            chrome: 60,
            safari: 10,
          },
          useBuiltIns: 'usage',
          corejs: 3,
        },
      ],
    ],
  }
  • 或者设置配置文件 .babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        // 需要兼容到以下浏览器的什么版本(可不填)
        "targets": {
          "ie": 7,
          "edge": "17",
          "firefox": "60",
          "chrome": "60",
          "safari": "10"
        },
        "useBuiltIns": "usage", // 这里配置usage 会自动根据你使用的方法以及你配置的浏览器支持版本引入对于的方法。
        "corejs": 3 // 指定 corejs 版本
      }
    ]
  ]
}

压缩 html 和 js

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 压缩html代码 webpack5 不用配置了
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),
  ],
  // 生产环境下自动压缩代码
  mode: 'production',
};

HMR

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
process.env.NODE_ENV = 'development';
module.exports = {
  /**
   * HMR: hot module replacement 热模块替换 / 模块热替换
   *  作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
   *    极大提升构建速度
   *
   *    样式文件:可以使用HMR功能:因为style-loader内部实现了
   *    js文件:默认不能使用HMR功能
   *    html文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新了~ (就一个文件不用做HMR功能)
   *      解决:修改entry入口,将html文件引入
   */
  // 解决webpack5 HMR不更新的问题 target: 'web',
  target: process.env.NODE_ENV === 'development' ? 'web' : 'browserslist',
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/index.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        test: /\.(sass|scss)$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(jpg|jpeg|png|gif)$/,
        loader: 'url-loader',
        options: {
          esModule: false,
          outputPath: 'image',
          limit: 10 * 1024,
          name: '[hash:8][name].[ext]',
        },
      },
      {
        test: /\.html$/,
        loader: 'html-withimg-loader',
      },
      {
        exclude: /\.(html|js|css|less|sass|scss|jpg|jpeg|png|gif)$/,
        loader: 'file-loader',
        options: {
          outputPath: 'media',
          name: '[hash:10].[ext]',
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    open: true,
    port: 3000,
    hot: true,
  },
};

source-map

const { resolve } = require('path');
process.env.NODE_ENV = 'development';
module.exports = {
  mode: 'development',
  /* 开发阶段:推荐使用 source-map或者cheap-module-source-map,这分别是vue和react使用的值,可以获取调试信息,方便快速开发
    测试阶段:推荐使用 source-map或者cheap-module-source-map,测试阶段我们也希望在浏览器下看到正确的错误提示
    发布阶段:false、缺省值(不写) */
  devtool: 'cheap-module-source-map',
};

oneOf

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        enforce: 'pre',
        exclude: /node_modules/,
        use: [
          {
            loader: 'eslint-loader',
            options: {
              fixe: true,
            },
          },
        ],
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种类型文件
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader],
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader'],
          },
          {
            test: /\.(sass|scss)$/,
            use: [...commonCssLoader, 'sass-loader'],
          },
          /*
            正常来讲,一个文件只能被一个loader处理。
            当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
              先执行eslint 在执行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    targets: {
                      ie: 10,
                      edge: 17,
                      firefox: 60,
                      chrome: 60,
                      safari: 10,
                    },
                    useBuiltIns: 'usage',
                    corejs: 3,
                  },
                ],
              ],
            },
          },
          {
            test: /\.(jpg|jpeg|png|gif)$/,
            loader: 'url-loader',
            options: {
              esModule: false,
              outputPath: 'image',
              limit: 10 * 1024,
              name: '[hash:8].[ext]',
            },
          },
          {
            test: /\.html$/,
            loader: 'html-withimg-loader',
          },
          {
            exclude: /\.(html|js|css|less|sass|scss|jpg|jpeg|png|gif)$/,
            loader: 'file-loader',
            options: {
              outputPath: 'media',
              name: '[hash:10].[ext]',
            },
          },
        ],
      },
    ],
  },
  mode: 'production',
};

缓存


/*
  缓存:
    babel缓存
      cacheDirectory: true
      --> 让第二次打包构建速度更快
    文件资源缓存
      hash: 每次wepack构建时会生成一个唯一的hash值。
        问题: 因为js和css同时使用一个hash值。
          如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)
      chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
        问题: js和css的hash值还是一样的
          因为css是在js中被引入的,所以同属于一个chunk
      contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样
      --> 让代码上线运行缓存更好使用
*/

// 定义nodejs环境变量:决定使用browserslist的哪个环境
process.env.NODE_ENV = 'production';
module.exports = {
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种类型文件
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常来讲,一个文件只能被一个loader处理。
            当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
              先执行eslint 在执行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 开启babel缓存
              // 第二次构建时,会读取之前的缓存
              cacheDirectory: true
            }
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              outputPath: 'imgs',
              esModule: false
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              outputPath: 'media'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};

tree shaking 树摇

/*
  tree shaking:去除无用代码
    前提:1. 必须使用ES6模块化  2. 开启production环境
    作用: 减少代码体积

    在package.json中配置
      "sideEffects": false 所有代码都没有副作用(都可以进行tree shaking)
        问题:可能会把css / @babel/polyfill (副作用)文件干掉
      "sideEffects": ["*.css", "*.less"]
*/

// 定义nodejs环境变量:决定使用browserslist的哪个环境
process.env.NODE_ENV = 'production';

code split 代码分割

const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // 单入口
  entry: './src/js/index.js',
  // 多入口:有一个入口,最终输出就有一个bundle(束)
  // entry: {
  //   index: './src/js/index.js',
  //   test: './src/js/test.js',
  // },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWitespace: true,
        removeComment: true,
      },
    }),
  ],
  /*
    1. 可以将node_modules中代码单独打包一个chunk最终输出
    2. 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
  */
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  mode: 'production',
}
/*
  通过js代码,让某个文件被单独打包成一个chunk
  import动态导入语法:能将某个文件单独打包
  webpackChunkName: 'test' 重命名
*/
// import('./test').then((res) => {console.log(res)}).catch(() => {})
import(/* webpackChunkName: 'test' */ './test')
  .then(({ mul, count }) => {
    // 文件加载成功
    // eslint-disable-next-line
    console.log(mul(2, 3));
  })
  .catch(() => {
    // eslint-disable-next-line
    console.log('文件加载失败~');
  });

lazy loading 懒加载和预加载

// 懒加载~:当文件需要使用时才加载~
// 预加载 prefetch:会在使用之前,提前加载js文件
// 正常加载可以认为是并行加载(同一时间加载多个文件)
// 预加载 prefetch:等其他资源加载完毕,浏览器空闲了,再偷偷加载资源
document.getElementById('btn').onclick = function () {
  import(/* webpackChunkName: 'test', webpackPrefetch: true */ './test').then(({ mul }) => {
    console.log(mul(4, 5));
  });
};

PWA 离线访问

npm i workbox-webpack-plugin -D
/*
  PWA: 渐进式网络开发应用程序(离线可访问)
    workbox --> workbox-webpack-plugin
*/
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
process.env.NODE_ENV = 'production';
module.exports = {
  plugins: [
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 帮助serviceworker快速启动
        2. 删除旧的 serviceworker

        生成一个 serviceworker 配置文件~
      */
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
  mode: 'production',
  devtool: 'source-map',
};
/*
  1. eslint不认识 window、navigator全局变量
    解决:需要修改package.json中eslintConfig配置
      "env": {
        "browser": true // 支持浏览器端全局变量
      }
   2. sw代码必须运行在服务器上
      --> nodejs
      -->
        npm i serve -g
        serve -s build 启动服务器,将build目录下所有资源作为静态资源暴露出去
*/
// 注册serviceWorker
// 处理兼容性问题
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js')
      .then(() => {
        console.log('sw注册成功了~');
      })
      .catch(() => {
        console.log('sw注册失败了~');
      });
  });
}

多进程打包

npm i thread-loader -S
/*
  开启多进程打包。
  进程启动大概为600ms,进程通信也有开销。
  只有工作消耗时间比较长,才需要多进程打包
*/
{
  loader: 'thread-loader',
  options: {
    workers: 2 // 进程2个
  }
},
{
  loader: 'babel-loader',
  options: {
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'usage',
          corejs: { version: 3 },
          targets: {
            chrome: '60',
            firefox: '50'
          }
        }
      ]
    ],
    // 开启babel缓存
    // 第二次构建时,会读取之前的缓存
    cacheDirectory: true
  }
}

externals 引入外链拒绝打包模块

<body>
  <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"><script>
</body>

module.exports = {
  mode: 'production',
  externals: {
    // 拒绝jQuery被打包进来
    jquery: 'jQuery'
  }
};

dll 配置打包文件,告诉 webpack 哪些库不参与打包

  • webpack.dll.js
/**
 * 使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
 * 当你运行webpack时,默认查找 webpack.config.js 配置文件
 * 需求:需要运行 webpack.dll.js 文件
 * --> webpack --config webpack.dll.js
 */
const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  // 打包出来的dll文件将细化到每个入口名称
  // entry: {
  //   // 最终打包生成的[name] --> jquery
  //   // ['jquery'] --> 要打包的库是jquery
  //   jquery: ['jquery'],
  //   lodash: ['lodash'],
  // },
  // 打包后,dll下只有一个文件,所有第三方包都打包进vendors.js
  entry: {
    vendors: ['jquery', 'lodash'],
  },
  output: {
    filename: '[name].js', // 文件名[name]指入口中的vendors
    path: resolve(__dirname, 'dll'),
    library: '[name]_[hash:6]', // 打包的库里面向外暴露出去的内容的名字
  },
  plugins: [
    // 打包生成一个 mainfest.json --> 提供和vendors映射
    new webpack.DllPlugin({
      name: '[name]_[hash:6]', // 映射的暴露的内容名称,和output.library保持一致
      path: resolve(__dirname, 'dll/[name].manifest.json'), // 输出映射文件
    }),
  ],
  mode: 'production',
};

  • webpack.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
// const fs = require('fs');
/* //由于使用entry1写法,将在dll中生成很多不同的第三方包,在通过DllReferencePlugin,AddAssetHtmlPlugin这两个插件引入到项目的js/html文件中,需要额外设置
const files = fs.readdirSync(resolve(__dirname, './dll'));
//用于存储DllReferencePlugin插件的配置,只能引入对象
const dllReferenceFiles = [];
//用于存储AddAssetHtmlPlugin插件的配置,
const htmlAssetFiles = [];
files.forEach(file => {
  //匹配jquery.js引入
  if (/.*\.js$/.test(file)) {
    htmlAssetFiles.push({ filepath: resolve(__dirname, './dll', file) });
  }
  //匹配jquery.manifest.json
  if (/.*\.manifest.json$/.test(file)) {
    dllReferenceFiles.push({ manifest: resolve(__dirname, './dll', file) });
  }
});
console.log(htmlAssetFiles, dllReferenceFiles); */

module.exports = {
  entry: './src/js/index.js',
  output: {
    // filename: 'js/[name].js',//开发环境使用该输出文件名
    filename: 'js/[name].[contenthash:4].js', //生产环境打包使用该输出文件名,可以有效利用浏览器缓存
    path: resolve(__dirname, 'build'),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    // 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/vendors.manifest.json'),
    }),
    // 将某个文件打包输出去,并在html中自动移入该资源(报错就手动引)
    new AddAssetHtmlWebpackPlugin({
      filepath: resolve(__dirname, 'dll/vendors.js'),
    }),
    // ...dllReferenceFiles.map(obj => new webpack.DllReferencePlugin(obj)),
    // new AddAssetHtmlWebpackPlugin(htmlAssetFiles),
  ],
  mode: 'production',
  devtool: 'source-map',
};

小结

编辑不易,转载请注明出处。感谢赏阅,期待你的建议,点赞和关注。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

webpack5配置解析 的相关文章

  • iOS 获取系统键盘UIKeyboard方法

    公司项目需求 需要让弹窗显示在键盘所在的图层之上 而不是在弹窗出现的时候消失 如图1 系统弹窗出现的时候会使键盘暂时不显示 而这种效果显然不符合要求的 由于没想到更好的办法 只好从键盘自身的UIKeyboard做文章了 通过获取当前键盘的U
  • 【Java多线程批量数据导入的方法】

    前言 当遇到大量数据导入时 为了提高处理的速度 可以选择使用多线程来批量处理这些处理 常见的场景有 大文件导入数据库 这个文件不一定是标准的CSV可导入文件或者需要在内存中经过一定的处理 数据同步 从第三方接口拉取数据处理后写入自己的数据库
  • 按装完mysql怎么启动_mysql安装完怎么启动服务器?

    mysql安装完启动服务器的方法 1 打开 开始 菜单 依次点击 管理工具 服务 打开系统服务窗口 2 在 服务 窗口中找到 MySQL 右击选择 启动 命令就可以启动mysql服务器了 mysql 是世界流行的开源数据库系统 下面本篇文章
  • 关于TypeScript和React的使用

    TS和React的使用 接口与类型 type与interface 内置的语法糖 Partial和Required Readonly Omit Exclude 继承 接口与类型 type与interface 内置的语法糖 Partial和Re
  • ffmpeg错误码

    cpp view plain copy AVERROR BSF NOT FOUND 1179861752 AVERROR BUG 558323010 AVERROR DECODER NOT FOUND 1128613112 AVERROR
  • 数字化转型中的国产化替代之路

    引言 数字经济浪潮席卷全球 我国数字经济已进入快速发展阶段 加快推进企业数字化转型 已成为共识 同时有利于构建全产业链数字化生态 增强产业链上下游的自主可控能力 为数字经济社会发展 构建数智化生态注入新动能 在此过程中 国产软件企业作为数字
  • python利用tushare下载数据并计算当日收益率

    python利用tushare下载数据并计算当日收益率 计算股票收益率的程序主要有以下几部分构成 1 获取股票接口数据函数 pro daily stock 2 计算收益率函数 cal stock 里面有两种计算式 你可以根据自己字典写入建仓
  • 堆排序的topk问题+归并排序+六大排序总结

    回忆一下堆排序 思路 sift函数 调整 将父亲和孩子 左孩子和右孩子中最大的那个数 然后和父亲比较 如果孩子大就将孩子的位子变为下一个父亲 往下拉 并且将孩子的值赋给他的父亲 j lt high 条件认可 防止父亲在最后一层 魔法般的对应
  • Tensorflow的Win10、CPU版本安装

    1 Anaconda的安装 Miniconda的安装 Anaconda的安装链接 https www anaconda com products distribution 如图所示 点击箭头所指 可以安装anaconda的最新版本 Mini
  • elementui 禁止浏览器自动填充用户名密码

    浏览器这功能在登录的时候挺好用的 但是在注册和管理的时候就很难受了 所以 在普通的input上直接off就行了
  • 华为虚拟机服务器怎么使用教程,虚拟机装服务器教程

    虚拟机装服务器教程 内容精选 换一换 应用容器化改造有三种方式 您可单击这里查看 本教程以某游戏为例 将该游戏进行微服务的架构改造 再进行容器化 本教程不对改造细节做深度讲解 仅讲解大致的建议 如需要详细了解容器化改造的过程 请单击服务咨询
  • 攻防世界adworld-hit-the-core

    hit the core 题目来源 CTF 题目描述 暂无 题目附件 下载附件 kwkl kwkl strings home kwkl 桌面 8deb5f0c2cd84143807b6175f58d6f3f core CORE code c
  • 【视频流上传播放功能】前后端分离用springboot-vue简单实现视频流上传和播放功能【详细注释版本,包含前后端代码】

    前言 我是前端程序猿一枚 不是后端的 如有写的有不规范的地方别介意哈 自己摸索了两天算是把这个功能做出来了 网上看了很多帖子没注释说实话 我看的基本是懵逼的 毕竟没有系统学过 所以现在做出来了就总结一下 自己多写点注释解释一下逻辑 让前端的
  • SpringBoot+MyBatisPlus+Thymeleaf+AdminLTE增删改查实战

    说明 AdminLTE是网络上比较流行的一款Bootstrap模板 包含丰富的样式 组件和插件 非常适用于后端开发人员做后台管理系统 因为最近又做了个后台管理系统 这次就选的是AdminLTE做主题模板发现效果不错 这里我把最核心的Spri
  • 华为机考练习python

    HJ108 求最小公倍数 while True try a b map int input split for i in range 1 b 1 if a i b 0 print a i break except break HJ107 求
  • linux中256错误,YUM安装遭遇: [Errno 256] No more mirrors to try

    把YUM配置好后 使用yum命令进行安装时 出现了如下错误 Downloading Packages ftp 192 168 220 46 RHEL6 2 x64 Server libaio devel 0 3 107 10 el6 x86
  • Calling a v8 javascript function from c++ with an argument

    Calling a v8 javascript function from c with an argument up vote 18 down vote favorite 8 I am working with c and v8 and
  • 笔试面试常考数据结构-单链表常用操作编程实现

    单链表是笔试以及面试手写代码中常考的数据结构之一 下面实现了单链表的常见操作 创建单链表 删除节点 打印单链表 包括正向打印以及逆向打印 反转单链表 找出单链表的倒数第K个节点 合并两个有序单链表等操作 代码 C cpp view plai
  • 【数据治理模型】哪种模型最适合您的组织?

    内部数据治理 第 2 部分 数据治理模型 在本系列的第一部分中 我们定义了数据治理并研究了导致大规模清理项目的失误 在这篇文章中 我们将研究常见的数据治理模型 哪些模型最适合不同类型的组织 没有单一的数据治理模型适合所有组织 在当今的业务中

随机推荐

  • RedisTemplate连接不释放导致服务异常

    最近在给一个项目做压测 刚开始时很正常 过一会服务就无法正常访问了 停止了压测任务再调用接口也同样没有响应 经排查是redis连接池没有释放导致的 解决方法 方法一 全局关闭事务 找到redis配置 将 enableTransactionS
  • jxl分割excel文件

    最近在实施一个项目 其中一项工作是处理历史数据 客户提供过来的数据是excel表格 超过20万条记录 由于目标系统导入限制 每次只能导入大小不超过8M的文件 所以需要对这些数据进行分割处理 在手工处理一遍后 觉得可以通过写一个程序来自动实现
  • 服务器 声音文件 nginx,docker nginx搭建视频音频服务器

    1 docker pull nginx 2 创建 nginx conf user nobody worker processes 1 error log logs error log error log logs error log not
  • python统计三国高频词,画条形图,绘词云图

    文章目录 前言 思路 代码 效果 总结 前言 记录一次期末作业 要求 1 统计三国演义 下卷 前十的高频词 含出现次数 2 根据上题结果 绘制高频词出现次数的条形图 3 生成三国演义 下卷 词云图 思路 1 open打开读取整篇文档 2 使
  • Vetur can‘t find `package.json`

    Vetur can t find package json 重新装了一下vscode 重新装vetur插件的时候右下角老是弹出提示 并且vetur的格式化也用不了了 我的解决办法是重新安装了vetur的版本 扩展里面找到vetur插件 点击
  • powershell报错:“irm : 请求被中止: 未能创建 SSL/TLS 安全通道“

    问题描述 powershell 执行下载的时候 报错 irm 请求被中止 未能创建 SSL TLS 安全通道 此时系统 所有的网络下载 经过https安全加密方式的TLS请求都会报错 因为加密版本不匹配的问题 可以通过以下命令 查看当前加密
  • TypeScript Property ‘XXX‘ does not exist on type ‘never‘.

    开发过程中出现这个错误是因为Typescript在执行代码检查时在该对象没有定义相应属性 这个错误不致命 遇到该错误有以下几种解决办法 1 将对象设置成 any this targetArray this options find item
  • 面向对象之反射

    目录 反射 优点 实战案例 案例 使用内置函数改造 反射内建函数注意事项 实例方法绑定和非绑定的区别 动态增加属性方法的区别 反射 其实它的核心本质其实就是利用字符串的形式去对象 模块 中操作 查找 获取 删除 添加 成员 一种基于字符串的
  • 【Android -- 开源库】表格 SmartTable 的基本使用

    介绍 1 功能 快速配置自动生成表格 自动计算表格宽高 表格列标题组合 表格固定左序列 顶部序列 第一行 列标题 统计行 自动统计 排序 自定义统计规则 表格图文 序列号 列标题格式化 表格各组成背景 文字 网格 padding等配置 表格
  • C++中的RTTI

    文章目录 dynamic cast运算符 指针类型的dynamic cast 引用类型的dynamic cast typeid运算符 使用RTTI type info类 参考资料 RTTI Runtime Type Information
  • 计算机专业2021考研分数线,2021研究生国家分数线是多少

    2021年考研国家线公布 再看看外语国家线最高的是文学类a类地区53 b类地区50分 每年虽然英语线不高 但是很多学生还是折在英语上 可惜啊 2021考研国家线 国家线公布干什么 一 做出选择 考研本身就是一个选拔性的考试 有人考上 自然也
  • 《时代》评出100位AI领域最具影响力人物,黄仁勋、马斯克、萨姆·奥特曼在列...

    编辑 腾讯科技 郝博阳 郭晓静 翻译 金鹿 在过去的一个世纪里 时代 杂志的封面反映了塑造社会的力量 今年也是如此 生成式人工智能 Generative AI 无疑是今年最受关注的重塑社会的力量 我现在看到的创新水平比我一生中见过的要强几个
  • gRPC的C++编译及简单使用

    grpc的编译及简单使用 1 grpc相关参考文档 grpc 主页 https grpc io grpc 文档 https grpc io docs grpc 简介 https grpc io docs what is grpc intro
  • loadrunner入门教程(1)--概述

    文章目录 1 loadrunner介绍 2 特性 2 1 轻松创建虚拟用户 2 2 创建真实的负载 2 3 定位性能问题 3 工作原理 3 1 VuGen发生器 3 2 控制器 Controller 3 3 分析器 Analysis 4 工
  • 大数据开发:Hive DDL操作入门

    Hive针对于数据管理操作 提供了类SQL语言HQL 在Hadoop生态当中 Hive定位为数据仓库工具 对于数据的各种操作 也就是使用HQL来完成 而HQL查询 可以分为DDL和DML两个部分来掌握 今天的大数据开发学习分享 我们就先来讲
  • 【Java8】Guava——Preconditions

    Preconditions Precondition 是先决条件的意思 也叫前置条件 可以人为是使函数正常执行的参数需要满足的条件 Preconditions 这个静态工厂中 Guava 为我们提供了一系列的静态方法 用于帮助我们在函数执行
  • 50+ 可以帮助提高前端开发效率的 ChatGPT Prompts

    大厂技术 高级前端 Node进阶 点击上方 程序员成长指北 关注公众号 回复1 加入高级Node交流群 如果你已经厌倦了繁琐重复的编码日常 想要提升自己的效率 那你可是来对地方了 借助 ChatGPT 的强大能力 你可以简化你的工作流程 减
  • 数据结构与算法-列表(双向链表)设计及其排序算法

    0 概述 本文主要涵盖列表 双向链表 的设计及其排序算法的总结 列表是一种典型的动态存储结构 其中的数据 分散为一系列称作节点 node 的单位 节点之间通过指针相互索引和访问 为了引入新节点或删除原有节点 只需在局部调整少量相关节点之间的
  • VUE项目获取url中的参数

    获取url参数有两种情况 情况一 内部页面之间互相传值 这里先讲情况一 因为同一项目内互相传值比较简单 假如要从A页面跳转到B页面 并传值 就要在A页面这么写 this router push name B query Id this tI
  • webpack5配置解析

    webpack 配置文件 webpack config js entry output loader plugins mode webpack 命令即可打包 entry entry 入口起点 1 string gt src index js