解锁webpack:对html、css、js及图片资源的抽离打包处理

面试被问到webpack,可别只知道说 HtmlWebpackPlugin 了哇。

前期准备

安装依赖

npm init -y
npm install webpack webpack-cli --save-dev

配置打包命令

// package.json
{
    "scripts": {
        // ... 其他配置信息
        "build": "webpack --mode production"
     }
}

基本配置

entry

通过entry指定项目打包时的入口文件,可以配置单入口或者多入口

  • 单入口文件
module.exports = {
  entry: './path/to/my/entry/file.js',
};
  • 多入口文件
module.exports = {
  entry: {
    index: './src/index.js',
    info: './src/information.js',
  },
};

output

通过output配置项目打包后的文件名以及文件的输出路径(位置)

  • filename:此选项决定了每个输出 bundle 的名称
    • 什么是bundle?

      根据入口文件,最后打包生成的、可以直接让浏览器解析的JS、CSS文件。

    • JS属于入口文件,那CSS为什么也可看作bundle?

      • 不对CSS做抽离,那CSS会被内联在JS中(必然算);
      • 对CSS做抽离,但CSS也是通过JS去做处理的(算做样式bundle);
    • html算不算?

      HTML文件从严格意义上讲不算做bundle,因为不包含直接打包的代码或资源;

      只是对打包好的资源做加载或展示;

    • CODE

      module.exports = {
        output: {
          // 为什么这样命名?方便应用浏览器的缓存机制
          filename: 'js/[name].[hash:8].js',
        }
      }
      

        webpack官方:output->filename 

        webpack官方:缓存(输出哈希文件名)

  • path:打包时会将 bundle 写入到output.path选项指定的目录下
    • 官方给出:对应一个绝对路径,如何配置它的值?

      绝对路径不做解释,懂得都懂,不懂得自查;

      在node下提供了一个全局变量__dirname,表示的就是当前执行的脚本文件所在的绝对路径;

    • CODE

      module.exports = {
        output: {
          filename: 'js/[name].[hash:8].js',
          // 将打包后的资源输出到当前目录下的 dist 目录中
          path: path.resolve(__dirname, 'dist')
        }
      }
      
  • assetModuleFilename:与output.filename相同,不过应用于Asset Modules(字体or图标)
    • 支持的占位符:[name],[file],[query],[ext],[hash][path]
      • name:原始文件名
      • file:完整文件名(带拓展名)
      • query:URL查询参数部分——图的大中小到底请求哪个?(x.png?size=large),得到的是问号及后面的部分;
      • ext:文件拓展名
      • hash:根据文件内容生成的哈希值|区别与chunkhash和contenthash,是整个项目构建过程的哈希值,现在V5中叫fullhash。
      • path:文件的相对路径。
    • 同内容但更新了文件名?涉及到文件名及内容,避免延迟更新。
    • 注意:
      • 该配置项是全局的,全局优先级低于局部的;
      • 局部指的是后面通过asset系列方式对资源文件做解析时配置的generato.filename。
    • CODE
    module.exports = {
      output: {
        filename: 'js/[name].[hash:8].js',
        path: path.resolve(__dirname, 'dist'),
        // 将资源文件输出到 assets 目录下以hash码来命名
        assetModuleFilename: 'assets/[hash][ext]',
      }
    }
    
    
  • clean:控制是否在生成文件之前清空打包输出目录
    • 布尔值true(清空)、false(不清空)
    • 或以对象形式配置,使用keep来设置保留某个目录下的文件
    • CODE
    module.exports = {
      output: {
        filename: 'js/[name].[hash:8].js',
        path: path.resolve(__dirname, 'dist'),
        assetModuleFilename: 'assets/[hash][ext]',
        clean:true
      }
    }
    
    

optimization

优化:比如对代码进行压缩、分割代码、去除未使用的导出模块、去除空chunk等

  • minimize:告知 webpack 使用TerserPlugin或其它在optimization.minimizer定义的插件压缩 bundle;值为布尔类型。
    • CODE
    module.exports = {
      //...
      optimization: {
        minimize: true,
      },
    };
    
  • minimizer:允许开发者通过提供一个或多个定制过的TerserPlugin实例,覆盖默认的代码压缩工具,通过去除文件的换行、空格、注释等字符来缩小文件体积。
    • teser-webpack-plugin
      • 该插件使用terser来压缩Javascript(terser也是一个第三方依赖)
      • 非内置,非webpack官方插件,需要安装使用
      • webpack官方:terser-webpack-plugin
      • CODE
      npm install terser-webpack-plugin --save-dev
      
      const TerserPlugin = require('terser-webpack-plugin');
      
      module.exports = {
        optimization: {
          minimize: true,
          // 为啥是数组?你就用一个吗?接受的类型就是数组类型
          minimizer: [new TerserPlugin()],
        },
      };
      
    • css-minimizer-webpack-plugin
      • 该插件使用cssnano来压缩CSS(cssnano是一个第三方库)
      • webpack贡献,不过也需要安装使用
      • 注意:webpack只能识别处理Js文件,对CSS的压缩处理记得配置好它的加载器(下面说这个东西)。
      • webpack官方:css-minimizer-webpack-plugin
      •  CODE
      npm install css-minimizer-webpack-plugin --save-dev
      ## 安装加载器
      npm install mini-css-extract-plugin --save-dev
      
      
      const MiniCssExtractPlugin = require('mini-css-extract-plugin');
      const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
      
      module.exports = {
        // 当前的主角配置
        optimization: {
          minimize: true,
          minimizer: [
            new CssMinimizerPlugin(),
          ],
        },
        module: {
          rules: [
            {
              test: /.s?css$/,
              use: [MiniCssExtractPlugin.loader, 'css-loader'],
            },
          ],
        },
        plugins: [new MiniCssExtractPlugin()],
      };
      

加载器Loader

加载器在webpack这里有一个统称,叫loader,用于辅助webpack来加载非JS类型的文件,需要注意使用顺序。

webpack默认情况下只能处理Js文件,如果要处理其他文件,前提得让webpack能够加载其他文件,比如图片、CSS文件等。

配置在module>rules中,rules是一个对象数组,对于某类文件的解析及配置写在对象中,其中test指定某类文件,use指定所需的加载器们。

style-loader

  • style-loader:将 CSS 代码以