Webpack 概念速通:从入门到掌握构建工具的精髓

devtools/2024/9/20 1:13:48/ 标签: webpack, 前端

Webpack基本概念

这里我们先简单熟悉下Webpack的基本概念,我们在搭建项目的时候都会要用到的!

这里我们分享的着重点是基本概念而不是具体配置项和使用方法

  • 依赖图(dependency graph)
  • 模式(mode)
  • 入口(entry)
  • 输出(output)
  • 加载器(loader)
  • 插件(plugin)
  • 源映射(Source Maps)
  • 开发服务器(devServer)

依赖图(dependency graph)

依赖图是指所有模块及其相互之间的依赖关系的一个整体表示。

简单来说,当Webpack处理应用程序时,它会从一个或多个入口文件(entry point)开始递归地构建一个图表。这个图表描述了项目中所有模块是如何相互依赖的。每个文件、模块都是图中的一个节点,节点之间的连接线(边)代表了文件的引入关系或依赖关系。

举个例子,如果你的应用程序有一个入口文件 index.js,它依赖于另一个模块 moduleA.js,而 moduleA.js 又依赖于 moduleB.js,那么Webpack会生成一个包含这些文件的依赖图。通过这个依赖图,Webpack可以知道哪些模块需要被打包在一起,并以合适的顺序加载它们。

这种方式可以确保最终生成的打包文件是最优化的,只包含了实际使用的代码,并且依赖关系被正确解析,从而确保应用程序能够正常运行。

模式(mode)

模式(mode) 是用来指定打包时的环境,主要分为三种:developmentproductionnone。不同的模式会影响 webpack的打包方式和优化策略,以适应不同的开发需求。

这里我们主要是说开发和生产两种模式:

development 模式production 模式
输出文件非压缩,带有注释与调试信息压缩,移除所有注释与调试信息
Source Map默认启用eval-source-map默认禁用或启用高效的source-map
压缩不压缩自动压缩代码并移除未使用的代码
性能优化关闭性能提示启用性能提示与限制
树摇优化(Tree Shaking)不启用启用,移除无用代码
环境变量process.env.NODE_ENV 被设为 'development'process.env.NODE_ENV 被设为 'production'

通过上面的表格中的对比我们可以总结得出:

  • development:适合本地开发,提供调试信息,构建速度快
  • production:适合生产环境,自动压缩和优化代码,提高性能

none呢,它完全不应用任何优化,完全自定义,通常我们不使用这个模式…

入口(entry)

我们上面在说依赖图的时候实际上也提到了我们的核心概念——入口

入口起点(entry point) 指示webpack应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后webpack会找出有哪些模块和库是入口起点(直接和间接)依赖的。

我们有多种方法可以配置入口:

单个入口(简写)语法

  1. 字符串

    用法:entry: string

    webpack.config.js中:

    module.exports = {entry: './src/index.js',// ...其他配置
    }
    
  2. 数组

    用法:entry: [string]

    当你使用数组形式来定义入口时,Webpack会按照数组中文件的顺序依次加载它们,并且所有这些文件将会被编译进同一个bundle中。这种方式适合于需要按特定顺序加载多个文件的情况,即多页面应用程序。(注意:数组中所有文件会被合并到一个输出文件中)

    webpack.config.js中:

    module.exports = {entry: ['./src/polyfills.js', './src/index.js'],// ...其他配置
    }
    

    在这个例子中,Webpack会首先加载 polyfills.js 文件,然后加载 index.js 文件。这两个文件的内容会被合并到同一个输出文件中。

对象语法

用法:entry: { <entryChunkName> string | [string] } | {}

当你使用对象形式来定义入口时,每个键值对实际上是在定义一个独立的入口点。这意味着每个入口点都可能会有自己的输出文件(取决于 output 配置,我们这里简单说下,这里后面会详细说),并且它们之间是相互独立的。

webpack.config.js中:

const path = require('path');
module.exports = {entry: {main: './src/index.js',vendor: './src/vendors.js'},output: {path: path.resolve(__dirname, 'dist'),filename: '[name].bundle.js'}
}

这里定义了两个入口点:mainvendor。每个入口点都指向了一个单独的文件,Webpack会分别为它们创建对应的输出文件。例如,如果 output.filename 被设置为 [name].bundle.js,那么最终的输出文件名将是 main.bundle.jsvendor.bundle.js(注意是两个文件)

用于描述入口对象的常用属性有以下几种:

  1. dependOn:指定当前入口所依赖的入口
  2. filename:用于覆盖默认的文件名生成规则(优先级高)
  3. import:启动时需要提前加载的模块

看下面这段代码来简述这三个属性的使用:

module.exports = {entry: {one: './a',two: {import: './b',dependOn: 'one',filename: 'B.bundle.js'}},output: {filename: '[name].bundle.js'}
}

它设定了两个入口点,其中two入口点依赖于one入口点,one文件中的代码应该在two之前执行;one的输出文件名为one.bundle.js,而two由于设定了优先级更高的filename属性,输出文件名为B.bundle.js

输出(output)

输出(output)告知webpack在向硬盘写入编译后(打包后)的文件的具体路径名称,值得一提的是,output配置并不像entry一样可以有多个,它只可以被唯一指定

在说输出之前,我们先来说一下输出中处处会用到的占位符

我们来说几个常见的占位符:

  • [name]:入口文件的名称
  • [id]:模块的id
  • [ext]:输出文件的扩展名(通常在最后)
  • [hash]:根据编译的版本计算的哈希值,文件内容变化时会变,适合做缓存
  • [chunkhash]:根据chunk内容生成的哈希值,每个chunk不同。(chunk是块,它在webpack中指打包过程中生成的一组模块,简单说,chunk是在构建过程中生成的代码片段,它的目的就是将代码分割成多个块,这样可以显著的优化加载和提高性能)
  • [contenthash]:根据文件内容生成的哈希值(通常是静态文件)
chunkhashcontenthash
基于Chunk 的内容(多个模块的集合)单个文件的内容
常用场景JavaScript 文件(尤其是代码分割后的)CSS 文件、静态资源文件(图片、字体)
缓存控制较为宽泛,依赖整个chunk的变化更精确,依赖单个文件内容变化
变化条件当chunk内的任一模块内容变化时改变当文件内容变化时改变

占位符是固定的,不可以随便更改名字的哦~

