qidao123.com技术社区-IT企服评测·应用市场

标题: 小白必看,总结前端全部主流的构建工具,webpack / vite / roollup / esbui [打印本页]

作者: 王柳    时间: 2024-12-16 08:10
标题: 小白必看,总结前端全部主流的构建工具,webpack / vite / roollup / esbui
前言

本篇文章旨在总结前端常见的构建工具,构建工具是前端工程化中的重要的构成部分。
在实际项目中,我们初始化项目,一样寻常是利用脚手架命令一键天生的,比如说利用 create-vue 初始化 vue 项目的时候,就会默认利用 vite 进行打包,同理利用 vue-cli 的时候就是默认利用webpack进行打包(现在vue已经不推荐利用这种方式了)
  1. pnpm create vue@latest
复制代码

利用脚手架初始化项目简单又方便,很多东西都是现成的,但是这就导致有的时候新手小白不会去认真看打包工具的官网,误以为诸如 webpack 和 vite 等打包工具只能和 vue/ react 等框架绑定利用。
所以我的发起是,可以跟着打包工具的官网,一步一步跟着来详细的学习一下,然后再看你用脚手架初始化的项目,有些东西和设置你才会豁然开朗。
   照旧必要强调一下,学习一个新的工具,首选的学习资料就是该工具的官网。官网的教程,体系而详细,不要一遇到问题就去百度/博客上搜,得到的结果往往是乱七八糟的。
  一、准备工具

1.1 创建仓库

1.1.1 新建 gitee 仓库

   我用 gitee 仓库纯粹是因为不方便科学上网,各人也可以利用 github
  我的仓库地点是 learn-pack-build 
1.1.2 克隆到本地

把你的项目克隆到本地,并新增 .gitignore 文件。
接下来我们就在这个项目中学习各种打包工具。
1.2 前端构建工具总结

前端的构建工具有很多,随着技能的发展有些已经不是主流利用的了,请参考这篇文章,我们照旧重要学习主流用的工具比如 webapck。但是在面试的时候,会问你各种工具的区别,所以照旧要学习一下现在已经不常用的构建工具比较好,如许方便明白,比如 grunt 和 gulp。多学习一点总是没错的。
我们把这些打包工具重要分为两类,一类是基于使命的打包工具(grunt 和 gulp),第二类是基于模块的打包工具(webpack、vite、esbuild、roollup、parcel、browserify),这 8 个的底子用法我们都要学习一下,才气够更好的明白。
   注意,这些工具我们比较风俗称之为构建工具,而不是打包工具,因为打包工具听起来就只是一个简单的打包功能,但是构建工具有很多其他的功能,比如编译、测试、打包、优化、压缩等。照旧称之为构建工具比较好。
  二、基于使命的构建工具

对于基于使命的构建工具重要就相识以下两个就行,相识即可,知道它们为什么是基于使命的就行。
2.1 grunt 

Grunt 是一个基于使命的构建工具,通过设置使命列表,实现前端项目的自动化构建和优化。Grunt 的使命通常是串行执行的,但是可以利用一些插件实现并行执行。
   Grunt 是一个 JavaScript 使命运行器,它利用设置文件(通常是一个名为 Gruntfile.js 的文件)来定义使命。使命通常是一些插件的集合,用于执行各种操作,如文件的合并、压缩、编译等。Grunt 利用相对较多的设置,因此有些开发者大概以为其设置较为冗长。
    注意这个单词的发音【g ruang t】
  

  我们可以跟着 grunt 的官网来学一下到底怎么用,恕我直言,我也没用过这个工具,但是跟着官网一步一步来,是可以很轻易打包一个 js 文件的。
详细代码请参看项目的这个文件夹

重点是 Gruntfile.js 这个文件,在这个文件中【定义使命】—> 【注册使命】可以利用各种插件,grunt 有很多可以利用的插件,总之我们必要明白 grunt 是基于使命的构建工具。
2.2 gulp

 Gulp 也是一个基于使命的构建工具,通过定义一系列使命,可以实现对前端项目的自动化构建,包罗文件的合并、压缩、编译等。Gulp 原生就可以支持使命的串行、并行执行。
   Gulp 则是另一个 JavaScript 使命运行器,它更加基于代码,利用流/管道(stream)来定义使命。开发者通过编写 JavaScript 代码来设置使命,这使得使命的定义更加灵活、简洁。Gulp 的流式处置惩罚方式通常被以为更加直观和易于明白。
   

  g ao p​
  同样的我们跟着 gulp 的官网一步一步来实现一个简单的 demo。
详细代码请参看项目的这个文件夹

