安装 webpack

  1. npm i webpack webpack-cli -D

webbpack 配置文件

webpack 默认会使用当前文件夹下 src/index.js 做为打包的入口文件,当前文件夹下的webpack.config.js 作为 webpack 的配置文件,如果想要使用其他配置文件时,可以再 package.json 中增加一个新的脚本:

  1. {
  2. "script": "webpack --config 配置文件地址"
  3. }

如果 webpack 安装在了全局可以只使用 webpack --config 地址 的形式去运行 webpack 并指定配置文件地址,但如果 webpack 是安装在项目中时,如果想在命令行中执行 webpack ,则需要在先找到 node_modules 中的 webpack 再执行,但如果使用上面 script 脚本的方式则不需要指定 webpack 地址,直接在命令行 npm run build 即可。

webpack 基本配置

 webpack 是运行在 node 环境中的,所以在配置文件中我们需要使用 commonjs 方式将配置项导出。
// webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js', // 入口
  output: {
      filename: 'main.js', // 打包出来的文件名称
    path: path.resolve(__dirname, './dist'), // 指定打包出来的文件存储路径

    // 如果打包一个库文件会用到以下配置
    libraryTraget: 'umd', // 打包为 umd 模块
    library: 'ki', // 库的名称,也是全局暴露出来的变量名
    globalObject: "this", // 全局变量挂载到哪里,默认为 self
  },
};
  • entry:入口文件,webpack 会根据这个入口文件,分析其依赖关系进行打包
  • output:出口配置,打包完后对应的配置
    • filename:指定打包出来的 js 文件名称
    • path:指定打包出来的文件存放位置

      webpack 依赖图

      webpack 在处理应用程序时,它会根据命令或者配置文件找到入口文件,从入口文件开始,分析依赖生成一个 依赖关系图 ,这个依赖关系图会包含应用程序中所需的所有模块(js文件、图片、css、html),然后遍历图结构,打包一个个模块(使用不同的 loader 处理):
      image.png

      loader 介绍

      webpack 默认只能解析 JS 文件和 JSON 文件,如果想要解析其他文件(CSS、图片、字体等)就需要配合对应的 loader 来实现: ```javascript module.exports = { … module: { rules: [ {
       test: /\.css$/, // 一个正则表达式,匹配对应的文件,匹配中的文件将会使用下面的 loader 处理
      
      use: [
         // 使用多个 loader
       {
           loader: 'css-loader', // loader 名称
         options: {
             // 传递给 loader 的配置
         },
       },
      
      ], }, ], }, }

// 如果只使用了一个文件那么在 rules 数组中可以这样简写: { test: ‘test’, loader: ‘loader name’, // 去掉 use 直接使用 loader }

// 如果不需要给 loader 传递 option 时, 可以直接在 user 中写 loader 名称字符串 { test: ‘test’, use: [ ‘loader name1’, ‘loader name2’, ], }

当配置多个 loader 时,loader 的执行顺序时从后往前、从下往上、从右往做的,先执行 use 数组后面的 loader,再指定前面的 loader。

<a name="pq1Hd"></a>
## 打包 CSS、LESS 文件
打包 CSS 文件和 LESS 文件需要用到下面几个 loader:
```javascript
npm i css-loader style-loader less-loader less;

css-loader 用于解析 css 文件,style-loader 用于将解析好的 css 插入到 html 的 header 中,less-loader 用于调用 less 工具处理 less 文件,将 less 文件转为 css 文件,webpack 配置如下:

const path = require('path');

