Webpack: 底层配置逻辑

概述

  • Webpack 5 提供了非常强大、灵活的模块打包功能,配合其成熟生态下数量庞大的插件、Loader 资源,已经能够满足大多数前端项目的工程化需求,但代价则是日益复杂、晦涩的使用方法,开发者通常需要根据项目环境、资源类型、编译目标编写一份复杂的配置文件,用以定制资源打包行为
  • 问题是,仅 Webpack 原生配置项就多达上百种,且各项之间缺乏一致性与关联度,对初学者而言单是掌握每一个配置的作用与变种就已经很难,更不用说理解配置与配置之间的协作关系
  • 对此,我们将尝试通过一种结构化视角分类讨论 Webpack 各个核心配置项的功能与作用;再用一个简单的例子介绍配置项结构的逻辑;最后介绍一些业界比较知名,能迅速生成项目脚手架的工具

结构化理解 Webpack 配置项

  • Webpack 原生提供了上百种配置项,这些配置最终都会作用于 Webpack 打包过程的不同阶段,因此我们可以从流程角度更框架性、结构化地了解各项配置的作用。

  • Webpack 的打包过程非常复杂,但大致上可简化为:

  • 输入:从文件系统读入代码文件;

  • 模块递归处理:调用 Loader 转译 Module 内容,并将结果转换为 AST,从中分析出模块依赖关系,进一步递归调用模块处理过程,直到所有依赖文件都处理完毕;

  • 后处理:所有模块递归处理完毕后开始执行后处理,包括模块合并、注入运行时、产物优化等,最终输出 Chunk 集合;

  • 输出:将 Chunk 写出到外部文件系统;

  • 从上述打包流程角度,Webpack 配置项大体上可分为两类:

    • 流程类:作用于打包流程某个或若干个环节,直接影响编译打包效果的配置项
    • 工具类:打包主流程之外,提供更多工程化工具的配置项

流程类配置项

  • 与打包流程强相关的配置项有:

1 ) 输入输出

  • entry:用于定义项目入口文件,Webpack 会从这些入口文件开始按图索骥找出所有项目文件;
  • context:项目执行上下文路径;
  • output:配置产物输出路径、名称等;

2 ) 模块处理

  • resolve:用于配置模块路径解析规则,可用于帮助 Webpack 更精确、高效地找到指定模块
  • module:用于配置模块加载规则,例如针对什么类型的资源需要使用哪些 Loader 进行处理
  • externals:用于声明外部资源,Webpack 会直接忽略这部分资源,跳过这些资源的解析、打包操作

3 ) 后处理

  • optimization:用于控制如何优化产物包体积,内置 Dead Code Elimination、Scope Hoisting、代码混淆、代码压缩等功能
  • target:用于配置编译产物的目标运行环境,支持 web、node、electron 等值,不同值最终产物会有所差异
  • mode:编译模式短语,支持 developmentproduction 等值,可以理解为一种声明环境的短语

4 ) 划重点

  • 这里的重点是,Webpack 首先需要根据输入配置(entry/context) 找到项目入口文件;之后根据按模块处理(module/resolve/externals 等) 所配置的规则逐一处理模块文件,处理过程包括转译、依赖分析等;模块处理完毕后,最后再根据后处理相关配置项(optimization/target 等)合并模块资源、注入运行时依赖、优化产物结构等
  • 这些配置项与打包流程强相关,多关注它们对主流程的影响,例如 entry 决定了项目入口,而 output 则决定产物最终往哪里输出;resolve 决定了怎么找到模块,而 module 决定了如何解读模块内容,等等

工具类配置项

  • 除了核心的打包功能之外,Webpack 还提供了一系列用于提升研发效率的工具,大体上可划分为:

1 ) 开发效率类

  • watch:用于配置持续监听文件变化,持续构建
  • devtool:用于配置产物 Sourcemap 生成规则
  • devServer:用于配置与 HMR 强相关的开发服务器功能

2 ) 性能优化类:

  • cache:Webpack 5 之后,该项用于控制如何缓存编译过程信息与编译结果
  • performance:用于配置当产物大小超过阈值时,如何通知开发者