2.3 grunt 和 gulp 的区别

   Grunt 和 Gulp 是 JavaScript 的构建工具,它们有很多相似之处,但也存在一些区别,重要集中在以下几个方面:
    总的来说,Grunt 和 Gulp 在实现自动化构建方面都能很好地胜任,但在利用体验、性能和可读性等方面存在一些差异,开发者可以根据本身的偏好和项目需求选择符合的工具。
  好了,基于使命的构建工具就相识 grunt 和 gulp 两个就行。接下来我们要学习一下重头戏,基于模块的构建工具,这个部分我也分为两组。一组是简单的,如 parcel、browserify、roollup、esbuild,一组是较复杂的 webpack 和 vite 
三、简单的基于模块的构建工具

3.1 parcel

Parcel 是一个零设置的前端打包工具,可以自动辨认项目中的文件,并进行相应的打包。它支持多种文件范例,支持热更新,而且具有快速的打包速度。
3.1.1 优点


3.1.2 缺点


   注意这个零设置,给人的感觉好邪乎,好神奇,有这么好的事?不要怕,一切都是纸老虎
  同样的我们跟着 parcel 官网来实现一个简单的 demo,你测试一下会发现确实很快,而且不消任何关于 parcel 的设置文件。
详细代码请参看项目的这个文件夹

   我个人以为,如果你本身写一个学习的项目,不考虑性能,用这个打包是绝佳的首选,简单好上手,零设置真是强推。
  但是如果在实际的项目中,我们就要考虑性能等各种方面,parcel 没有webpack 的社区活跃,功能强大。
parcel 2的官网里面表现也支持插件等,功能比1 强大很多,有爱好可以试着学习一下(我没有爱好~~)


3.2 browserify

 Browserify 答应在前端利用类似于 Node.js 的 require 语法,将模块化的 JavaScript 文件打包成一个文件,以便在欣赏器中利用,它打包后的文件可以直接在html 中引用。
     如果你用过 webpack 等主流的构建工具,你会发现 browserify 有的功能,webpack 也有,因为 browserify 是先提出来的,所以有了webpack 之后就不咋用了。
   看出来了,它的焦点优势就是前端利用类似于 Node.js 的 require 语法
  

   同样的我们跟着 browserify 的官网实现一个简单的demo,看看怎么回事。
详细代码请参看项目的这个文件夹,在这个demo中也是没有设置文件,只是单纯的利用 browserify 打包了一个 js 文件。

四、重要的基于模块的构建工具

这一章节会先容 4 个重要的构建工具,分别是 rollup 、esbuild、webpack、vite,都是我们在开发过程中常用的,这四个构建工具的共同点有
4.1 Rollup

Rollup 是一个 JavaScript 模块打包器,专注于打包 JavaScript 库。它能够进行 Tree-shaking,即删除未利用的代码,以减小打包后的文件体积,常用于构建库(library),特殊是那些专注于 ES6 模块的库。
4.1.1 优点


4.1.2 缺点


   JavaScript 库是啥?
  JavaScript 库通常包含了一系列功能、组件或模块,用于在开发过程中提供特定的功能或解决特定的问题。vue 、react、jquery、lodash 等都属于 javascript库。就是我们利用 npm 命令去安装的都是 js 库。
    在我们的项目中很少单独时候 rollup 打包,但是实际上我们常用的构建工具 vite 他的底层逻辑就是利用了 rollup, 所以照旧有必要学习一下的。
  可以跟着rollup 官网进行学习,rollup 支持设置文件,支持插件,但是不支持热更新。
详细代码请参看项目的这个文件夹。

   如果你在本身学习一个新的技能,也可以是试着利用 rollup 进行打包。不外 rollup 不支持热更新,不如之前说的 parcel 方便。
  4.2 esbuild

esbuild 是一个非常快速的 JavaScript 和 TypeScript 构建工具。它以极快的速度执行构建使命,并支持 Tree-shaking,即消除未利用的代码。esbuild 被计划成一个零设置的工具,但也提供了一些设置选项供用户进行调解。
   esbuild 主打一个快速,但是不支持插件设置,也不支持热更新,他是 2019 年首次发布的,因此它相对较新。所以目前为止有些插件和 esbuild 并不兼容,这也就是 vite 的打包利用了 rollup 而没有用 esbuild 的原因,相对而言 rollup 有更活的插件 api 和底子建立。
  
  一下内容来自 vite 官网
  

  可以跟着esbuild  官网进行学习,esbuild 不支持插件,也不支持热更新。
详细代码请参看项目的这个文件夹。