module.exports = {
    entry: './src/index.js',
  module: {
      rules: [
      // 配置解析 css 文件的 loader
      {
          test: /\.css$/,
        use: [
          {
              loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
        ],
      },
      // 配置解析 less 文件的 loader
      {
          test: /\.less$/,
        use: [
          {
              loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
              loader: 'less-loader',
          },
        ],
      },
    ],
  },
  output: {
      filename: 'main.js',
    path: path.resolve(__dirname, './disy'),
  },
};

浏览器兼容性

在开发中会遇到浏览器的兼容性问题,比如不同浏览器对与的 CSS 特性的支持,在一些旧版本的浏览器中我们需要加一些前缀来让其支持对应的 CSS 特性,这时我们就会用到 babel、postcss 等工具来进行浏览器的兼容,但是浏览器非常多且又很多版本,到底哪些浏览器和版本需要兼容呢?可能需要考虑到浏览器的市场占用率来判断到底需不需要兼容他们。

浏览器市场占有率查询网站:https://caniuse.com/usage-table

browserslist 工具

browserslist 是一个在不同前端工具中(babel、postcss等),共享目标浏览器和 Node.js 版本的配置。

通过安装 browserslist 工具,编写配置文件,如 babel、postcss 等前端工具,都会自动的找到这个配置文件,通过这个配置文件来实现对应浏览器的兼容性处理。

注:在安装 webpack 时已经安装上了 browserslist 工具,我们直接编写配置文件即可。

browserslist 配置文件

对于 browserslist 配置可以写在两个地方:

  • 创建 browserslistrc 文件编写配置信息
  • package.json 中编写 browserslist 配置信息

image.pngimage.png
配置文件基本编写规则:

  • defaults:Browserslist的默认浏览器(> 0.5%, last 2 versions, Firefox ESR, not dead)。
  • 5%:通过全局使用情况统计信息选择的浏览器版本。 >=,<和<=工作过。
  • dead:24个月内没有官方支持或更新的浏览器。现在是IE 10,IE_Mob 11,BlackBerry 10,BlackBerry 7, Samsung 4和OperaMobile 12.1。
  • last 2 versions:每个浏览器的最后2个版本。
  • last 2 Chrome versions:最近2个版本的Chrome浏览器。
  • last 2 major versions或last 2 iOS major versions:最近2个主要版本的所有次要/补丁版本。
  • not ie <= 8:排除先前查询选择的浏览器。

如果没有配置文件,那么会应用一个默认规则:

> 0.5%
last 2 versions
Firefox ESR
not dead

PostCSS 工具,处理 CSS 兼容问题

Post CSS 是一个通过 JavaScript 来转换样式的工具,这个工具可以帮我们实现一些 CSS 的转换和适配,比如添加浏览器前缀、CSS 样式重置,但是实现这个功能还需要再安装一些 Post CSS 插件,比如 autoprefixer。

在 webpack 中使用时我们可以安装以下依赖:

npm i postcss postcss-loader postcss-preset-env -D

postcss-preset-env: 就是一个 postcss 的插件,用于处理 css 的兼容问题。

修改 webpack 配置:

module.exports = {
    ...
  module: {
      rules: [
      {
          test: /\.less$/,
        use: [
            'style-loader',
          'css-loader',
          // 因为 postcss-loader 是对 css 文件做处理的,所以要写在 less-loader 的上面
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                  plugins: [
                    require('postcss-preset-env'), // 引入 postcss-preset-env 插件
                ],
              },
            },
          },
          'less-loader',
        ],
      }
    ],
  },
};

postcss 的配置也可以写在一个单独的 postcss.config.js 文件中,这时在 webpack 配置中就不需要写 postcss-loader 的 option 了。

// 根目录下创建 postcss.config.js 文件
module.exports = {
    plugins: [
      require('postcss-preset-env'), 
  ],
}

// webpack 中:
use: [
    ...
  'postcss-loader',
  'less-loader',
]

打包图片资源

打包图片时可以使用 file-loader 或者 url-loader,这个两个 loader 之间的区别是 url-loader 可以将图片转为 base64 之间嵌入在代码中,使用方式如下:

npm i file-loader url-loader -D

webpack 配置:

module.exports = {
    module: {
      rules: [
      {
             test: /\.(jpe?g|png|gif)$/,
        use: [
          // file-loader 配置
          {
              loader: 'file-loader',
            name: 'images/[name]-[hash:8].[ext]', // 指定输出文件名称和路径
          },

          // or

          // url-loader 配置
          {
              loader: 'url-loader',
            options: {
              // 小于 8kb 就转为 base64 打包到 js 文件中, 大于 8kb 的打包到指定的文件夹中
                limit: 8 * 1024,
              name: 'images/[name]-[hash:8].[ext]', // 指定输出文件名称和路径
            },
          },
        ],
      },
    ],
  },
};

文件名称规则

在上面的代码中指定图片名称时用了 [name]-[hash:8].[ext] 这种写法,这种写法是 webpack 的 placeholder 写法,常用的 placeholder 如下:

  • [ext]:文件拓展名
  • [name]:原文件名称
  • [hash]:文件内容通过 MD4 散列函数生成的散列值
  • [hash:x]:保留 x 位 hash 值,比如 [hash:8] 就是保留前 8 位 hash值
  • [path]:webpack 配置文件路径
  • [content-path]:在这里和 hash 相同,在其他地方不同,可以用于做性能优化。

asset module type

在 webpack 5 之前可以使用上面的 url-loader、file-loader 处理文件资源,在 webpack5 中就不再需要这两个 loader 了,可以使用 asset module type 实现相同的功能。

资源模块类型

