webpack学习

162 阅读8分钟

webpack是一套基于NodeJS的模块打包工具

一、配置文件

1、什么是webpack配置文件?

我们在打包JS文件的时候需要输入: npx webpack index.js

这句指令的含义是: 利用webpack将index.js和它依赖的模块打包到一个文件中

其实在webpack指令中除了可以通过命令行的方式告诉webpack需要打包哪个文件以外,

还可以通过配置文件的方式告诉webpack需要打包哪个文件

2、webpack常见配置

entry: 需要打包的文件

output: 打包之后输出路径和文件名称

mode: 打包模式 development/production

development: 不会压缩打包后的JS代码

production: 会自动压缩打包后的JS代码

4、webpack配置注意事项

配置文件的名称必须叫做: webpack.config.js, 否则直接输入 npx webpack打包会出错

如果要使用其它名称, 那么在输入打包命令时候必须通过 --config 指定配置文件名称

npx webpack --config xxx

每次输入npx webpack --config xxx来打包文件会有一点蛋疼, 所以我们可以通过npm script来简化这个操作

5、什么是sourcemap?

webpack打包后的文件会自动添加很多代码, 在开发过程中非常不利于我们去调试

因为如果运行webpack打包后的代码,错误提示的内容也是打包后文件的内容

所以为了降低调试的难度, 提高错误代码的阅读性, 我们就需要知道打包后代码和打包之前代码的映射关系

只要有了这个映射关系我们就能很好的显示错误提示的内容, 存储这个映射关系的文件我们就称之为sourcemap

在webpack.config.js中添加

devtool: "xxx",

  1. sourcemap各配置项说明

    • eval:

      不会单独生成sourcemap文件, 会将映射关系存储到打包的文件中, 并且通过eval存储

      优势: 性能最好

      缺点: 业务逻辑比较复杂时候提示信息可能不全面不正确

    • source-map:

      会单独生成sourcemap文件, 通过单独文件来存储映射关系

      优势: 提示信息全面,可以直接定位到错误代码的行和列

      缺点: 打包速度慢

    • inline:

      不会单独生成sourcemap文件, 会将映射关系存储到打包的文件中, 并且通过base64字符串形式存储

    • cheap:

      生成的映射信息只能定位到错误行不能定位到错误列

    • module:

      不仅希望存储我们代码的映射关系, 还希望存储第三方模块映射关系, 以便于第三方模块出错时也能更好的排错

  2. 企业开发配置建议

    • development: cheap-module-eval-source-map

      只需要行错误信息, 并且包含第三方模块错误信息, 并且不会生成单独sourcemap文件

    • production: cheap-module-source-map

      只需要行错误信息, 并且包含第三方模块错误信息, 并且会生成单独sourcemap文件

二、loader

###1、loader基础概念

  1. 什么是loader?

    webapck的本质是一个模块打包工具, 所以webpack默认只能处理JS文件,不能处理其他文件,

    用于将其它类型文件转换为webpack能够识别处理模块的工具我们就称之为loader

  2. 如何使用loader

    • 通过npm安装对应的loader

    • 按照loader作者的要求在webpack进行相关配置

    • 使用配置好的loader

