Webpack: 底层配置逻辑

news2024/7/6 17:50:06

概述

  • 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.coloradmin.cn/o/1860629.html

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

相关文章

Python生成器嵌套太多?使用yield from秒变简洁!

目录 1、yield from基础概念 🌐 1.1 yield关键字回顾 1.2 yield from引入动机 2、yield from深入解析 🧭 2.1 语法与用法 2.2 传递生成器控制权 2.3 与迭代器的高效整合 2.4 与传统yield对比优势 3、实战应用示例 📈 3.1 链接多个生成器 3.2 简化递归生成器实…

什么牌子的开放式耳机好?五大优质机型,新手必看!小白闭眼入系列

音乐技术的不断进步为耳机市场的发展有了更多的选择,开放式耳机成为音乐爱好者们新的一个选择。从最初的基础音质到如今的高解析度音频,开放式耳机经历了一次次的技术革新和升级。这类耳机以开放式不入耳的设计,舒适的佩戴体验著称&#xff0…

C语言实现的飞机票系统解析

前言 操作系统:Windows下运行。如果需要在Linux运行(单机版),则需要修改删除conio.h,自己写个头文件获取键盘输入。我已经写好了getch.h文件,需要将其导入使用。 开发环境:CodeBlocks || VS C…

界面组件DevExpress WinForms v24.1 - 支持DateOnly TimeOnly类型

DevExpress WinForms拥有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜…

嘀嗒出行项目管理专家和项目管理负责人王禹华受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 嘀嗒出行项目管理专家和项目管理负责人王禹华女士受邀为第十三届中国PMO大会演讲嘉宾,演讲议题为“AI时代项目经理挑战机会和个人成长”。大会将于6月29-30日在北京举办,敬请关注! 议题简要: AI时代对互…

Pyecharts入门

数据可视化 Pyecharts简介 Apache ECharts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时&#…

Vue下载接口返回流的处理

1.下载接口返回流如下: 2.可以写公共方法处理 excelDownload(obj, name Date.now(), suffix xlsx) {//Date.now()获取当前日期const url window.URL.createObjectURL(//Blob是二进制大对象new Blob([obj], { type: application/vnd.ms-excel }))const aDOM docu…

【一竞技LCK】夏季赛:HLE强势横扫2比0击败KT!

北京时间6月24日,LCK夏季赛在昨天结束了第二周最后一个比赛日的比赛。昨天第二场比赛是HLE战队迎战DK战队,本赛季DK战队的状态可以说是相当的低迷,在首轮比赛是被KDF战队给2比0横扫,昨天面对实力不俗的HLE战队也是落了下风&#x…

工程化视角的 Kotlin Multiplatform核心解读及优化

本篇为KMP技术的技术及实践系列文章的第二篇。在这篇技术文章中我们会以百人移动研发团队的工程化视角,探讨Kotlin Multiplatform的核心技术及优化。 Kotlin: 语言与编译 人们在用自然语言沟通时,内容可以不明确,甚至小的错误,而听…

【数学建模】—【Python库】—【Numpy】—【学习】

目录 ​编辑 1. NumPy安装 2. ndarray对象 1. 创建ndarray 1.从列表或元组创建: 2.使用内置函数创建: 2. ndarray属性 3. 数组运算 1. 基本运算 2. 数学函数 3.统计函数 4. 数组索引与切片 1. 一维数组索引与切片 2.多维数组索引与切片 5.…

Excel 宏录制与VBA编程 —— 16、InputBox函数的使用方式

Input函数基本操作 InputBox函数的Type参数使用技巧(输入类型限制,若输入类型不符系统提示) 关注 笔者 - jxd

山东大学-科技文献阅读与翻译(期末复习)(选择题+翻译)

目录 选择题 Chapter1 1.which of the following is not categorized as scientific literature 2.Which of the followings is defined as tertiary(三级文献) literature? 3.Which type of the following international conferences is listed as Number one conference…

【Redis】数据持久化

https://www.bilibili.com/video/BV1cr4y1671t?p96 https://blog.csdn.net/weixin_54232666/article/details/128821360 单点redis问题: 数据丢失问题:实现Redis数据持久化并发能力问题:搭建主从集群,实现读写分离故障恢复问题&…

jeecg导入excel 含图片(嵌入式,浮动式)

jeecgboot的excel导入 含图片(嵌入式,浮动式) 一、啰嗦二、准备三、 代码1、代码(修改覆写的ExcelImportServer)2、代码(修改覆写的PoiPublicUtil)3、代码(新增类SAXParserHandler&a…

算法设计与分析:并查集法求图论桥问题

目录 一、实验目的 二、问题描述 三、实验要求 四、算法思想 1. 基准算法 1.1 算法思想 1.2 代码 1.3 时间复杂度 2. 使用并查集的高效算法 2.1 算法思想 2.2 代码: 2.3 时间复杂度: 五、实验结果 一、实验目的 1. 掌握图的连通性。 2. 掌…

《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时,也带来了对安全风险防范能力的挑战。基于此,中国信通院依托中国人工智能产业发展联盟(AIIA),联合开源…

干货分享 | TSMaster 的 CAN UDS 诊断操作指南(下)

上期,我们主要介绍了 UDS 诊断模块的创建以及TSMaster 基础诊断配置。很多客户表示意犹未尽。因此我们将继续带来《TSMaster 的 CAN UDS 诊断操作指南(下)》的精彩内容,为您带来UDS on CAN/CAN FD 的功能以及详细的使用操作。 本文…

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

简介 在现代的软件开发中,特别是在 JavaScript 生态系统中,npm(Node Package Manager)是一个核心工具。它不仅仅是 Node.js 的包管理器,还扮演着项目依赖管理、脚本执行、项目发布等多重角色。理解 npm 的常用命令不仅…

【数据结构】线性表之《队列》超详细实现

队列 一.队列的概念及结构二.顺序队列与链队列1.顺序队列2.链队列 三.链队列的实现1.创建队列2.初始化队列3.入队4.出队5.获取队头元素6.获取队尾元素7.队列的大小8.队列的判空9.清空队列10.销毁队列 四.队列的盲区五.模块化源代码1.Queue.h2.Queue.c3.test.c 六.栈和队列必做O…

小白上手AIGC-基于FC部署stable-diffusion

AIGC AIGC(人工智能创造内容)作为一种基于人工智能技术生成内容的新型创作模式。打破了过去大家对于AI的理解都是说只能涉足部分领域而无法涉足艺术或者是其他的创作领域的定律,现在的AIGC也能够创作内容了,而不再只是单纯的返回…