webpack学习指南

webpack简介

webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具,当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图,然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

总之,webpack就是用来打包代码的,整个打包过程可以分为三步,即初始化编译输出,它们具体的功能如下:

  • 初始化:读取命令行参数、配置文件、默认配置,合并它们形成一个最终的配置对象。

  • 编译:根据入口文件(每个入口文件形成一个chunk)寻找依赖关系,生成模块列表,根据模块列表生成资源列表(包含代码文件、map文件等),再把所有的资源列表合并。

  • 输出:按照最终生成的资源列表生成文件。

对webpack打包流程的全貌有所理解之后,再从webpack本身、以及作为第三方库的平台两个视角 ,分三个模块来详细介绍一下webpack: (1)webpack本身的重要概念(2)webpack常用/实用的配置(3)webpack集成其它工具

一 webpack本身的重要概念

chunk:包含多个模块的代码块,这些模块从入口模块通过依赖分析得到。

bundle:chunk构建好后会生成一个资源清单,清单中的每一项就是一个bundle,可以认为bundle就是最终生成的文件。

Loader:作用是处理单个文件的转换。

自定义loader举例: 复制代码
module.exports = function(source) {
    // loader本质上是一个函数,有一个参数source,source是转换前源代码,做一系列操作后,把转换后的代码输出
    // 本例的loader作用是简单转换css文件
    return `var style = document.createElement('style');style.innerHTML =\`${source}\`;
    document.head.appendChild(style);`;
}

plugin:作用是扩展Webpack的功能,作用于整个构建流程,通过在打包生命周期的不同阶段挂载钩子函数,实现诸如生成HTML文件、压缩代码、资源管理、环境配置等功能。

自定义plugin举例: 复制代码
class MyPlugin {
    // 插件本质上是一个具有 apply 方法的 JavaScript 对象,一般通过创建类的方式定义插件,在使用时用new MyPlugin()即可
    apply(compiler) {
    // 插件的apply方法在webpack初始化阶段就运行,且只会运行一次,后续文件发生变化也不会再调用了
    // 插件提供功能的方式是在apply函数里注册事件(钩子函数、hooks),格式如下(事件名称和事件类型webpack内置好的):
    
    // compiler.hooks.事件名称.事件类型(name,function(compilation){
        // compiler的事件处理函数
        // compilation.hooks.事件名称.事件类型(name,()=>{
            // compilation的事件处理函数
        // })
    // })

    // 在compilation创建之后且模块构建开始之前,同步输出'开始构建了!'
    compiler.hooks.compilation.tap('MyPlugin-begin', (compilation) => {
      compilation.hooks.buildModule.tap('begin', (module) => {
        console.log('开始构建了!');
      });
    });

    // 编译完成后,同步输出字符串'编译完成了!'
    compiler.hooks.done.tap('MyPlugin-done',function(compilation) {
      console.log('编译完成了!');
     });
   }
}
module.exports = MyPlugin;

Compiler对象:该对象是在初始化阶段构建的,整个webpack打包期间只有一个。

Compilation对象:该对象是在compiler对象内部创建的,具体的打包工作由它完成。

环境变量:webpack在打包过程中主要是两个地方会使用环境变量,一是根据环境变量编写配置文件,二是根据环境变量编译源码文件。

  • 根据环境变量编写配置文件:命令行使用env参数传入,然后在webpack配置时,使用函数的方式导出,此函数的参数env用于接收环境变量,就可以差异化的进行webpack配置了。需要修改package.json和webpack.config.js这两个文件。
package.json 复制代码
"scripts": {
    "dev": "webpack --env development",
    "build": "webpack --env production"
}
webpack.config.js、 复制代码
mode: env.production ? 'production' : 'development',
devtool: env.production ? 'source-map' : 'eval-cheap-source-map',
  • 根据环境变量编译源码文件:如果命令行中指定了 --mode,无论配置文件中的 mode 如何设置,最终都会以命令行参数为准;如果命令行未指定 --mode,则使用配置文件中的 mode 值;如果两者均未指定,Webpack 会默认使用 production 模式,并输出警告提示。