2、项目中常用的loader

  1. file-loader 地址

    1. 安装 npm install --save-dev file-loader

    2. 在webpack.config.js中配置file-loader

    module: {
            rules: [
                {
                    test: /\.(png|jpg|gif)$/,
                    use: [
                        {
                            loader: 'file-loader',
                            options: {
                                // 指定打包后文件名称
                                name: '[name].[ext]',
                                // 指定打包后文件存放目录
                                outputPath: 'images/',
                                // 指定托管服务器地址(统一替换图片地址)
                                publicPath: 'http://www.1111.com/images/'
                            }
                        }
                    ]
                }
            ]
        }
    
    1. 注意点:
    • 默认情况下fileloader生成的图片名就是文件内容的 MD5 哈希值

      如何想打包后不修改图片的名称, 那么可以新增配置 name: "[name].[ext]"

      其它命名规则详见: placeholders

    • 默认情况下fileloader会将生成的图片放到dist根目录下面

      如果想打包之后放到指定目录下面, 那么可以新增配置 outputPath: "images/"

    • 如果需要将图片托管到其它服务器, 那么只需在打包之前配置 publicPath: "托管服务器地址"即可

    1. 使用file-loader处理字体图标

    字体图标中也用到了url用到了文件, 所以我们需要通过file-loader来处理字体图标文件

    {
       test: /\.(eot|svg|ttf|woff|woff2)$/,
       use:[{
           loader: "file-loader",
           options: {
               name: "[name].[ext]",
               outputPath: "font/",
           }
       }]
    }
    
  2. url-loader 地址

    url-loader 功能类似于 file-loader,

    但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL

    1. 安装 npm install --save-dev url-loader

    2. 在webpack.config.js中配置file-loader

      module: {
            rules: [
                  {
                      test: /\.(png|jpg|gif)$/,
                      use: [
                          {
                              loader: 'url-loader',
                              options: {
                                  /*
                                  limit: 指定图片限制的大小
                                  如果被打包的图片超过了限制的大小, 就会将图片保存为一个文件
                                  如果被打包的图片没有超过限制的大小, 就会将图片转换成base64的字符串
                                  注意点:
                                  对于比较小的图片, 我们将图片转换成base64的字符串之后, 可以提升网页的性能(因为减少了请求的次数)
                                  对于比较大的图片, 哪怕我们将图片转换成了base64的字符串之后, 也不会提升网页的性能, 还有可能降低网页的性能
                                  (因为图片如果比较大, 那么转换之后的字符串也会比较多, 那么网页的体积就会表达, 那么访问的速度就会变慢)
                                  * */
                                  limit: 1024 * 100,
                                  // 指定打包后文件名称
                                  name: '[name].[ext]',
                                  // 指定打包后文件存放目录
                                  outputPath: 'images/',
                              }
                          }
                      ]
                  }
              ]
          }
      
    3. 注意点:

      • 默认情况下fileloader生成的图片名就是文件内容的 MD5 哈希值

        如何想打包后不修改图片的名称, 那么可以新增配置 name: "[name].[ext]"

        其它命名规则详见: placeholders

      • 默认情况下fileloader会将生成的图片放到dist根目录下面

        如果想打包之后放到指定目录下面, 那么可以新增配置 outputPath: "images/"

      • 如果需要将图片托管到其它服务器, 那么只需在打包之前配置 publicPath: "托管服务器地址"即可

    4. 优势:

      图片比较小的时候直接转换成base64字符串图片, 减少请求次数

      图片比较大的时候由于生成的base64字符串图片也比较大, 就保持原有的图片

  3. css-loader

    借助loader将CSS文件转换为webpack能够处理的类型

    安装css-loader需要同style-loader一起安装

    css-loader: 解析css文件中的@import依赖关系

    style-loader: 将webpack处理之后的内容插入到HTML的HEAD代码中

    1. 安装 npm install --save-dev css-loader

      npm install style-loader --save-dev

    2. 在webpack.config.js中配置css-loader

        // 打包CSS规则
                  {
                      test: /\.css$/,
                      /*
                      css-loader:   解析css文件中的@import依赖关系
                      style-loader: 将webpack处理之后的内容插入到HTML的HEAD代码中
                      * */
                      // use: [ 'style-loader', 'css-loader' ]
                      use:[
                          {
                              loader: "style-loader",
                          },
                          {
                              loader: "css-loader"
                          }
                      ]
                  }
      
    3. 注意点:

      loader是从右至左从下至上处理

    4. 高级知识:

      默认情况下通过import "./xxx.css"导入的样式是全局样式

      也就是只要被导入, 在其它文件中也可以使用

      如果想要导入的CSS文件只在导入的文件中有效, 那么就需要开启CSS模块化

      {
         loader: "css-loader",
         options: {
             modules: true // 开启CSS模块化
         }
      }
      

      然后在导入的地方通过 import xxx from "./xxx.css"导入

      然后在使用的地方通过 xxx.className方式使用即可

  4. scss-loader

    自动将scss转换为CSS

    1. 安装 npm install --save-dev node-sass

      npm install --save-dev sass-loader

    2. 在webpack.config.js中配置css-loader

        // 打包CSS规则
      {
        test: /\.scss$/,
        use: [{
            loader: "style-loader" // 将 JS 字符串生成为 style 节点
        }, {
            loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
        }, {
            loader: "sass-loader" // 将 Sass 编译成 CSS
        }]
      }
      
    3. 注意点:

      因为loader是从右至左从下至上,所以必须先由sass-loader处理往后才能交给其他loader处理

    三、plugin

    1、plugin基础概念

    1. 什么是plugin?

      plugin 用于扩展webpack的功能

      当然loader也是变相的扩展了webpack ,但是它只专注于转化文件这一个领域。

      而plugin的功能更加的丰富,而不仅局限于资源的加载。

    2. 如何使用plugin

      • 通过npm安装对应的plugin

      • 按照plugin作者的要求在webpack进行相关配置

      • 使用配置好的plugin

    2、企业中用到常用的plugin

    1. HtmlWebpackPlugin 地址

      HtmlWebpackPlugin会在打包结束之后自动创建一个index.html, 并将打包好的JS自动引入到这个文件中

      1. HtmlWebpackPlugin使用

        1. 安装HtmlWebpackPlugin

          npm install --save-dev html-webpack-plugin

        2. 配置HtmlWebpackPlugin

          const HtmlWebpackPlugin = require('html-webpack-plugin');
          plugins: [new HtmlWebpackPlugin()]
          
      2. HtmlWebpackPlugin高级使用 address

        默认情况下HtmlWebpackPlugin生成的html文件是一个空的文件,如果想指定生成文件中的内容可以通过配置模板的方式来实现

         plugins: [new HtmlWebpackPlugin({
                template: "index.html"
            })]
        

        默认情况下生成html文件并没有压缩,

        如果想让html文件压缩可以设置

        new HtmlWebpackPlugin({
            template: "index.html",
            minify: {
                collapseWhitespace: true
            }
        })]
        
    2. clean-webpack-plugin 地址

      webpack-clean-plugin会在打包之前将我们指定的文件夹清空

      应用场景每次打包前将dist目录清空, 然后再存放新打包的内容, 避免新老混淆问题

      • clean-webpack-plugin使用
      1. 安装clean-webpack-plugin

      npm install --save-dev clean-webpack-plugin

      1. 配置clean-webpack-plugin
      const { CleanWebpackPlugin } = require('clean-webpack-plugin');
      plugins: [new CleanWebpackPlugin()]
      
      
    3. copy-webpack-plugin address

      在打包项目的时候除了JS/CSS/图片/字体图标等需要打包以外, 可能还有一些相关的文档也需要打包

      文档内容是固定不变的, 我们只需要将对应的文件拷贝到打包目录中即可

      那么这个时候我们就可以使用copy-plugin来实现文件的拷贝

      • copy-webpack-plugin使用

        1. 安装copy-webpack-plugin

          npm install --save-dev copy-webpack-plugin

        2. 配置copy-webpack-plugin

          const CopyWebpackPlugin = require('copy-webpack-plugin');
          plugins: [new CopyWebpackPlugin([
                      {from:"doc", to:"./doc"}
                  ])];
          
    4. mini-css-extract-plugin压缩css address

      注意: 由于配置了webpack的optimization.minimizer项目会覆盖默认的JS压缩选项,

      所以JS代码也需要通过插件自己压缩

      1. 安装JS代码压缩插件

        npm install --save-dev terser-webpack-plugin

      2. 安装CSS代码压缩插件

        npm install --save-dev optimize-css-assets-webpack-plugin

      3. 导入插件

        const TerserJSPlugin = require('terser-webpack-plugin');
        const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
        
      4. 配置webpack优化项

        optimization: {
            minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
        }
        

    四、webpack的高阶配置

    1、watch

    webpack 可以监听打包文件变化,当它们修改后会重新编译打包

    watch相关配置watchOptions

    poll: 1000 // 每隔多少时间检查一次变动

    aggregateTimeout: // 防抖, 和函数防抖一样, 改变过程中不重新打包, 只有改变完成指定时间后才打包

    ignored: 排除一些巨大的文件夹, 不需要监控的文件夹, 例如 node_modules

    module.exports = {
       watch: true,
       watchOptions: {
           aggregateTimeout: 300, // 防抖, 和函数防抖一样, 改变过程中不重新打包, 只有改变完成指定时间后才打包
           poll: 1000, // 每隔多少时间检查一次变动
           ignored: /node_modules/ // 排除一些巨大的文件夹, 不需要监控的文件夹
       },
      }
    

    2、webpack-dev-server address

    webpack-dev-server和watch一样可以监听文件变化

    webpack-dev-server可以将我们打包好的程序运行在一个服务器环境下

    webpack-dev-server可以解决企业开发中"开发阶段"的跨域问题

    1. 安装webpack-dev-server

      npm install webpack-dev-server --save-dev

    2. 配置webpack-dev-server

      devServer: {
              contentBase: "./bundle", // 打包后的目录
              open: true,// 是否自动在浏览器中打开
              port: 9090 // 服务器端口号 
          }
      "start": "npx webpack-dev-server --config webpack.config.js
      
      
    3. 跨域问题

      同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能

      所谓同源是指: 协议,域名,端口都相同,就是同源, 否则就是跨域

      1. dev-server解决跨域问题
      devServer: {
              contentBase: "./dist",
              open: true,
              port: 9090,
              proxy: {
                  // 所有API开头的请求都会被代理到target
                  // 例如: 我们发送请求地址: http://127.0.0.1:9090/api
                  //       实际发送请求地址: http://127.0.0.1:3000/api
                  "/api": {
                      target: "http://127.0.0.1:3000", // 代理地址
                      changeOrigin: true,     // 域名跨域
                      secure: false,          // https跨域
                  }
              }
          }
      
      
      1. 常用配置附录

      target:要使用url模块解析的url字符串

      forward:要使用url模块解析的url字符串

      agent:要传递给http(s).request的对象(请参阅Node的https代理和http代理对象)

      ssl:要传递给https.createServer()的对象

      ws:true / false,是否代理websockets

      xfwd:true / false,添加x-forward标头

      secure:true / false,是否验证SSL Certs

      toProxy:true / false,传递绝对URL作为路径(对代理代理很有用)

      prependPath:true / false,默认值:true - 指定是否要将目标的路径添加到代理路径

      ignorePath:true / false,默认值:false - 指定是否要忽略传入请求的代理路径(注意:如果需要,您必须附加/手动)。

      localAddress:要为传出连接绑定的本地接口字符串

      changeOrigin:true / false,默认值:false - 将主机标头的原点更改为目标URL