webpack4学习笔记,记录了常用的配置,注释详细

/*
  开发环境配置
    运行项目指令:
      webpack 会将打包结果输出出去
      npx webpack-dev-server 只会在内存中编译打包,没有输出
    
  生产环境:
    运行项目指令:
      webpack 会将打包结果输出出去

*/

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

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

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

// 当修改了webpack配置,新配置要想生效,必须重新启动webpack服务
// loader与plugin都需要Npm install 才能正常使用
// resolve 用来拼接绝对路径
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 AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
const webpack = require('webpack');

// 设置nodejs环境变量,下面设置的是开发环境,否则是生产环境
// process.env.NODE_ENV = development;

const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [
        // postcss 的插件
        require('postcss-preset-env')()
      ]
    }
  }
]

module.exports ={
  // webpack配置
  // 入口文件
  entry: ['./src/index.js', './src/index.html'],
  // 输出
  output: {
    // 输出文件名
    filename: 'build.[contenthash:10].js',
    // 输出路径
    // __dirname nodejs的变量,代表当前文件的绝对路径
    path: resolve(__dirname,'build')
  },
  // loader 的配置
  module: {
    rules: [
       /*
        语法检查:eslint-loader eslint
         注意: 只检查自己写的源代码,第三方库是不用检查的
         设置检查规则
          package.json中eslintConfig中设置
          airbnb --> eslint-config-airbnb-base eslint-plugin-import eslint
      */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          // 自动修复eslint报的错误
          fix: true
        }
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种文件
        oneOf: [
          /*
            正常来讲,一个文件只能被一个loader处理
            当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序
              先执行eslint 再执行babel
          */
          // 详细loader配置
          {
            // 匹配哪些文件
            test: /\.css$/,  // 正则表达式,表示为以.css结尾的文件
            // 使用哪些loader进行处
            // 要使用多个loader处理用use
            use:[
              // use数组中loader执行顺序:从右到左,从下到上,依次执行
              // 创建style标签,将js中的样式资源插入进行,添加到head中生效、
              // 创建style标签,将样式放入
              // 'style-loader',
              // 这个loader取代style-loader 作用:提取js中css成单独文件
              MiniCssExtractPlugin.loader,
              // 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
              'css-loader',
              /*
                css兼容性处理:postcss --> postcss-loader postcss-preset-env

                帮postcss找到package.json中browserslist(写在devDependencies的后面)里面的配置,通过配置加载指定的css兼容性样式
                    "browserslist": {
                      // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
                      "development": [
                        "last 1 chrome version",
                        "last 1 firefox version",
                        "last 1 safari version"
                      ],
                      // 生产环境:默认是看生产环境
                      "production": [
                        ">0.2%",
                        "not dead",
                        "not op_mini all"
                      ]
                    }
              */
              // 使用loader的默认配置
              // 'postcss-loader',css样式的兼容性处理
              // 修改loader的配置
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    // postcss 的插件
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          // 处理less文件
          {
            test: /\.less$/,
            use:[...commonCssLoader,'less-loader']
          },
          // 处理图片资源
          // 问题:默认处理不了html中img图片
          {
            test: /\.(jpg|png|gif)$/,
            // 使用一个loader
            // 需要下载url-loader和file-loader 因为url-loader依托于file-loader
            loader: 'url-loader',
            options: {
              // 图片大小小于8kb,就会被base64处理
              // 优点:减少请求数量(减轻服务器压力)
              // 缺点:图片体积会更大(文件请求速度更慢)
              limit: 8 *1024,
              // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
              // 解析时会出现问题:[object Module]
              // 解决:关闭url-loader的es6模块化,使用commonjs解析
              esModule: false,
              // 给图片进行重命名
              // [hash:10]取图片的hash的前10位
              // [ext]取文件原来扩展名
              name: '[hash:10].[ext]',
              // 指定输出路径
              // outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            // 处理html文件的img图片(负责引入img,从而能被url-loader处理)
            loader: 'html-loader'
          },
          // 打包其他资源(除了html/js/css资源以外的资源)
          {
            // 排除html/js/css
            exclude: /\.(css|js|html|less|jpg|png|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]'
            }
          },
          /*
            js兼容性处理: babel-loader @babel/core  
              1. 基本js兼容性处理 --> @babel/preset-env
                问题: 只能转换基本语法,如promise高级语法不能转换
              2. 全部js兼容性处理 --> @babel/polyfill
                使用时需要将 `import '@babel/polyfill'`引入js文件
                问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大
              3. 需要做兼容性处理的就做 :按需加载  --> corejs
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: [
              /*
                开启多进程打包 
                进程启动大概为600ms,进程通信也有开销
                只有工作消耗时间比较长,才需要多进程打包
              */
              {
                loader: 'thread-loader',
                options: {
                  workers: 2 // 两个进程
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  // 预设: 指示babel做怎么样的兼容性处理
                  presets: [
                    '@babel/preset-env',
                    {
                      // 按需加载
                      useBuiltIns: 'usage',
                      // 指定core-js版本
                      corejs: {
                        version: 3
                      },
                      // 指定兼容性做到哪个版本浏览器
                      targhets: {
                        chrome: '60',
                        firefox: '60',
                        ie: '9',
                        safari: '10',
                        edge: '17'
                      }
                    }
                  ],
                  // 开启babel缓存
                  // 第二次构建时,会读取之前的缓存
                  cacheDirectory: true
                }
              }
            ] 
          },
        ]
      } 
    ]
  },
  // plugins 的配置
  plugins: [
    //html-webpack-plugin
    //功能:默认会创建一个空的html,自动引入打包输出的所有资源(js/css)
    new HtmlWebpackPlugin({
      // 复制 './src/index.html' 文件,并自动引入打包输出所有资源
      template: './src/index.html',
      // 压缩html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'css/build.[contenthash:10].css'
    }),
    // 压缩css
    new OptimizeCssAssetsWebpackPlugin(),
    /*
      下面两个plugin的使用需要提前运行生成maninfest.json的code
      
        使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
          当你运行webpack时,默认查找webpack.config.js配置文件
          需求:需要运行webpack.dll.js文件
            --> npx webpack --mode=production --config webpack.dll.js

            const webpack = require('webpack')
            const resolve = require('path')
            module.exports = {
              entry: {
                // 最终打包生成的[name]  --> jquery
                // ['jquery'] --> 要打包的库是jquery
                jquery: ['jquery']
              },
              output: {
                filename: '[name].js',
                path: resolve(__dirname, 'dll'),
                library: '[name]_[hash]', // 打包的库黎明向外暴露出去的内容叫什么名字
              },
              plugins: [
                // 打包生成一个 manifest.json --> 提供和jquery 映射
                new webpack.DllPlugin({
                  name: '[name]_[hash]', // 映射库的暴露的内容名称
                  path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
                })
              ],
              mode: 'production'
            }

       // 告诉webpack哪些库不参与打包,同时使用时的名称也得变
        new webpack.DllReferencePlugin({
          manifest: resolve(__dirname,'dll/mainfest.json')
        }),
        // 将某个文件打包输出出去,并在html中自动引入该资源
        new AddAssetHtmlWebpackPlugin({
          filepath: resolve(__dirname,'dll/jquery.js')
        })
    */
  ],
  // 模式
  // mode: 'development', // 开发环境
  mode: 'production',  // 生产环境(js代码会自动压缩)

  // 开发服务器 devServer:用来自动化(自动变异,自动打开浏览器,自动刷新浏览器....)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令为:npx webpack-dev-server
  devServer: {
    // 项目构建后的路径
    contentBase: resolve(__dirname,'build'),
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 3000,
    // 自动打开浏览器
    open:true,
    /*
      HMR: hot module replacement 热模块替换 / 模块热替换
        作用: 一个模块发生变化,只会重新打包这一个(而不是打包所有模块)
        极大的提高打包速度
        样式文件:可以使用HMR功能:因为style-loader内部实现了
        js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR
          注意:HMR功能对js的处理,只能处理非入口js文件的其他文件
          // 在js文件中写如下代码,表示一个判断如果有module.hot,则...
          if(module.hot){
            // 一旦module.hot 为true。说明开启了HMR功能 --> 让HMR功能代码生效
            module.hot.accept('./print.js',function(){
              // 方法会监听print.js文件的变化,一旦发生变化,其他模块不会重新打包构建
              // 会执行后面的回调函数
              ...
            })
          }
        html文件:默认不能使用HMR功能。同时会导致问题:html文件不能热更新了(不用做hmr功能)
          解决:修改entry入口,将html文件引入
    */
    // 开启HMR功能
    hot: true
  },
  /*
    source-map: 一种 提供源代码到构建后代码映射 技术(如果构建后代码出错了,通过映射可以追踪源代码错误)
      [incline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
      错误代码准确信息和源代码的错误位置
      incline-source-map: 内联
        1.只生成一个内联source-map
        错误代码准确信息和源代码的错误位置
      hidden-source-map外部
        错误代码错误原因,但是没有错误位置
        不能追踪到源代码错误,只能提示到构建后代码的错误位置
      eval-source-map 内联
        1. 每一个文件都生成对应的source-map,都在eval
      nosources-source-map: 外部
        错误代码准确信息但是没有任何源代码信息
      cheap-source-map 外部
        错误代码准确信息和源代码的错误位置
        只能精确的行
      cheap-module-source-map 外部
        错误代码准确信息和源代码的错误位置
        module会将loader的source map加入

      内联和外部的区别z
        1.外部生成了文件,内联没有
        2.内联构建速度更快

      开发环境:速度快,调试更友好
      速度快(eval>incline>cheap>...)
        eval-cheap-source-map
        eval-source-map
      调试更友好
        source-map
        cheap-module-source-map
        cheap-source-map

      --> eval-source-map 最推荐(react,Vue的脚手架使用的是这个)
      生产环境:源代码要不要隐藏?调试要不要更有友好
        内联会让代码体积变大,所以在生产环境下不用内联
        nosources-source-map 全部隐藏
        hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

        --> source-map / cheap-module-source-map
  */
  devtool: 'eval-source-map',
  /*
    1.可以将node_modules中代码单独打包一个chunk最终输出
    2.自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk
  */
  // optimization: {
  //   splitChunks: {
  //     chunks: 'all'
  //   }
  // }

  externals: {
    // 忽略库名  --npm包名
    // 拒绝jquery被打包进来
    jquery: 'jQuery'
  }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值