模块类型:webpack会根据不同的模块类型(包括 ES6,CommonJS 和 AMD)采用不同的模块化标准进行编译,具体规则如下。

  • 文件扩展名:.mjs 强制视为 ESM,.cjs 强制视为 CommonJS。
  • package.json:若未指定扩展名,依据 package.json 中的 "type": "module" 或 "type": "commonjs" 判断。
  • 代码分析:未指定拓展名,package.json也未指定模块标准,则通过 AST 解析语法特征(如 import/export 或 require/module.exports)自动推断模块类型。

二 webpack常用/实用的配置

  • mode:模式配置
  • entry:入口配置
  • context:项目执行上下文路径配置,用于解析入口点(entry)和加载器(loader)
  • output:出口配置
  • module:loader配置
  • plugins:插件配置
  • devServer:开发服务器配置
  • devtool:源码地图配置
  • resolve:设置模块如何被解析
  • optimization:优化产物体积配置
  • cache:控制如何缓存编译过程信息与编译结果
  • target:为构建目标(target)指定一个环境
  • watch:配置持续监听文件变化,持续构建
  • watchOptions:一组用来定制 watch 模式的选项
  • externals:外部依赖配置,webpack会忽略这部分资源,跳过它们的解析、打包操作
  • performance:配置当产物大小超过阈值时,如何通知开发者
  • stats:精确的控制编译过程的日志内容
  • infrastructureLogging:用于控制日志输出方式,例如将日志输出到磁盘文件
  • ......

三 webpack集成其它工具

webpack中的第三方库,绝大部分要么是loader,要么是plugin,也有一些特殊工具通过其它方式与wepack进行协作,例如开发服务器webpack-dev-server等。

根据三方库的种类,大体上有两种使用的方式。

  • (1)webpack的内置插件,使用方式如下:
js 复制代码
const webpack = require('webpack');
new webpack.插件名(options)
  • (2)除了内置插件,其它三方库的使用方式都是先用npm下载,再配置使用。

下面简单介绍一下开发服务器和一些有用的库:

  • webpack-dev-server:提供开发服务器,在命令行中以webpack-dev-server方式启动,该命令几乎支持webpack所有的命令行参数,详细配置可以通过devServer选项设置。
  • file-loader:生成依赖的文件到输出目录,然后将模块文件设置为:导出一个路径。
  • url-loader:将依赖的文件转换为:导出一个base64格式的字符串。
  • raw-loader:不做任何转译,简单将文件内容复制到产物中,适用于SVG场景。
  • html-webpack-plugin:生成一个 HTML 文件供打包结果使用,并且可以自定义模板。
  • copy-webpack-plugin:将已存在的单个文件或整个目录复制到构建目录。
  • DefinePlugin:定义一些全局的常量。
  • BannerPlugin:为每个 chunk 文件头部添加 banner(版权、声明等信息)。
  • ProvidePlugin:自动加载模块,而不必在任何地方导入它们,项目中非常多需要导入的模块可以使用该插件。

ps:file-loader、url-loader、raw-loader使用频率极高,webpack5直接内置了这些能力,只需要通过module.rules.type属性指定资源类型即可。

总结

关于webpack的介绍就这么多,关于webpack本身的重要概念其实并不多。

更重要的是它的使用,比如关于webpack命令行接口、Node接口等语法。

更更重要的,它还是一个平台,能集成丰富的插件,自然有很多插件的语法,比如插件生命周期、compiler钩子、compilation钩子、各种插件配置等。

总之,目前webpack的生态非常丰富,本文只介绍了一部分,还需要开发者通过实践的过程慢慢探索。

相关推荐
RadiumAg22 分钟前
记一道有趣的面试题
前端·javascript
yangzhi_emo26 分钟前
ES6笔记2
开发语言·前端·javascript
yanlele42 分钟前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
中微子2 小时前
React状态管理最佳实践
前端
烛阴2 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子2 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...2 小时前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts
皮皮林5513 小时前
90 后程序员辞职搞灰产,不到一年获利超 700 万,结局很刑!
程序员
天天扭码3 小时前
《很全面的前端面试题》——HTML篇
前端·面试·html
xw53 小时前
我犯了错,我于是为我的uni-app项目引入环境标志
前端·uni-app