1. webpack的基本使用

  • webpack是一个打包模块化JavaScript的工具,它会从入口模块出发,识别出源码中的模块化导入语句,递归地找出入口文件的所有依赖,将入口文件和其所有依赖打包到一个单独的文件中。是工程化、自动化思想在前端开发中的体现。

一、Webpack4.x

  • 4.x版本,同时需要安装webpack和webpack-cli;
  • 不推荐使用全局安装;
  • webpack与webpack-cli的版本对应:Webpack@4.43.0 ——— webpack-cli@3.3.11
  • 卸载:npm uninstall webpack webpack-cli

二、查看本地webpack版本 :

  • webpack -v:查看的是本地全局安装的webpack版本
  • npx webpack -v:查看本地本项目中的webpack版本。
  • npx为npm自带的一个工具,默认指向当前项目的node_modules/.bin/webpack.js

三、启动

1、 默认配置

  1. 直接启动,什么都不配置:npx webpack;
  2. 启动时候,首先会在根目录下寻找webpack.config.js,如果找不到就走webpack的默认配置;
  3. 可以认为 1chunk = 1bundle,chunk是代码块(执行构建之后的一个产物),1个chunk可以是多个模块组成的,是管理控制最终渲染资源的组合;bundle是资源文件。nodejs中万物皆模块。
// 默认配置
  const path = require('path');

  module.exports = {
    entry: './src/index.js',

    output: {
      filename: 'main.js',
      path: path.resolve(__dirname, './dist'),
    }
  }  
  1. 会寻找根目录下的src/index.js,打包之后会将打包后的文件输出到根目录下的dist/main.js;
  2. webpack是基于nodejs的;

2、 手动配置

  1. 可以直接创建webpack的默认配置文件 webpack.config.js,然后对这个文件进行修改,进行个性化配置;
  2. 也可以创建其它配置文件,比如:webpackconfig.js,然后通过 --config webpackconfig.js 来指定webpack使用哪个配置文件来执行构建;
  3. webpack.config.js 配置基础结构:
module.exports = {
  // 上下文:项目打包时的相对路径,默认根目录
  // context: '', // 默认值为:process.cwd(),一般不用修改,如果修改,后面的 ./src/index.js 的相对位置也会改
  entry: './src/index.js', //打包入口文件
  output: './dist', //输出结构
  mode: 'production', //打包环境
  module: {
    rules: [
      // loader模块处理
      {
        test: /\.css$/,
        use: 'style-loader'
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin()]  //插件配置
}
2.1.entry
  1. webpack 打包入口文件,webpack执行构建的第一步将从entry开始,可以抽象成输入:
//单入口SPA,本质是个字符串
entry: {
  main: './src/index.js',
}
===相当于如下简写===
entry: './src/index.js',
===数组===
entry: ['./src/index.js', './src/other.js'],  // 会将两个文件合并打包到 ./dist/index.js中,相当于拼接了两个文件内容,并不是多入口
// 数组:webpack会自动生成另外一个入口模块,并将数组中的每个指定的模块加载进来,并将最后一个模块的module.exports作为入口模块的module.exports导出。

//多入口,entry 是个对象
entry: {
  index: './src/index.js',
  login: './src/login.js',
}
2.2.output
  1. 输出结果:打包转换后的文件输出到磁盘位置,在webpack经过一系列处理并得到最终想要的代码后输出的结果。
output: {
  filename: 'bundle.js',  //输出文件的名称
  path: path.resolve(__dirname, 'dist'),  // 输出文件到磁盘的目录,必须是绝对路径
}

//多入口的处理
output: {
  filename: '[name]-[hash:6].js',  // 利用占位符,文件名称不要重复
  path: path.resolve(__dirname, './dist'),  // 输出文件到磁盘的目录,必须是绝对路径(`dist`或者`./dist`都可以)。
}
  1. hash和chunkhash
    1.hash:整个项目的hash值,每次只要有一个文件内容改动,构建之后,所有文件就会有一个新hash值;
    2.chunkhash:根据不同入口entry进行依赖解析,构建对应的chunk,生成相应的hash,只要组成entry的模块没有内容改动,则对应的hash不变。每次构建只有内容发生变化的模块hash才改变,多页应用推荐使用。
2.3.mode
  1. mode 用来设置当前的构建环境,会自动触发webpack内置的函数,达到优化的效果。
    1.production:会将DefinePlugin中的 process.env.NODE_ENV的值设置为production,并启用一系列的插件;
    2.development:会将DefinePlugin中的process.env.NODE_ENV的值设置为development,并启用NamedChunksPlugin和NamedModulesPlugin;
    3.none:退出任何默认优化选项。
  2. 如果没有设置,webpack会设置默认值production。
  3. 设置 NODE_ENV 并不会自动设置 mode 的值。
  4. 开启 development 有利于热更新的处理,识别哪个模块变化;开启 production 有利于模块压缩、处理副作用等一些功能。
2.4.loader
  1. 模块解析、模块解析器,用于把模块原内容按照需求转换成新内容。
  2. webpack默认只支持处理js和json模块,其它格式的模块(css、图片等)就需要使用对应的loader进行处理了。
  3. 常见的loader:
    1、style-loader;
    2、css-loader;
    3、less-loader;
    4、sass-loader;
    5、ts-loader; //将ts转换成js
    6、babel-loader; //转换ES6及ES6+等js新特性语法;
    7、file-loader; //处理图片等资源文件
    8、eslint-loader...
2.5.module
  1. 模块,webpack中一切皆模块,一个模块对应着一个文件。webpack会从配置的entry开始递归找出所有依赖的模块,当webpack遇到不认识的模块时,需要在webpack中的module里进行配置loader,当检测到对应格式的模块就会使用相应的loader进行处理。
module: {
  rules: [
    {
      test: /\.xxx$/, //指定匹配规则
      // use使用一个loader时可以使用对象、字符串;多个loader时需要使用数组
      use: {
        loader: 'xxx-loader'  //指定使用的loader
      }
    }
  ]
}
  1. file-loader:处理静态资源模块
    1、原理:把打包入口中识别出的资源文件,移动到输出目录,并且返回一个地址名称;
    2、使用场景:当我们需要模块仅仅是从源代码挪到打包目录,如:txt、svg、csv、excel、图片资源等等;
    3、案例:

    module: {
      rules: [
        {
          test: /\.(png|jpe?g|gif)$/,
          // use使用一个loader时可以使用字符串或者对象,如果有多个loader时需要使用数组
          use: {
            loader: 'file-loader', 
            // options 为额外配置,比如资源名称
            options: {  
              name: '[name]_[hash].[ext]',  // [name]:老资源的名称;[ext]:老资源模块的后缀
              outputPath: 'images/',  // 打包后的存放位置
            }
          }
        }
      ]
    },
    
      // 字体处理
      // css
      @font-face {
        font-family: 'webfont';
        font-display: swap;
        src: url('webfont.woff2') format('woff2');
      }
    
      body {
        background: blue;
        font-family: 'webfont' !important;
      }
    
      // webpack.config.js
      module: {
        rules: [
          {
            test: /\.(eot|ttf|woff|woff2|svg)$/,
            use: 'file-loader'
          }
        ]
      }
    
  2. url-loader
    1、内部使用了file-loader,算是file-loader的加强版本,可以处理file-loader的所有事情,但是遇到图片等格式的模块时会把图片转换成base64格式字符串,并打包到js里。如果体积较大会不合适,这里可以手动进行配置:
    2、案例:

    module: {
      rules: [
        {
          test: /\.(png|jpe?g|gif)$/,
          use: {
            loader: 'url-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
              outputPath: 'images/',
              limit: 2048,  // 只有当大小小于2048时,才转换成base64
            }
          }
        }
      ]
    }    
    
  3. css-loader、style-loader
    1、css-loader:分析css模块之间的关系,并合并成一个css,并加入到js模块中去(css in js);
    2、style-loader:会把css-loader生成的内容,以style挂在到页面的header部分,即从js中提取css的loader,在html页面中创建style标签,把css的内容放在这个style标签中;
    3、案例:

    module: {
      rules: [
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'],
        }
      ]
    }
    
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            {
              loader: 'style-loader',
              options: {
                injectType: 'singletonStyleTag',  // 将所有的style标签合并成一个
              }
            }, 'css-loader'
          ]
        }
      ]
    }
    
  4. less-loader
    1、把less语法转化为css;
    2、注:loader有顺序,从右到左,从下到上;
    3、需要同时安装less-loader【连接less和webpack的桥梁】、less【less语法编译】
    3、案例:

    module: {
      rules: [
        {
          test: /\.less$/,
          use: [ 'style-loader', 'css-loader', 'less-loader']
        }
      ]
    }
    
  5. sass-loader
    1.把sass语法转换成css;
    2.需要安装 sass-loader、node-sass;
    3.css模块化是通过配置css-loader来配置的;
    3.案例:

    module: {
      rules: [
        {
          test: /\.scss$/,
          use: [ 
            'style-loader',
            {
              loader: 'css-loader',
              options: {
                // css modules
                modules: true,
              },
            }, 'sass-loader']
        }
      ]
    }
    
  6. 总结:
    1、loader 处理webpack不支持的格式文件、模块;
    2、一个loader只处理一件事情;
    3、loader有执行顺序。

2.6.plugins
  1. 作用于webpack打包整个过程;
  2. webpack的打包过程是有(生命周期概念的)钩子的;
  3. plugin 可以在webpack运行到某个阶段的时候,帮你做一些事情,类似于生命周期的概念;
  4. 扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想做的事情;
  5. 作用于整个构建过程。
  6. html-webpack-plugin
    1、 会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中。(发现一个如下报错,原因是html-webpack-plugin版本和webpack版本相差太大导致)
    image.png

    2、案例:
    // webpack.config.js
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: {
        main: './src/index.js',
      },
      output: {
        filename: '[name]-[chunkhash:4].js',
        path: path.resolve(__dirname, './dist'),
      },
    
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.png/,
            use: {
              loader: 'url-loader',
              options: {
                limit: 2048,
                outputPath: './images/',
                filename: '[name]-[hash:4].[ext]',
              }
            }
          }
        ]
      },
      
      plugins: [
        new HtmlWebpackPlugin({
          title: 'My Webpack',
          filename: 'app.html',
          template: './src/index.html',
        })
      ]
    }
    
    // index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
      <div id="root"></div>
    </body>
    </html>
    
  7. clean-webpack-plugin
    1.清除不必要的文件。
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    ...
    plugins: [
      new CleanWebpackPlugin()
    ]
    
2.7. npx webpack --profile
  1. 使用此命令打包,可以查看各个模块所花费的时间,然后可以根据需要进行优化;
  2. 学完本节,webpack的基本使用应该已经没有问题了,后续将讲解其它高级插件和loader以及相关优化等。

推荐阅读更多精彩内容