输出(output) 很重要,但是却相对简单,下面我们来说一下output的常见配置选项:

  1. path:指定打包文件的输出目录。

    此配置通常与Node.js的path模块结合使用(这应该不需要我过多解释吧…),来看一段代码:

    const path = require('path')
    module.exports = {output: {// 输出文件夹为项目根目录下的 dist 文件夹path: path.resolve(__dirname, 'dist'), },
    }
    
  2. filename:指定输出文件的文件名,与入口相关

    此属性是output属性的最低要求,这意味着你必须要在output属性中添加此配置。属性允许我们动态命名文件,也就是使用我们上面说过的占位符

    来看一个小栗子:

    const path = require('path')
    module.exports = {entry: {main: './src/index.js',admin: './src/admin.js'},output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[hash].bundle.js', 
    }
    

    我们定义了两个入口文件,同时指定了输出目录(path),在这里我们使用了两个占位符[name][hash],输出的文件名会是main.[hash].bundle.jsadmin.[hash].bundle.js

  3. chunkFilename:用于指定非入口chunk文件的名称,这些chunk通常由动态导入或代码分割生成。

    此配置也允许我们使用占位符动态命名文件:

    module.exports = {// ...output: {// ...chunkFilename: '[id].[chunkhash].js', // ...},
    }
    
  4. library:可以让你控制你的库如何被其他代码导入或引用。当你构建一个库而不是应用程序时,这个选项变得尤为重要。

    来看一段library实际使用的代码段:

    const path = require('path')
    module.exports = {entry: './src/index.js',output: {filename: 'my-library.js',path: path.resolve(__dirname, 'dist'),library: {name: 'MyLib',type: 'umd', // 支持CommonJS2, CommonJS, AMD, 和全局变量// 如果需要,还可以指定exportNameexport: 'default',},},mode: 'production', // 后面再解释
    }
    

    在控制台输入npx webpack来进行库的打包,上述代码打包后,你会在dist文件夹中看到一个my-library.js文件。

    现在你可以将打包好的库部署到某个地方:

    1. 如果你发布到了一个可访问的URL(例如:https://example.com/dist/my-library.js),那么我们就可以在HTML页面中通过<script>标签来进行引入:

      <script src="https://example.com/dist/my-library.js"></script>
      
    2. 如果你将库发布到了NPM,那么你可以通过npm install来安装它,像我们熟知的模块一样导入使用:

      import { add, sub } from 'myLibrary' // 假设我们定义了这两种方法...
      
  5. publicPath:用于配置项目中所有资源(如 JavaScript、CSS、图片等)的公共 URL 前缀

    它主要影响的是打包之后HTML中引用这些资源的路径,可以理解为输出目录的”虚拟“路径或URL前缀。我们来看一个例子就会瞬间理解publicPath

    现在我们假设有一个项目要部署到https://cdn.example.com/上,那么我们可以这样进行配置:

    const path = require('path')
    module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'), // 打包输出的物理路径filename: '[name].[hash].bundle.js',  // 输出文件名publicPath: 'https://cdn.example.com/assets/'  // 静态资源的公共URL前缀}
    }
    

    在我们打包后生成的HTML文件中,引用的脚本的形式可能为:<script src="https://cdn.example.com/assets/main.a1b2c3.bundle.js"></script>

    如果没有设置publicPath的话,webpack会默认使用相对路径(./)的形式来引用生成的资源文件。

    默认的相对路径可以满足简单的项目结构或者是静态的网站部署,但是如果针对特定复杂的项目(类似CDN)来说肯定是不合理的,所以是否需要配置publicPath还请君细细斟酌~

  6. assetModuleFilename:用于确定静态资源文件的输出路径和名称。

    直接上例子:

    const path = require('path')
    module.exports = {output: {assetModuleFilename: 'assets/[hash].[contenthash][ext]',},
    }
    

    假设你在代码中引入了一个logo.png,那么输出路径类似于:assets/logo.[contenthash].png

  7. clean:用于清除输出目录(webpack5新增配置)。

    它对于确保构建目录只包含当前构建生成的文件是非常有用的,特别是在构建过程中可能会出现旧文件残留的情况。为true时为开启。

加载器(loader)

加载器(loader)webpack中处理和转换文件内容的工具。它允许webpack处理各种类型的非JavaScript文件(如CSS、图片、字体等)。使用loader,可以将这些文件转换为webpack认识的模块。

webpack中通常使用配置文件中的 module.rules 中配置loader,每个规则包括:

  1. test:一个正则表达式,用于匹配需要处理的文件类型。

  2. exclude:排除某些文件或目录,以避免不必要的处理。

  3. include:指定包含的文件或目录。

  4. use:指定使用的loader配置

  • loader: 指定使用的加载器(如果没有其他配置的话默认为loader)

  • options: 传递给loader的配置选项

  1. type: 用于指定如何打包和处理静态文件资源(专门处理图片资源的属性,相当于use,webpack5新加属性)

加载器最常见的使用场景就是针对js、css和静态资源文件,这里我们着重说一下打包静态资源时使用的type属性的几个值:

'asset/resource''asset/inline''asset''asset/source'
作用将静态资源打包到output并返回资源的URL将静态资源作为Base64编码的字符串嵌入到打包后的js文件中webpack自动判断是将文件作为resource还是inline处理将文件的内容作为字符串导入到js中
说明文件单独生成,打包时会将文件复制到dist目录中适用于文件较小的情况,减少HTTP请求是混合处理方式,文件小于8KB会使用inline,反之会使用resource通常在倒入txt文件时采用,使用场景较少

插件(plugin)

插件(plugin) 是用来扩展webpack功能的。

插件在整个构建过程中执行各种任务。它与loader不同,loader只是转换文件,而插件的功能更为强大,几乎能够完成你想要的任何任务。包括打包优化,资源管理,注入环境变量等一系列的任务。

可以说插件是基于webpack之外的工具库,它可以让你集成其他工具来强化、充盈你的webpack

源映射(Source Maps)

在生产环境中,代码通常会被打包和压缩,这使得调试变得非常困难,因为生成的代码是混淆和压缩过的。而有了Source Maps,浏览器开发者工具可以帮助你查看原始的源代码,而并非是打包、压缩或编译后的,这会让调试更加直观和方便。

假设你有一个源文件app.js,在构建过程中,Webpack会生成一个压缩后的文件(如app.bundle.js),同时也会生成一个app.bundle.js.map文件。这个.map文件包含了原始代码的行号、列号和文件的对应关系。

Source Maps仅需要手动开启一下即可:

module.exports = {devtool: 'source-map', // 生成完整的 Source Maps
}

开发服务器(devServer)

开发服务器(devServer) 专为开发环境设置。它提供了一系列的功能,帮助开发者在本地快速开发、调试和预览项目。它的主要作用是提高开发效率,通过一些高效的配置项优化开发体验。

这里有一个常见的误区,就是被开发服务器映射到浏览器的代码其实并不是你编辑器中的代码(包括打包后和打包前的),实际被映射的代码是在内存中的。

webpack的开发服务器在开发模式下所提供的打包文件都是存在在内存中的,而不是从物理硬盘上直接读取的文件。

我们来说一些常见的配置项以及相应的作用:

  1. static:定义哪些文件夹中的内容将作为静态资源提供

    • directory:通常由此属性指定静态文件目录。这些静态资源不会经过webpack的打包处理,而是直接提供给浏览器访问。这通常用于服务不需要通过webpack处理的文件,如图片、字体等,或某些独立的HTML文件。

    常见使用方式为:

    module.exports = {devServer: {static: {directory: path.resolve(__dirname, 'public')}}
    }
    

    这段代码的意思为,webpack会直接提供public文件夹中的文件,它们不会经过任何打包处理,即使没有使用webpack的入口文件,也能直接通过URL访问这些资源。

    同样也可以传递dist值,但是正如上面误区所提示的,在开发模式下我们实际提供的打包文件都是在内存中的,所以即使你编辑器中的dist文件夹下内容为空,也可以正常访问项目。那么我们来看一下publicdist的区别:

    publicdist
    用途通常用来存放不需要经过webpack打包处理的静态文件,这些文件可以是HTML文件、图片、Font文件、独立的js文件等,直接供浏览器访问用于在开发服务器中模拟生产环境的静态文件
    表现开发服务器会直接提供public(存放静态资源文件的文件夹)文件夹下的所有文件,它们可以直接通过url访问开发服务器不会从物理的dist目录打包文件,而是从内存中读取它生成的文件
    使用场景图像、字体等不会修改的静态资源查看已经打包完成的文件结构(但在开发模式下,文件其实是从内存提供的)
  2. port:指定开发服务器运行的端口

  3. open:是否在启动开发服务器时自动打开服务器(默认值为false

  4. hot:启用HMR(热模块更新),使得在修改代码时页面不刷新而只替换修改的模块(默认值为false

  5. historyApiFallback:支持H5历史模式路由时,重定向404相应到index.html(默认值为false

  6. proxy:将请求代理到另外一个服务器中,常用语开发环境下的API请求

    • target: 代理的目标服务器
    • changeOrigin:修改请求的来源为目标服务器,解决跨域问题(默认值为false
    • pathRewrite:设置api路径配置
  7. compress:启用Gzip压缩,提高资源的加载速度

  8. client:用于配制客户端设置

后续会继续持续更新补充文章中的概念相关的问题,同时也会继续分享一些使用场景来帮助大家巩固webpack的使用。

如果文章有哪里写错劳烦各位在评论区里指正,我会感激不尽!

如果你看到这里很啦希望你可以点个赞鼓励一下作者,非常感谢!


http://www.ppmy.cn/devtools/111721.html

相关文章

基于微信小程序的图书馆预约占座系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的图…

RHCE--复习(二)之时间同步服务器

一、计时方式的发展 1.1.古代计时方式 在远古时期&#xff0c;人类用来确定时间的方式是一些自然界“相对”宜古不变的周期。如地球的公转是为一年&#xff0c;月球的公转是为一月&#xff0c;地球的自转是为一天等&#xff0c;最早的计时可以追溯到公元前大约2000年&#xff…

基于SpringBoot的古城墙景区管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的古城墙景区管理系…

Excel 基础知识-操作手册1

Excel基础操作知识 一、工作窗口的视图控制 1、创建新窗口&#xff1a;依次点击【视图】----【新建窗口】命令&#xff0c;即可为当前工作簿创建新的窗口。在原有的工作簿中更改标题或表格内容时&#xff0c;新建的工作簿也会相应的更改。 2、窗口切换&#xff1a;在【视图】…

css父容器溢出隐藏 子容器溢出滚动

在父容器上设置 overflow: hidden; 可以隐藏溢出的内容。如果你想要在子容器溢出时出现滚动条&#xff0c;可以设置 overflow: auto;。 HTML: <div class"parent"><div class"child">这里是一些可能会溢出的内容...</div> </div&g…

UNION嵌套STRUCT的两种类型

1. STRUCT里面的总长度大于UNION中的最大长度 在UNION类型中&#xff0c;嵌套如STRUCT类型&#xff0c;其中STRUCT的类型还比UNION类型中最大的类型的长度还长的时候&#xff0c;会如何处理呢&#xff0c;看下面示例 程序源码 #include "stdafx.h"typedef unsigned…

HarmonyOS开发5.0【应用程序包】

对比HarmonyOS 与 Android 的应用程序包 HarmonyOS 的应用程序包与 Android 的应用程序包在多个方面存在一些不同之处&#xff0c;主要体现的方面&#xff1a; 包格式&#xff08;从包的后缀名可以看出来&#xff09; HarmonyOS: 使用 .hap 格式作为应用程序包。这个格式是 …

linux限制普通用户只能上传文件不能下载和传文件到到其他服务器

1、实施方案 因为用户在linux系统默认主要是通过sftp、scp和lrzsz命令实现文件上传和下载&#xff0c;可以通过以下几点来防制普通用户的上传和下载文件&#xff0c;相关设置必须使用root用户进行操作。 禁用普通用户使用scp命令&#xff0c;可以防止普通用户使用winscp软件下…

利用 Zero-1-2-3 进行多视图 3D 重建:从单图像到多视图 3D 模型的生成

3D 模型生成在计算机视觉领域有着广泛的应用&#xff0c;从虚拟现实到自动驾驶&#xff0c;基于单张图像的 3D 重建技术正在迅速发展。这篇博客将带你深入探索如何使用 Zero-1-2-3 框架进行多视图 3D 重建&#xff0c;通过详细解析该框架中的代码结构和功能&#xff0c;帮助你理…

WTL580-电子锁微波雷达应用解决方案,5.8GHz精准人体感知,触发高效交互新体验

一、简介 随着智能电子门锁普及&#xff0c;电子门锁的市场也随着打开&#xff0c;安装智能化电子门锁也为大势所趋。现我司推出基于WTL580微波雷达的电子锁应用方案&#xff0c;通过检测门锁周围是有活动人体存在来激活门锁。我司WTL580微波雷达方案采用5.8GHz微米波雷达传感器…

C语言-第十章:预处理

传送门&#xff1a;C语言-综合案例&#xff1a;通讯录 目录 第一节&#xff1a;什么是预处理 第二节&#xff1a;#define 2-1.定义符号 2-2.给类型取别名 2-3.定义一段代码 2-4.定义宏 2-5.#define 的替换规则 2-6.宏中的# 2-7.宏中的## 2-8.#undef 移除一个宏定义 第三节&a…

武汉传媒学院联合创龙教仪建设DSP教学实验箱,基于DSP C6000平台搭建

1、院校简介 武汉传媒学院是中南地区唯一一所传媒类本科高校&#xff0c;也是湖北省“转型发展”首批试点高校 前身是2004年成立的华中师范大学武汉影视工程学院&#xff0c;2007年经教育部批准更名为华中师范大学武汉传媒学院&#xff0c;2016年&#xff0c;经教育部批准&…

漫谈设计模式 [10]:享元模式

引导性开场 菜鸟&#xff1a;老鸟&#xff0c;我最近在做一个游戏开发项目&#xff0c;发现内存占用特别大&#xff0c;尤其是一些重复对象&#xff0c;非常浪费资源。你有什么建议吗&#xff1f; 老鸟&#xff1a;这个问题很常见。你听说过设计模式中的“享元模式”吗&#…

HarmonyOS开发实战( Beta5.0)滑动视频自动播放案例实践

鸿蒙HarmonyOS开发往期文章必看&#xff1a; HarmonyOS NEXT应用开发性能实践总结 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; 介绍 本示例主要介绍视频列表滑动到屏幕中间自动播放场景&…

电巢科技携Ecosmos元宇宙产品亮相第25届中国光博会

第25届中国国际光电博览会&#xff08;“CIOE中国光博会”&#xff09;今日在深圳国际会展中心盛大开幕。本届博览会以“光电引领未来&#xff0c;驱动应用创新”为主题&#xff0c;吸引了全球超过3700家优质光电企业参展&#xff0c;展示了光电产业的最新成果和前沿技术。 电…

Excel 基础知识-操作手册2

十、查找与引用函数 Excel中的查找与引用函数非常丰富&#xff0c;以下是一些主要的函数及其使用示例&#xff1a; 1. **VLOOKUP** - 语法&#xff1a;VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup]) - 示例&#xff1a;假设A列是员工编号&#xff0c;B…

YOLOv5植物识别系统

YOLOv5植物识别系统 项目描述 本项目旨在开发一个基于YOLOv5的植物识别系统&#xff0c;该系统能够通过图像识别技术自动检测和分类植物。项目使用YOLOv5作为核心检测模型&#xff0c;并结合Python编程语言&#xff0c;构建了一个高效、准确的植物识别工具。该系统不仅可以用于…

漫谈设计模式 [20]:解释器模式

引导性开场 菜鸟&#xff1a;老鸟&#xff0c;我最近在处理一个项目&#xff0c;需要解析和执行一些简单的脚本语言。但是&#xff0c;我实现的代码变得非常复杂和难以维护。你有过类似的经验吗&#xff1f; 老鸟&#xff1a;当然有&#xff0c;解析和执行脚本语言确实会让代…

2024网络安全人才实战能力白皮书安全测试评估篇

9月10日&#xff0c;国内首个聚焦“安全测试评估”的白皮书——《网络安全人才实战能力白皮书-安全测试评估篇》&#xff08;以下简称“白皮书”&#xff09;在国家网络安全宣传周正式发布。 作为《网络安全人才实战能力白皮书》的第三篇章&#xff0c;本次白皮书聚焦“安全测…

JavaWeb项目打包、部署至Tomcat并启动的全程指南(图文详解)

前言 我们想要部署一个javaWeb项目到tomcat上&#xff0c;需要了解一些概念 什么是tomcat&#xff1f; Tomcat 是 Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;下的一个开源项目&#xff0c;主要用于实现 Java Servlet、JavaServer Pages&#xff08;…