构建工具和脚手架:从源码到dist

    • **1. 为什么需要工程转换?**
    • **2. 构建工具的核心职责**
      • 为什么要求转换
      • **1)明确三种关键问题**
      • **(2)Webpack 的打包机制**
    • **3. 开发服务器(Webpack Dev Server)**
    • **4. 文件指纹与源码地图**
      • **(1)文件指纹(Hash)**
      • **2)源码地图(Source Map)**
    • **5. 脚手架:工程化的最后一环**

1. 为什么需要工程转换?

  • 开发环境 vs. 运行时环境的不一致性

    • 开发时:使用现代语法(JSX/Sass/ESM)、npm 管理依赖
    • 运行时:浏览器仅支持标准 JS/CSS,无法直接识别 node_modules
    • 构建工具的作用:将开发环境的代码转换成浏览器可执行的代码
  • 工程结构的变化

    • 开发时:模块化、依赖关系清晰(import/require

    • 运行时:扁平化静态资源(dist 目录,含 index.html + bundle.js

工程的转换,命令是 **npm run build** 进行打包,打包完成会生成一个 dist 目录,这个目录里面有个 html 文件,有个 js 有 css,还有 assets 文件,这就是转换的结果。

2. 构建工具的核心职责

为什么要求转换

思考一个问题,我们为什么要去转换? 是因为我们开发和维护的代码和运行时需要的代码不一致了。

我们使用一个语言新的特性,不想去考虑兼容问题,但是运行时不能不考虑,运行时的代码就希望兼容性更好。再比如说,开发和维护的代码希望使用一些非常简便的语法,像 jsx,sass,我们需要对语言进行增强,这个写起来更舒服,生产效率更高,但是这个运行时它不支持,而运行时需要的代码是什么呢,是一个非常纯粹满足语言标准的代码,没有那些花里胡哨的代码。

因为开发和维护的代码和运行时的代码不一致,所以我们需要一个东西去转换,这是对代码层面的。同样,工程层面也是一个道理,我们开发和维护的工程和运行时的工程不一样。我们开发和维护的时候希望可以使用 npm 去安装各种第三方库,生成 node_modules,但是运行时不行,浏览器环境并不支持 npm ,所以我们运行时的工程是非常传统的,也就是说打包之后的代码它就完全脱离了开发的环境。我们打包之后的代码跟传统代码一样通过index.html 右键在浏览器上运行。

我们开发的时候的工程和运行时的工程结构不一致了,所以我们就需要找一个东西来进行这个转换,而进行转换的工具就叫做构建工具。所以构建工具是用来进行工程的转换的。

1)明确三种关键问题

  1. 哪种工程更适合开发和维护?

    • Webpack:一切皆模块(JS/CSS/图片均可 import
  2. 哪种工程更适合运行时?

    • 传统 HTML+JS+CSS 结构,可直接在浏览器运行
  3. 如何转换(打包)?

    • 依赖分析 → 代码转换(Babel/Loader)→ 合并优化

这三个问题没有标准,这就造成了在不同的需求下,从不同的角度出发,着力点不一样,这三个点的理解可能就不一样,于是就造成了各种构建工具的差异。构建工具有很多,webpack、rollup、esbuild等等,这些构建工具的本质差异是什么,其实就是对上边这三点的理解不一致。

webpack的这三个东西

  1. 哪种工程更适合开发和维护 (一切皆为模块,都可以进行导入)
  2. 哪种工程更适合运行时 (传统工程,就是最开始的html右键浏览器运行)
  3. 如何转换(打包) (以一个文件为入口点出发,去寻找他们的依赖关系,导入谁就依赖谁,然后就形成了一大堆文件,最后进行合并,把所有的 JS 文件合并在一起,把所有的 CSS 文件合并在一起,less 代码该转换转换,资源文件就单独形成各自的文件)

(2)Webpack 的打包机制

  • 依赖分析(不运行代码,而是解析 AST)

    • 支持 ESM (import)CJS (require)

    • 模块查找规则:

      • ./../ → 相对路径
      • ./ 开头 → node_modules 查找(遵循 package.jsonmain 字段)
  • 打包结果的特点

    • 无模块化语法(import/require 被替换)
    • 合并 JS/CSS(减少 HTTP 请求)
    • 文件指纹(Hash 值,优化缓存)

    weboack 的入口,在分析依赖关系的时候,具体是如何分析的呢?它分析的方式并不是去运行这个代码,而是把整个代码看成是一个字符串,webpack 是不会去运行代码的,它就是来进行打包转换的,把入口文件告诉 webpack,会把这个文件的内容读出来,读出来过后分析一下这个文件用到了哪些其他的文件。

    它是怎么知道用到了哪些其他的文件的,它就是把整个代码看成一个字符串,然后把这个字符串分解成为一个 AST(抽象语法树),然后通过抽象语法树去找到那些导入的语句,而且 webpack 是同时支持 ESM 和 CMJ 的,这就意味着在代码中即可以使用 import 来进行导入,也可以使用 require 来进行导入,它都支持。

    这就解决了一个疑惑,说浏览器环境并不支持 CMJ,不能使用 require,那么为什么在 VUE 和 React 代码里边可以使用这个 require,是因为写的 require、import 压根不是给浏览器看的,是给构建工具看的,像 webpack 它来识别导入语句,因为它两者都支持,所以两种导入语句都能写。

    无论写的哪一种,实际上都是告诉 webpack 这里边有依赖关系,然后它把依赖关系分析完之后进行打包,打包结果里边不会包含任何的导入语句。也就是说在源代码中写的import、require 在打包结果里边压根就不存在了,打包结果里面是不存在任何的模块化代码。

    到哪里去找这个依赖的文件呢,也就是模块的查找,在 webpack 中所有都是模块,哪怕一个图片都是模块,到哪里去找这个图片,去哪找这个 JS 呢? 有模块的查找规则。

    比如说 import ‘./cover’,cover 是一个文件夹,会默认的去找这个文件夹的 index.js 文件,比如说 import $ from ‘jquery’,目录里面没有 jquery文件夹,这又是一个查找规则,当给的路径不以’./‘,’…/'开头时,这个时候用的是 node 模块规则,看一下当前目录有没有 node_modules,然后在 node_modules 这个目录里边去寻找 jquery文件夹,又找到这个文件夹下面的package.json找到 'main’字段对应的文件,然后在这个文件找到对应的 jquery.js 文件。

3. 开发服务器(Webpack Dev Server)

  • 作用:实时编译 + 自动刷新

  • 运行机制

    1. 启动 express 服务器
    2. 内存打包(不生成 dist,直接放在内存)
    3. 监听文件变化 → 重新编译 → 通知浏览器刷新

现在是可以进行转换了,但是该怎么运行呢,不能说每写一行代码就去运行一个命令 npm run build 把 dist 在新的工程打开把页面运行出来。能不能一边写代码一边自动运行,在 webpack 中使用的办法就是使用开发服务器

运行命令 npm run serve,运行之后会给地址。点击打开就运行出来了,就不用再去先打包然后再用 VScode 去打开这个打包结果再运行。

开发服务器(webpack serve)是由 webpack-dev-server(是webpack 的一个库) 启动的,webpack-dev-server 里面又依赖了 express 。

当我们运行 webpack serve 的时候,它会利用 webpack-dev-server 启动一个开发服务器,与此同时它会去进行打包,相当于帮我们运行了一个 npm run build,只不过这次打包是在内存里边完成,并不会把打包的结果形成文件,在内存中形成打包结果。

然后控制台会给一个提示,让去访问哪一个地址,当访问地址时就会打开浏览器,浏览器会自动的出现这个地址,由浏览器去访问开发服务器,于是浏览器向开发服务器发送请求,然后开发服务器会从内存中的打包结果中去拿到一个页面(index.html),把页面响应给浏览器。浏览器就可以看到页面了,浏览器拿到页面之后就要去渲染页面了,渲染页面的工程中会去继续请求 JS、CSS,开发服务器又回去内存中的打包结果取出相应的 JS、CSS相应给浏览器,这样一来浏览器就把整个页面运行出来了。

这就是整个过程,省略了手动的去打包,手动的去运行浏览器的过程。

这样还能实现源码变化后自动刷新的功能。是因为 webpack serve 还有个功能,它可以监听文件的变化,当文件发生变化时,它会触发重新打包,也就是说更改了内存中的打包结果。光更改没用,还得让浏览器刷新,一刷新就要重新请求,重新请求得重新拿打包结果,就拿到了新的打包结果,相应的就是新的内容。

4. 文件指纹与源码地图

(1)文件指纹(Hash)

  • 作用:确保内容不变时用缓存,内容变化时立即更新
  • 示例main.a3b4c5.js(哈希值随内容变化)

打包的 js 或 css 名称奇奇怪怪的字母数字是文件指纹,其实就是哈希值的前几位,会随着源码的内容的变化而变化的。文件指纹既可以保证文件内容没变时一直使用缓存结果,也可以保证内容变化之后立即使用最新的结果。

2)源码地图(Source Map)

  • 作用:调试时映射回原始代码(而非打包后的代码)
  • 文件.map 文件(关联 bundle.js 和源码)

源码地图:打包后’.map’后缀的,是可以让我们更好的去调试,如果没有源码地图,我们去调试时开发者工具打断点显示的代码是打包之后的代码而不是源码,源码地图让打包后的代码和源码相对应。

5. 脚手架:工程化的最后一环

vue-cli 、 vite 、 cra 、umijs 等等

虽然有了构建工具,这些目录结构的安排得自己去组织,构建工具里面的配置得一行一行去写,各种具体的插件得自己去安装。这时候就希望有一个工具能帮我们把这些给做了,这个工具就是脚手架,脚手架是用来干什么的,就是来搭工程的。
  • 为什么需要脚手架?

    • 构建工具配置复杂(Webpack 配置、Babel、Loader)
    • 项目结构标准化(如 Vue/React 官方推荐目录)
  • 核心功能

    1. 命令行交互(选择框架、配置项)

    2. 生成标准化工程模板(预置 webpack.config.jsbabelrc 等)

    根据你的选择,它给你提供一个工程结构,那些依赖帮我们处理好,配置帮我们考虑好

    1. 集成最佳实践(如 Vue CLI 默认支持 SassRouter

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

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

相关文章

数字化生产管理系统设计

下面提供一个基于Python的数字化管理系统框架,使用现代技术栈实现。这个系统将包含设备监控、故障管理、装配配套表生成、生产计划管理等功能。系统架构数字化生产管理系统 ├── 设备监控模块 ├── 故障管理模块 ├── 产品装配管理模块 ├── 生产计划管理模…

【vue】创建响应式数据ref和reactive的区别

目录 1、所谓响应式数据 2、ref创建基本类型响应式数据 3、reactive创建对象类型响应式数据 4、ref定义对象类型响应式数据 5、总结:ref和reactive对比 6、补充:toRefs与toRef 1、所谓响应式数据 所谓响应式数据就是,在vue页面中&#…

YOLO12 改进、魔改|直方图 Transformerm模块HTB ,通过动态范围特征分组、针对性注意力与多尺度融合,提高对遮挡以及多尺度目标的关注能力

在恶劣天气(如雨、雪、雾)下的图像恢复任务中,传统 Transformer 模型为降低计算量,常将自注意力限制在固定空间范围或仅在通道维度操作,导致难以捕捉长距离空间特征,尤其无法有效处理天气退化像素&#xff…

涉水救援机器人cad【12张】三维图+设计书明说

涉水救援机器人设计 摘 要 随着城市化进度的加快,各种水上游乐设备的增多,水上灾害和溺水事件频繁发生,水上救援任务困难重重,特别是在一些水流湍急的环境下进行救援。传统的水上救援工作比较缓慢,大多数是通过投射救…

电子病历:现代HIS系统不可或缺的核心组成部分

一、电子病历在 HIS 系统中扮演了一个什么角色?电子病历在医院信息系统(HIS)中扮演着核心、基础且不可替代的角色,可以说是整个HIS系统的临床信息中枢和业务驱动引擎。它的重要性体现在以下几个方面:1、临床诊疗活动的核心载体&a…

【深度学习】通俗易懂的基础知识:指数加权平均

一、什么是指数加权平均? 指数在数学中表示一个数的幂次运算(如aⁿ中的n),而在统计学中特指随时间变化的几何衰减系数,加权指对不同数据赋予不同权重,使重要数据对结果产生更大影响。指数加权平均指是一种时…

c++-list

C-list std::list是C标准模板库(STL)提供的双向链表容器&#xff0c;它提供了高效的插入和删除操作&#xff0c;特别适合频繁修改的序列。定义在 <list> 头文件中&#xff0c;属于 std 命名空间。该类的接口与常规容器接口基本一致。 模板原型&#xff1a; template <…

【笔试真题】2024秋招京东后端开发岗位-第一批笔试

31.牛牛与切割机 有一个序列 a1,a2,...,ana_1,a_2,...,a_na1​,a2​,...,an​ &#xff0c; 牛牛将对这个序列切割一刀&#xff08;划分分成两个不相交的非空序列&#xff0c;一个序列为 a1,...,apa_1,...,a_pa1​,...,ap​&#xff0c;另一个序列为 ap1,...,ana_{p1},...,a_na…

【整数转罗马数字】

思路计算数字的位数&#xff1a; 通过 while(x) 循环计算输入数字 num 的位数 n。提取各位数字&#xff1a; 将数字 num 的每一位分解并存储到 nums 数组中&#xff0c;顺序为从高位到低位。罗马数字映射&#xff1a; 使用固定数组 Roman 存储罗马数字符号&#xff1a;Roman {…

spring Scheduled注解详解

spirng Scheduled注解详解 用于标记需要安排执行的方法的注解。必须指定 cron、fixedDelay 或 fixedRate 中的恰好一个属性。 被标注的方法必须不接受任何参数。它通常会具有 void 类型的返回值&#xff1b;如果不是这样&#xff0c;那么在通过调度器调用该方法时&#xff0c;返…

新升级超值型系列32位单片机MM32G0005

灵动微推出的新型MM32G0005系列基于ArmCortex - M0内核&#xff0c;具备高可靠性、低功耗、高性价比等特性。Flash升级至64KB&#xff0c;SRAM为4KB&#xff0c;还有1KB Data Flash。Flash全温擦写次数超过10万次。采用24Pin封装&#xff0c;最多有22个IO。QFN20和TSSOP20封装与…

Spark SQL 的详细介绍

Spark SQL 是 Apache Spark 生态系统中用于处理结构化数据的模块&#xff0c;它将 SQL 查询与 Spark 的分布式计算能力相结合&#xff0c;提供了一种高效、灵活的方式来处理结构化和半结构化数据。以下是对 Spark SQL 的详细介绍&#xff1a;1. 核心定位与优势结构化数据处理&a…

【FreeRTOS】空闲任务与钩子函数原理、实现与功能详解

一、FreeRTOS空闲任务概述FreeRTOS中的空闲任务(Idle Task)是系统自动创建的一个特殊任务&#xff0c;具有最低优先级(优先级0)。当没有其他更高优先级的任务运行时&#xff0c;调度器就会运行空闲任务。空闲任务的主要功能系统资源回收&#xff1a;自动清理被删除任务的内存和…

imx6ull-驱动开发篇6——Linux 设备树语法

目录 前言 设备树 设备树概念 DTS、 DTB 和 DTC DTS 语法 .dtsi 头文件 设备节点 /根节点​​ 节点命名与标签 节点层次结构​ 属性数据类型​ 标准属性 compatible 属性 model 属性 status 属性 #address-cells 和#size-cells 属性 reg 属性 ranges 属性 n…

ansible简单playbook剧本例子2

1. 准备主机组[rootansible-master ansible_quickstart]# vim inventory/hosts[web:vars] ansible_port22 ansible_passwordAdmin123456[web] 192.168.100.1822.准备剧本 vim hello.yml--- - hosts: webremote_user: roottasks:- name: Ping the target hostsping:- name: 获取…

EmpService 和 EmpMapper接口的作用

在这个项目中&#xff0c;EmpService 和 EmpMapper 都定义接口&#xff0c;是基于面向接口编程&#xff08;Interface Oriented Programming&#xff0c;IOP&#xff09;的设计思想&#xff0c;这两种接口在项目中承担着不同的职责&#xff0c;具体说明如下&#xff1a; EmpSer…

【语音技术】什么是动态实体

目录 动态实体的定义和维度 1.1 动态实体的资源 1.2 生效维度 1.2.1 应用级 1.2.2 用户级 1.2.3 自定义级 2. 动态实体的上传及使用 2.1 WebAPI 2.1.1 授权认证 2.1.2 上传资源接口 2.1.2.1 参数说明 2.1.2.2 返回说明 2.1.3 查询打包状态 2.1.3.1 参数说明 2.1.…

STM32学习记录--Day3

今天了解了下I2C&#xff1a;1.I2C电路结构I2C通信示意图&#xff1a;数据传输阶段​​​​主→从模式​​&#xff08;写操作&#xff09;&#xff1a;主机控制SCL时钟&#xff08;把SCL拉低&#xff09;主机向SDA线发送数据&#xff08;每次8位1位ACK&#xff09;​​主←从模…

裂变数据看板:5个核心指标决定活动生死​

数据是裂变活动的“指南针”。本文详解曝光量、转化率、裂变系数等5大核心指标&#xff0c;结合工具与案例&#xff0c;教你用数据驱动活动优化&#xff0c;避免“自嗨式裂变”。​为什么数据是裂变的“生死线”&#xff1f;&#xff08;认知重构&#xff09; 很多企业裂变活动…

iOS 类存储 与 C# 类存储 的差异

C# 中类的代码&#xff08;包括方法、属性等成员&#xff09;的存储机制与 Objective-C 有显著差异&#xff0c;其核心依赖于 ​CLR&#xff08;公共语言运行时&#xff09;的方法表&#xff08;Method Table&#xff09;和虚拟方法表&#xff08;vtable&#xff09;机制&#…