webpack学习笔记

webpack配置

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 webpack = require('webpack');
// process.env.NODE_ENV = 'development';
module.exports = {
  mode: 'development', //生产模式下会自动压缩js代码

  /**
   * entry: 入口起点
   * 1.string ---》 './src/index.js'
   *  单入口
   *  打包形成一个chunk,输出一个bundle文件
   *  此时chunk的名称默认是main
   * 2.array ---》 ['./src/index.js', './src/add.js']
   *  多个入口
   *  所有文件最终只会形成一个chunk,输出去只有一个bundle文件。
   * 3.ojbect
   *  多入口
   *  有几个入口文件就形成几个chunk,输出几个bundle文件
   *  此时的chunk的名称是key
   */
  entry: {
    index: './src/js/index.js',
  },
  /**
   * 文件名称
   * filename: 'js/[name].js'
   * 输出文件目录
   * path: resolve(__dirname, 'build')
   * 所有资源引入的公共路径前缀
   * publicPath: '/'
   * 非入口chunk的名称
   * chunkFilename: 'js/[name]_chunk.js'
   * 整个库向外暴露的变量名
   * library: '[name]'
   * 变量名添加到哪里
   * libraryTarget: 'window' //global
   */
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build'),
    publicPath: './',
  },
  module: {
    // js兼容性处理:babel-loader @babel/core
    /**
     1.基本js兼容处理 --》 @babel/preset-env
      问题:只能转换基本语法,如promise不能转换
     2.全部js兼容性处理 --》@babel/polyfill
      直接在js文件中引入,问题是我只需要解决部分兼容性问题,但是将所有兼容代码引入到文件中,文件体积过大
     3.按需加载 --》core-js
     */

    rules: [
      {
        //一下loader只会匹配一个
        //注意:不能又两个配置同时处理一个类型文件,这样只会有先匹配的生效,
        //解决办法是将另外一个loader移到oneOf外面
        oneOf: [
          {
            test: /.js/,
            exclude: /node_modules/,
            use: [
              /**
               * 开启多进程打包
               * 进程启动时间大概为600ms,进程通信也有开销
               * 只有工作消耗比较长,才需要多进程打包
               */
              // 'thread-loader',
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        // 按需加载
                        useBuiltIns: 'usage',
                        // 指定core-js版本
                        corejs: {
                          version: 3,
                        },
                        // 指定兼容到浏览器的哪一个版本
                        targets: {
                          browsers: ['last 2 versions'],
                        },
                      },
                    ],
                  ],
                  // 开启babel缓存,第二次构建时,会读取之前的缓存
                  cacheDirectory: true,
                },
              },
            ],
          },
          {
            test: /\.css$/,
            // use: ['style-loader', 'css-loader'],
            use: [
              {
                //作用:提取js中的css到单独的css文件
                loader: MiniCssExtractplugin.loader,
                options: {
                  publicPath: '../',
                },
              },
              'css-loader',
              //css兼容性处理 --->postcss-loader postcss-preset-env
              // 通过package.json中browserslist或者.browserslistrc文件配置加载指定的css兼容样式
              // "browserslist": {
              //默认为生产环境,若想为开发环境需通过precess.env.NODE_ENV = 'development'来配置
              //   "development": [
              //     "last 1 chrome version",
              //     "last 1 firefox version",
              //     "last 1 safari version"
              //   ],
              //   "production": [
              //     ">0.1%",
              //     "not dead"
              //   ]
              // }
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [require('postcss-preset-env')()],
                },
              },
            ],
          },
          {
            test: /\.less$/,
            //使用多个loader处理用use,否则可用loader
            // style-loader:创建style标签,将js中的样式资源插入后添加到head标签中生效
            // css-loader:将css文件变成commonjs模块加载到js中,里面内容是样式字符串
            // less-loader:将less文件编译成css文件交给css-loader处理
            // use: ['style-loader', 'css-loader', 'less-loader'],
            use: [
              {
                //作用:提取js中的css到单独的css文件
                loader: MiniCssExtractplugin.loader,
                options: {
                  publicPath: '../',
                },
              },
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [require('postcss-preset-env')()],
                },
              },
              'less-loader',
            ],
          },

          {
            // 处理图片资源
            // 问题:默认处理不了html中的img图片,需使用html-loader来处理
            test: /\.(jpeg|jpg|png)$/,
            // 使用url-loader需下载url-loader和file-loader,url-loader依赖于file-loader
            loader: 'url-loader',
            options: {
              // 图片大小小于8kb就会被base64处理
              // 优点:减少请求数量(减轻服务器压力)
              // 缺点:图片体积会更大(文件请求速度更慢)
              limit: 8 * 1024,
              // 解决:关闭url-loader的es6模块化,使用commonjs解析
              esModule: false,
              // 给图片重命名
              // [hash:10]取图片hash值的前10位
              // [ext]取文件原来的扩展名
              name: '[hash:10].[ext]',
              // 指定处理完成后的输出路径
              outputPath: 'image',
            },
          },
          {
            test: /\.html$/,
            // 处理html文件中的img图片,负责引入img,从而能被url-loader处理
            loader: 'html-loader',
          },
          {
            // 打包其他资源(除了html,js,css,less,jpeg等资源)
            exclude: /\.(html|js|css|less|jpeg|png|gif|jpg)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media',
            },
          },
        ],
      },
    ],
  },

  plugins: [
    // html-webpack-plugin
    // 功能:默认会创建一个空的html,自动引入打包输出的所有资源(js/css)
    new HtmlWebpackPlugin({
      // 复制'./src/index.html'文件,并自动引入打包输出的所有资源
      template: resolve(__dirname, '/src/index.html'),
      // outputPath: 'build',

      // 压缩html
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),
    // 将css打包到单独文件
    new MiniCssExtractplugin({
      filename: 'css/index.[contenthash:10].css',
    }),

    // 压缩css
    new OptimizeCssAssetsWebpackPlugin(),
  ],

  // 开发服务器devServer,用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令为npx webpack-dev-server
  // 现在运行不了是因为包的版本问题
  devServer: {
    // 项目构建后的路径
    contentBase: resolve(__dirname, 'build'),
    // 启动gzip压缩
    compress: true,
    open: true,
    port: 3001,
    /*
      HMR: hot module replacement 热模块替换
      作用:一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块,极大提升构建速度
      样式文件:可以使用HMR功能,因为style-loader内部实现了
      js文件:默认不能使用HMR功能 --》需要修改js代码,添加支持HMR功能的代码
        注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
        if (moudle.hot) {
          一旦module.hot为true,说明开启了HMR功能
          module.hot.accept('./utils.js', function() {
            方法会监听utils.js文件的变化,一旦发生变化,其他默认不会重新构建打包
            会执行后面的回调函数
          })
        }
      html文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新,及修改html文件后,页面不会修改
        解决:修改entry入口,将html文件引入
        entry: ['./src/js/index.js', './src/index.html']
    */
    hot: true,
    //不要提示启动服务器日志信息
    clientLogLevel: 'none',
    //吃了一些基本启动信息以外,其他内容都不要提示
    quiet: true,
    //如果出错了不要全屏提示
    overlay: false,
    //服务器代理
    proxy: {
      '/api': {
        target: 'http://abc.com',
        //发送请求时,请求路径重写  将/api/xxx ---> /xxx
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },
  // 一种提供源代码到构建后代码映射的技术(如果构建后代码出错,通过映射可以追踪源代码错误位置
  // [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
  /**
   * source-map:外部(生成一个新的文件)
   * 展示错误代码准确信息 和 源代码的错误位置
   * inline-source-map: 内联
   * 只生成一个内联source-map,展示错误代码准确信息 和 源代码的错误位置
   * hidden-source-map:外部
   * 错误代码原因,但是没有错误位置,不能追踪源代码错误,只能提示到构建后代码的错误位置
   * eval-source-map:内联
   * 每一个文件都生成对应的source-map,展示错误代码准确信息 和 源代码的错误位置
   * nosources-source-map:外部
   * 错误代码准确信息,但是没有任何源代码信息
   * cheap-source-map:外部
   * 展示错误代码准确信息 和 源代码的错误位置,只能精确到行
   * cheap-module-source-map:外部
   * 展示错误代码准确信息 和 源代码的错误位置,module会将loader的source-map加入
   *
   *
   * 内联和外部的区别:1.外部生成了文件 2.内联构建速度更快
   * 开发环境:速度快,调试更友好
   *  速度快(eval>inline>cheap>...)
   *    eval-cheap-source-map
   *    eval-source-map
   *  调试更友好
   *    source-map
   *    cheap-module-source-map
   *    cheap-source-map
   *  --->eval-source-map / eval-cheap-module-source-map
   *
   * 生产环境:源代码要不要隐藏?测试要不要更友好
   *  内联会让代码体积变大,所以生产环境不用内联
   *  nosources-source-map
   *  hidden-source-map
   *  --->source-map / cheap-module-source-map
   */
  devtool: 'source-map',
  /**
   * code split 代码分割
   * 以下配置可以将node_modules中代码单独打包一个chunk最终输出
   * 例如多个入口文件中都引入jquery,不加这个配置则最终输入的出口文件每一个文件中都会引入jquery造成冗余
   *
   * 在js文件中使用‘import()’引入文件,则引入的文件会被单独打包成一个文件
   * ‘import('./index.js').then(() => {})’
   */
  // import(/* webpackChunkName: 'test' */'./index.js')  /* */里面的内容会重命名打包后的文件
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },

  externals: {
    //拒绝node_modules中指定的包被打包到输出文件中,需要手动在html文件中引入对应的cdn链接
    jquery: 'jQuery',
  },

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

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

/**
 * tree shaking:去除无用代码
 *   前提:1.必须使用es6模块化 2.开启production环境
 *   作用:减少代码体积
 *
 * 在package.json中配置
 *   "sideEffects":false //所有代码都可以进行tree shaking
 *     问题:可能会把css文件干掉
 *   "sideEffects":["*.css"]排除这些文件不进行tree shaking
 */

/**
 * 懒加载和预加载
 * 懒加载:当文件需要使用是才加载,使用import().then(() => {})实现
 * 预加载prefetch:会在使用之前,提前加载js文件,正常加载可以认为是并行加载,预加载会等其他文件加载完毕后再加载
 */
//  预加载实现方式: import(/* webpackPrefetch: true */'./test.js').then(() => {})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值