4.2.1 为啥会快

那么问题来了,问什么esbuild会这么快?
     4.3 vite

 Vite 是一种新型的前端构建工具,特殊计划用于快速开发。Vite 支持利用原生 ES 模块作为开发环境,接纳按需编译的方式,因此在开发过程中能够得到更快的冷启动速度。Vite 集成了 Vue.js,但也可以用于其他框架或库。
常见问题

vite 是我们常用的一个打包工具,有三个问题我们明白了,基本就涵盖了面试题中的问题,分别是
可以点进去看一下详细内容,有一点必要增补一下,这些内容在 vite 的官网实际上都有详细的描述,所以说官网是个好东西,发起各人都去看一遍官网,常看常新。
优点


缺点


接下来照旧实现一个简单的demo,我不利用脚手架,也不消 vue 等框架,就本身写一个。
4.3.1 新建 vite 文件夹

新建 vite 文件夹后,并运行下面命令,跳转到该文件夹下面
  1. cd vite
复制代码
4.3.2 初始化项目

在 vite 文件夹下面,运行下面的命令
  1. npm init -y
复制代码
4.3.3 安装 vite

在 vite 文件夹下面,运行下面的命令
  1. npm i vite -D
复制代码
4.3.4 新建 index.html / index.js

index.html 作为入口文件,并在 index.html 中 引入 index.js
代码如下
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Document</title>
  7. </head>
  8. <body>
  9.     <h1>vite</h1>
  10.     <!-- 以模块的形式导入 index.js -->
  11.     <script type="module" src="./index.js"></script>
  12.     <script>
  13.       // 这里面可以得到name
  14.       console.log('outer name', name)
  15.     </script>
  16. </body>
  17. </html>
复制代码
  1. // index.js
  2. export const name = 'vite'
  3. console.log('inner name', name)
复制代码
4.3.5 设置 dev 命令

在 package.json 中设置
  1. "scripts": {
  2.     "dev": "vite"
  3.   },
复制代码
4.3.6 运行项目

  1. npm run dev
复制代码

4.3.7 重点说明

在 vite 热更新的原理这篇文章,我们提到实用了 websocket 而且,在启动的时候会向客户端注入一个 js 文件。我们来看一下我们的项目中就可以看到 /@vite/client 文件。

可以本身在源代码中检察

4.3.8 增长设置

新增 vite.config.js ,可以根据官网进行各种设置,比如设置启动的端标语。

4.3.9 热更新

上面的这篇文章中提到了,vite 的热更新是利用了 websocket 原理,我们可以正好测试一下,启动项目的 demo,然后修改 html 的内容,会发现有 有些网络哀求,可以本身看一下。

这部分代码在下面这个文件夹中,可以参考。

好了, vite 照旧相对简单的构建工具,我们还剩一个最重要的重头戏 webpack,加油坚持就是胜利。
4.4. webpack

Webpack 是一个模块打包工具,它能够将各种资源(JavaScript、CSS、图片等)打包成一个或多个静态文件,以优化加载性能。
常见问题

webpack 是一个强大的构建工具,重要涉及到的重点问题有
依次看完这 9 个问题,基本上就对 webpack 的理论知识有了一定的相识,现在我们照旧跟着官网动手写一个 demo 吧。
4.4.1 新建 webpack 文件夹

新建 webpack 文件夹后,并运行下面命令,跳转到该文件夹下面
  1. cd webpack
复制代码
4.4.2 初始化项目

在 webpack 文件夹下面,运行下面的命令
  1. npm init -y
复制代码
4.4.3 安装 webpack 等

在 webpack 文件夹下面,运行下面的命令
  1. npm i -D webpack webpack-cli  webpack-dev-server html-webpack-plugin