3 ) 日志类

  • stats:用于精确地控制编译过程的日志内容,在做比较细致的性能调试时非常有用

  • infrastructureLogging:用于控制日志输出方式,例如可以通过该配置将日志输出到磁盘文件等等

  • 逻辑上,每一个工具类配置都在主流程之外提供额外的工程化能力,例如 devtool 用于配置产物 Sourcemap 生成规则,与 Sourcemap 强相关;devServer 用于配置与 HMR 相关的开发服务器功能;watch 用于实现持续监听、构建

  • 工具类配置内聚性较强,通常一个配置项专注于解决一类工程问题,学习时建议先对配置项按其功能做个简单分类,例如上述开发效率类、性能优化类等,之后再展开研究其可选值与效果

  • 综上,虽然 Webpack 提供了上百项复杂配置,但大体上都可以归类为流程类配置或工具类配置,对于流程类配置应该多关注它们对编译主流程的影响;而工具类则更加内聚,基本上一种配置项解决一种工程化问题。

  • 除了上面提到的属性外,Webpack 还提供了诸如 amdbaildependencies 等配置项,但使用频率较低,此处先不展开讨论

配置逻辑综合解析

接下来,我们构造一个简单示例,了解设计一个 Webpack 配置的过程,示例文件结构:

.
├── src
|   └── index.js
└── webpack.config.js

其中,src/index.js 为项目入口文件,webpack.config.js 为 Webpack 配置文件。在配置文件中,首先我们需要声明项目入口:

// webpack.config.js
module.exports = {entry: "./src/index"
};

之后,还需要声明产物输出路径:

// webpack.config.js
const path = require("path");module.exports = {entry: "./src/index",output: {filename: "[name].js",path: path.join(__dirname, "./dist"),}
};

至此,已经足够驱动一个最简单项目的编译工作。但是,在前端项目中经常需要处理 JS 之外的其它资源,包括 css、ts、图片等,此时需要为这些资源配置适当的加载器:

// webpack.config.js
const path = require("path");module.exports = {entry: "./src/index",output: {filename: "[name].js",path: path.join(__dirname, "./dist"),},module: {rules: [{test: /\.less$/i,include: {and: [path.join(__dirname, './src/')]},use: ["style-loader","css-loader",// "./loader",{loader: "less-loader",},],}],},
};

到这里已经是一个简单但足够完备的配置结构了,接下来还可以根据需要使用其它工程化工具,例如使用 devtool 生成 Sourcemap 文件;使用 watch 持续监听文件变化并随之重新构建。后面章节会展开细节,此处不赘述。

脚手架工具

上述概览只是对从流程角度对 Webpack 配置项做了一个简单的分类总结,实际应用中往往需要牵涉更多 Loader、Plugin,加之性能、效率方面的考虑,配置复杂度往往会随项目推进而极速膨胀,届时配置管理会变得比较困难。为此,社区提供了许多用于快捷管理配置的工具,包括:

  • Vue CLI:用于帮助用户快速创建、运行 Vue.js 项目脚手架的命令行工具;
  • create-react-app:用于创建 React 项目脚手架的命令行工具;
  • @angular/cli:用于创建 angular 项目的命令行工具;
  • webpack-cli:Webpack 官方提供的命令行工具,提供了一套交互式生成配置文件的指令集,以及项目编译、开发、迁移等功能;
  • Neutrino:用于快速创建、运行现代 JavaScript 应用的工具,同时支持 React、Preact、Vue、Web、Node.js、Library 等场景;
  • react-starter-kit:用于创建 React + Relay + GraphQL 应用的脚手架工具,内置 SSR 支持。

这些工具都内置了许多开箱即用的工程化能力,开发者无需从 0 开始学习 Webpack 与各种工程化组件,就可以直接使用工具一键生成足够应对中小型项目需求的工程化环境。下面我们逐一展开介绍 Vue CLI、create-react-app,你可根据技术栈需要侧重学习。

使用 Vue CLI 搭建项目脚手架

Vue CLI 全称 Vue.js Command-Line Interface,是由 Vue 核心团队开发,用于帮助用户快速创建、运行 Vue.js 项目脚手架的命令行工具。实现上,Vue CLI 底层调用 Webpack 实现针对 .vue 等资源的编译打包功能;调用 webpack-dev-server 实现包含 HMR 功能的开发服务器功能;还能通过插件方式整合 ESLint、Babal、Less 等工具。

总之, Vue CLI 提供了全套开箱即用的 Vue 项目开发、调试环境,开发者可以跳过繁琐复杂的环境配置过程,而专注于业务代码开发上。

与其它工具类似,使用 Vue CLI 时首先需要安装依赖:

npm install -g @vue/cli# 或者使用 yarn
yarn global add @vue/cli

安装完毕后,可以使用 vue -V 测试是否安装成功:

接下来,使用 vue create 命令创建项目:

vue create [项目名]

提示:可使用 vue create --help 命令查看 create 的参数列表

执行 create 命令后,CLI 会进一步询问使用何种脚手架方案:

Vue CLI v4.5.15
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 2] babel, eslint)Default (Vue 3) ([Vue 3] babel, eslint)Manually select features

这里 Vue CLI 内置了为 Vue 2、Vue 3 分别定制的脚手架方案,对应上述第一、二项,不过这两种方案默认只会包含 Babel、Eslint 工具,实用性不强。所以结合项目的实际需求,通常会选择第三个选项 “Manually select features” 定制各项特性:

提示:具体用法,请参考 Vue CLI 官网:cli.vuejs.org/

经过上述步骤后,Vue CLI 最终都会生成对应的文件并自动安装依赖,之后就可以使用 serve 命令启动项目:

npm run serve
# 或者
yarn serve

顺利的话,最终会运行起页面如:

Vue CLI 底层依赖于 Webpack 实现编译打包等工程化能力,开发者可通过 configureWebpackchainWebpack 配置项修改 Webpack 配置信息。

configureWebpack 为例,使用时需要在 vue.config.js 文件中写入配置:

// vue.config.js
module.exports = {configureWebpack: {plugins: [new MyAwesomeWebpackPlugin()]}
}

configureWebpack 的配置规则与 Webpack 一致,同样支持 plugins/module/resolve 等配置项。实际上,Vue CLI 内部最终会调用 webpack-merge 将 configureWebpack 值与其它上下文配置合并,生成最终的 Webpack 配置信息。

chainWebpack 的用法与 configureWebpack 一致,区别仅在于此处支持 webpack-chain 语法 —— 即以函数方式链式修改 Webpack 配置:

// vue.config.js
module.exports = {chainWebpack: config => {config.module.rule('vue').use('vue-loader').tap(options => {// modify the options...return options})}
}

提示:更多信息可参考 Vue CLI 官网 Working with Webpack 一节。

Vue CLI 在 Webpack 基础上包装多一层更易用的功能结构,这确实能极速提升研发效率与体验,但代价则是我们完全不清楚其内部运作细节,这会导致开发者比较难做一些深度定制或者性能优化,此时可使用 inspect 命令生成完整的 Webpack 配置信息:

vue inspect > output.js

inspect 命令执行完毕后,会生成内容如:

此外,inspect 还提供许多根据不同条件生成配置的参数,例如针对编译环境生成配置:

vue inspect --mode production > output.prod.js

更多用法,可查阅帮助文档:vue inspect --help

使用 CRA 搭建项目脚手架

CRA 全称 Create React Application,同样是用于帮助用户快速创建、运行 React 项目脚手架的命令行工具,功能、底层实现、用法都与 Vue CLI 相似,都提供了全套开箱即用的 React 项目开发、调试环境。

CRA 用法同样简单:

npx create-react-app my-app

执行完毕后,生成项目文件:

my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src├── App.css├── App.js├── App.test.js├── index.css├── index.js├── logo.svg└── serviceWorker.js└── setupTests.js

之后,进入 my-app 目录执行 npm start 命令即可运行项目。

提示:更多用法,请参考 CRA 官网: github.com/facebook/cr…

默认规则创建的脚手架包含如下工程能力:

  • JSX、ES6、TypeScript、Flow 语法支持
  • CSS 自动添加 --webkit-- 前缀
  • 基于 Jest 的自动化测试能力
  • 支持 HMR 的开发服务器
  • 等等,具体可参考官网

必要时,读者也可以通过 npm run eject 命令导出完整的项目配置结构:

my-app
├─ .gitignore
├─ README.md
├─ config
│  ├─ env.js
│  ├─ getHttpsConfig.js
│  ├─ jest
│  │  ├─ babelTransform.js
│  │  ├─ cssTransform.js
│  │  └─ fileTransform.js
│  ├─ modules.js
│  ├─ paths.js
│  ├─ webpack
│  │  └─ persistentCache
│  │     └─ createEnvironmentHash.js
│  ├─ webpack.config.js
│  └─ webpackDevServer.config.js
├─ package-lock.json
├─ package.json
├─ node_modules
├─ ...
└─ src├─ ...

导出配置后,直接修改 webpack.config.js 等相关配置文件即可控制各项功能行为。

总结

Webpack 配置项的用法虽然比较复杂难懂,但通常可以分为流程类或工具类,流程类配置项通常会直接影响 Webpack 打包编译的规则;而工具类相对比较独立,通常用于在编译主流程之外提供额外的工程化能力。

此外,为了降低 Webpack 的应用成本,社区已经出现了不少优秀的脚手架工具,包括 Vue CLI、create-react-app、@angular/cli 等,读者可在具体技术栈上下文下使用适当工具,简化工程化管理。

思考题

工具类与流程类配置有什么区别?分别有什么特点?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/34831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

huggingface 笔记:peft

1 介绍 PEFT 提供了参数高效的方法来微调大型预训练模型。传统的范式是为每个下游任务微调模型的所有参数,但由于当前模型的参数数量巨大,这变得极其昂贵且不切实际。相反,训练较少数量的提示参数或使用诸如低秩适应 (LoRA) 的重新参数化方法…

探索增删改查(CRUD)操作在软件开发中的重要性

在软件开发中,CRUD(Create, Read, Update, Delete)是常见且基础的操作集合,它们构成了对数据进行基本管理和操作的核心。无论是开发Web应用、移动应用还是管理系统,了解和有效地实施…

通过分离有色和无色pdf页面减少打印费

该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具,去打印店打印全彩的毕业论文的话会比较贵,他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印,前者打印彩色,后者打印黑白,这…

深入浅出:NPM常用命令详解与实践

深入浅出地讲解npm常用命令及其实践,可以帮助开发者更好地理解和使用这个强大的Node.js 包管理工具。以下是一些常用的npm命令及其详细解释和实践案例: 1:初始化项目: 命令:npm init用途:生成一个package…

MySQL数据库(二):数据库基本操作

MySQL是一种流行的关系型数据库管理系统,广泛用于Web应用和各种数据存储需求。通过本次介绍,您将学习如何进行MySQL数据库的基本操作,包括创建数据库和表、插入和查询数据、更新和删除记录。这些基础知识将为您打下坚实的数据库操作基础。 目…

2023国家最高科学技术奖薛其坤院士:科学家的幸福感来自于哪里

内容来源:量子前哨(ID:Qforepost) 文丨浪味仙 排版丨沛贤 深度好文:2000字丨8分钟阅读 6 月 24 日,2023 年度国家最高科学技术奖在京揭晓,薛其坤院士荣获中国科技界崇高荣誉,这不…

【软件下载】Camtasia Studio 2024详细安装教程视频

习惯上来说Camtasia Studio是一款简单易用的高清录屏和视频编辑软件,拥有录制屏幕和配音、视频的剪辑和过场动画片、添加说明字幕和水印、制作视频封面和菜单、视频压缩和播放。不得不说Camtasia是一款屏幕录制和视频剪辑软件,教授课程,培训他…

字节跳动联手博通:5nm AI芯片诞生了?

字节跳动联手博通:5nm AI芯片诞生了? 前言 就在6月24日,字节跳动正在与美国博通合作开发一款5纳米工艺的专用集成电路(ASIC) AI处理器。这款芯片旨在降低采购成本并确保高端AI芯片的稳定供应。 根据报道,尽管芯片设计工作进展顺利…

力扣SQL50 即时食物配送 II min函数 嵌套查询

Problem: 1174. 即时食物配送 II 👨‍🏫 参考题解 Code -- 计算立即配送的订单百分比 select round (-- 计算订单日期与客户偏好配送日期相同的订单数量sum(case when order_date customer_pref_delivery_date then 1 else 0 end) * 100 /-- 计算总订…

向npm发包

前提:安装node和npm,注册npm账号 1.创建文件夹,初始化项目: mkdir my-plugin cd my-plugin npm init 2.创建 .npmignore 文件来指定在发布包时应该忽略的文件和目录。这可以帮助你减小包的大小,避免不必要的文件被上…

【linux学习十六】网络管理

网络管理器(NetworkManager)是一个动态网络的控制器与配置系统,它用于当网络设备可用时保持设备和连接开启并激活 默认情况下,CentOS/RHEL7已安装网络管理器,并处于启用状态。 认识网卡 ens32 ens33 ens34 ens35 一.ip相关 查询网络状态 sy…

2005年下半年软件设计师【下午题】试题及答案

文章目录 2005年下半年软件设计师下午题--试题2005年下半年软件设计师下午题--答案 2005年下半年软件设计师下午题–试题 2005年下半年软件设计师下午题–答案

「全新升级,性能更强大——ONLYOFFICE 桌面编辑器 8.1 深度评测」

文章目录 一、背景二、界面设计与用户体验三、主要新功能亮点3.1 高效协作处理3.2 共同编辑,毫无压力3.3 批注与提及3.4 追踪更改3.5 比较与合并3.6 管理版本历史 四、性能表现4.1 集成 AI 工具4.2 插件强化 五、用户反馈与使用案例 一、背景 Ascensio System SIA -…

如何处理Java中的BufferOverflowException异常?

如何处理Java中的BufferOverflowException异常? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在Java编程中,BufferOverflowExceptio…

C++类的继承(听课笔记)

代码1: 子类访问限定、继承方式 &#xff0c;以及 子类和父类复制兼容 #include<iostream> using namespace std;//父类和子类是两个独立的作用域 //所以他的属性和方法可以重名class Person//父类 { public:void Print(){cout << "name:" << _na…

JVM-类加载机制

一、基础概念 当我们用java命令运行某个类的main函数启动程序时&#xff0c;首先需要通过类加载器把该类加载到JVM。 其主要流程如下&#xff1a; 1.什么是类加载 那么什么是类加载&#xff1f; Java的类加载&#xff0c;就是把字节码格式“.class”文件加载到JVM的方法区…

48、基于深度学习的离群值输入向量(matlab)

1、基于深度学习的离群值输入向量原理及流程 基于深度学习的离群值检测的输入向量原理是通过神经网络模型对数据进行学习和表示&#xff0c;在该表示中探测异常样本。其流程大致如下&#xff1a; 数据预处理&#xff1a;将数据进行归一化处理&#xff0c;确保神经网络模型能够…

pycharm常用快捷键

详细总结了Pycharm的常用快捷键&#xff0c;下文介绍使用方法和场景, 并不需要记忆这些快捷键, 你只需要知道有这些快捷键, 再需要用的时候查看一下, 用的多了自然也就记住了,需要的朋友可以参考下 1.注释(添加/消除)(Ctrl /)这里说下Python的单行注释是 # , 多行注释是 注释内…

L59---101.对称二叉树(广搜)---Java版

1.题目描述 2.思路和知识点 &#xff08;1)根节点为空&#xff1a; 如果根节点为空&#xff0c;树是对称的。 (2)递归检查&#xff1a; isMirror 方法递归检查两个子树是否是镜像对称的。 (3)辅助函数 isMirror&#xff1a; 1)如果两个节点都为空&#xff0c;它们是镜像对称的…

react笔记-04redux篇

redux和react-redux笔记&#xff0c;以及项目中如何使用&#xff0c;对redux的封装&#xff0c;让其使用类似于vuex一样方便。 一、redux 1. redux工作流程 流程&#xff1a;创建action > dispatch分发action > 交给store > reducer加工数据返回给store 2. redux的…