asset module type 支持以下几种类型配置:

  • asset/resource: 打包发送一个文件资源,类似 file-loader
  • asset/inline : 将文件资源转为 data URI,类似 url-loader
  • asset : 在单独打包和转为 data URI 之间自动选择,类似 url-loader

    使用 asset module type

    module.exports = {
    module: {
     rules: [
     {
               test: /\.(png|jpe?g)/,
       type: 'asset/resource', // 指定 asset module type
           },
       ],
    },
    }
    

    指定打包文件名称和目录:
    有两种方式可以指定 asset module type 打包出来的文件名称和存放目录:

  • 在出口 output 中指定 assetModuleFilename 字段,这样可以指定全局的 asset module type 存放方式。

  • 在单个 rule 中配置,这样只有匹配到的文件才会这样处理

注:[ext] 占位符在这里默认有了 “.” ,类如 .png,所以就不需要自己加 “.” 了。

// 第一种方式(全局设置) output:
module.exports = {
  output: {
      ...,
    assetsModuleFilename: '[name]-[hash:8][ext]',
  },
    ...
}

// 第二种方式(单个设置):
module.exports = {
    module: {
        rules: [
          {
              test: /\.png$/,
              type: 'asset',
              generator: {
                  filename: '[name]-[hash:8][ext]',
                },
            },
      ],
    },
}

使用 type = asset 实现 url-loader

module.exports = {
    module: {
        rules: [
      {
                test: /\.png$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            // 配置最大 size,小于这个 size 就会转为 base64
            maxSize: 10 * 1024,
          },
        },
        generator: {
          // 指定打包文件名称和目录
                    filename: 'imgs/[name]-[hash:8][ext]',
                },
            },
        ],
    },
};

Plugin

Loader 是用于处理特定的模块类型转换,而 Plugins 是用于执行更加广泛的任务,比如:打包优化、资源管理、变量环境注入等。

Plugins 的配置

plugin 配置在 plugins 字段中,每个 plugin 都是一个类,所以需要通过 new 调用。

module.exports = {
    plugins: [
      // .. 多个 plugin
  ],
}

CleanWebpackPlugin

每次执行打包时都会创建一个文件夹,里面放着打包好的资源,多次打包时同名资源会被覆盖,没有出现重名的资源不会被覆盖和删除,如果我们不需要某些资源时,需要手动删除,这时可以利用 CleanWebpackPlugin 插件,在打包之前先将之前打包的文件删除掉,这样就不需要手动删除了:

npm i clean-webpack-plugin -D

配置:

const {CleanWebpackPlugin} = require('clean-webpack-plugin');

module.exports = {
    plugins: [
      new CleanWebpackPlugin(),
  ],
}

HtmlWebpackPlugin

HtmlWebpackPlugin 可以自动生成一个 html 模板、或指定一个 html 模块,在打包后将打包完成的资源,如 JS 文件,自动引入到这个 html 模板中:

npm i html-webpack-plugin -D

配置:

const HtmlWepbackPlugin = require('html-webpack-plugin');
module.exports = {
    plugins: [
      new HtmlWepbackPlugin({
            template: 'public/index.html', // 自己指定模板,如果不指定会自动创建
      title: 'hello webpack', // 传递一个配置,可以在模板中指定,打包后后替换掉
      inject: 'body', // 代码的插入位置,默认为 heade
      cache: true, // 开启缓存,如果文件没有发生改变就不会生成新的文件
      minify: {
          removeComments: true, // 移除注释
        collapseWhirespace: true, // 折叠空格
      },
        }),
  ],
};

模板:

<html>
  <helder>
    <title>
      /*这里会接受到配置中传递的 title */
        <%= htmlWepackPlugin.options.title %/>
    </title>
  </helder>
  <body>
    <div id='app'></div>
  </body>
</html>

DefinePlugin

image.png
上图 Vue 的模板中有一个 BASE_URL 的属性,这个并不是 html-webpack-plugin 配置的,而是全局的 webpack 配置属性,它可以在任何地方使用,配置这些全局属性的方式就是 definPlugin,definePlugin 已经集成在了 webpack 中,不需要单独下载,之间引入使用即可:

const { DefinePlugin } = require('webpack');
module.exports = {
    plugins: [
        new DefinePlugin({
            BASE_URL: '"/"', // 注意在这里写字符串时需要写两个引号
        }),
    ],
};

CopyWebpackPlugin

有的文件不需要额外的处理直接复制到打包好的文件中即可,这时可以使用 copy-webpack-plugin 实现:

npm i copy-webpack-plugin -D

配置:

const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
    plugins: [
        new CopyPlugin({
        patterns: [
        // 注意: 指定的文件目录中必须存在内容(排除掉忽略文件后存在内容), 不然打包会报错
        {
          from: 'public', // 需要打包处理的文件目录
          // to: 'dist', // 指定复制文件到哪个地方, 可以不指定, 默认跟随 webpack 的出口
          globOptions: {
            // 指定忽略复制的文件
              ignore: [
                '**/index.html',
            ],
          },
        },
            ],
    }),
  ],
};