复制代码
【webpack-cli】Command Line Interface 是 Webpack 的命令行工具,用于在命令行中运行和设置 Webpack。
【webpack-dev-server】是 webpack 的开发服务器,用于开发中的热更新,自动编译等功能。
【html-webpack-plugin】是 webpack 的 html 插件,可以将打包后的 js 等资源文件挂载到 html中,进行预览、开发。
4.4.4 依次新建如下文件


 
都一些简单的代码,其中重要的设置是在 webpack.config.js 中,详细的可以在后面我的仓库中检察。
  1. const HtmlWebpackPlugin = require('html-webpack-plugin')
  2. const path = require('path')
  3. module.exports = {
  4.     mode: 'development',
  5.     entry: {
  6.         // 配置多个入口文件,就会有多个 bundle 捆绑包,就要配置多个output
  7.         main: './main.js',
  8.         login: './login.js'
  9.     },
  10.     output: {
  11.         path: path.resolve(__dirname, 'dist'),
  12.         // 打包后的文件名,因为是多入口,所以要按照入口文件名区分
  13.         // 下面这个 name / chunkhash 都是是固定写法
  14.         // 这里面就涉及到著名的面试题  hash, chunkhash, contenthash 有什么区别,入口文件一般用 chunkhash
  15.         // 可以试下,不同的写法打包后有啥不同的效果
  16.         filename: 'bundle.[name].[hash].js',
  17.         // filename: 'bundle.[name].[chunkhash].js',
  18.         // filename: 'bundle.[name].[contenthash].js'   
  19.     },
  20.     devServer: {
  21.         port: 3001
  22.     },
  23.     plugins: [
  24.         new HtmlWebpackPlugin({
  25.             // 打包后的文件名,这个文件名也可以用  hash, chunkhash, contenthash
  26.             // 但是如果用来哈希值,每次大包的名字不一样,在开发过程中的路由每次就会变不方便我们开发
  27.             filename: 'main.html',
  28.             template: 'main.html', //自己写的html文件
  29.         }),
  30.         new HtmlWebpackPlugin({
  31.             filename: 'login.html', //打包后的文件名
  32.             template: 'login.html', //自己写的html文件
  33.         }),
  34.     ]
  35. }
复制代码
4.4.5 设置运行脚本

 必要在 package.json 中设置开发和打包的脚本

4.4.5 运行项目

运行 npm run dev

访问 http://localhost:3001/login.html

我们在看一下 html 的内容,它把脚本加上了 defer,代表了脚本异步加载,加载之后期待 html 解析后才执行,注意 defer 和 async 的区别,请参考这篇文章。

4.4.5 hash / chunkhash / contenthash

光说不练假把式,我们照旧实际是一下这三个单词的区别吧。
(1)hash

入口文件名,设置为【hash】,然后运行打包命名 npm  run pack,你会发现,全部文件共用一个哈希值。

此时我们只对其中的一个 js 文件 login.js 做出改动,然后重新打包,你会发现重新天生了两个 js 文件,没有改动的 main.js 也重新打包了
所以说 hash, 是全部文件公用一个哈希值,一个文件改动,全部文件都会被重新打包,全部的文件名都会发生改变。
(2)chunkhash

我们再来看一下 chunkhash,起首把 dist 文件夹里面的内容清空,然后打包。

改变 login.js 的内容,重新打包,发现只新打包了 login

我们刚才是改动了 login.js ,现在我们改动 loginInfo.js ,login 引用了 loginInfo,【换言之,loginInfo.js 是 login.js 的依赖】再重新打包。

会发现也会重新打包,所以说,在入口文件的依赖发生改变时,也会重新打包,这是很好明白的,因为 webpack 会根据入口文件依次打包它的依赖文件整合到一个文件中,所以一个依赖发生变化,天生的资源文件肯定发生变化。
chunkhash 就很得当用来打包入口文件,如许每个入口文件以及依赖发生变化,只会重新打包发生变化的文件,而不会影响其他的入口文件。
(3)contenthash

我们修改一下项目,增长一个css 的插件,依次安装下面的插件
  1. npm i css-loader mini-css-extract-plugin -D
复制代码
【css-loader】使得能够在 js 中 import css 文件加载样式
【mini-css-extract-plugin】可以把 js 文件单独打包成一个文件,如果不实用这个插件,就会把 css的内容打包到引用它的 js 文件中。
新增 index.css ,并在 login.js 中引用

此时 webpack.config.js 的设置如下

现在我们设置的是 chunkhash,打包之后内容如下

修改 login.js ,注意修改的是js文件,重新打包,会发现 css 文件也重新打包,但是其实css 的文件没有做任何改动。

所以我们这个时候可以利用 contenthash,再来重复上面的操作。



所以说 contenthash 是只有在内容发生变化的时候,哈希值才会变化,一样寻常用于打包 css 文件,这对于缓存很有用。
三个哈希值的对比,请参考这篇文章。
五、总结

本篇文章全部的代码都在这个仓库中,内容不是很多,所以没有特殊详细的按照步骤提交,不外每个工具的代码都是独立的,有任何问题欢迎在批评区指正。
至此,基本上前端涉及到的流行的构建工具都已经本身写了一个 demo,其中 vite 和 webpack 的尤为重要,webpack 是高频面试题,所以照旧必要好好看一下官网,明白一下原理。
欢迎关注我的专栏《前端工程化体系教程》和《面试题一扫而空》内容连续更新中。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4