前端开发中的webpack打包工具
前端技术发展迅猛,各种可以提高开发效率的新思想和框架层出不穷,但是它们都有一个共同点,即源代码无法直接运行,必须通过转换后才可以正常运行。webpack是目前主流的打包模块化JavaScript的工具之一。
本章主要涉及的知识点有:
l 什么是webpack
l webpack的作用
l webpack的配置
l webpack-dev-server
以前,一个网站可能只是由几个HTML和CSS文件构成,在某些情况下可能还有一个或几个JavaScript文件。但随着前端技术的发展,这一切都被改变。
整个开发社区一直致力于改善用户和开发人员在使用和构建JavaScript/Web应用程序方面的整体体验。因此,在项目中引入了许多新的库和框架。
一些设计模式也随着时间的推移而演变,为开发人员提供了一种更好、更强大但非常简单的编写复杂JavaScript应用程序的方法。网站不再只是一个包含几个文件的程序包,随着JavaScript模块的引入,编写封装的小块代码成为一种新趋势。但随之而来的是网站代码的体积越来越大,而且JavaScript版本不断升级,新的API层出不穷,在开发人员编写的代码类型和浏览器能够理解的代码类型方面也存在巨大差异。开发人员必须使用大量被称为polyfills的辅助代码,以确保浏览器能够解析其中的代码。
为了解决这些问题,开发了一系列构建工具,它们各有优缺点。由于前端工程师很熟悉JavaScript,Node.js又可以满足所有构建需求,因此大多数构建工具都是用Node.js开发的。
1. Grunt
Grunt是一个任务执行者,它有大量现成的插件封装了常见的任务,也能管理任务之间的依赖关系,自动化地执行依赖的任务。每个任务的具体执行代码和依赖关系写在配置文件Gruntfile.js里,代码如下:
module.exports = function(grunt) {grunt.initConfig({uglify: {app_task: {files: {'build/app.min.js': ['lib/index.js', 'lib/test.js']}}}, watch: {another: {files: ['lib/*.js'],}}});grunt.loadNpmTasks('grunt-contrib-uglify');grunt.loadNpmTasks('grunt-contrib-watch');grunt.registerTask('dev', ['uglify','watch']);
};
其中,uglify和watch都是插件,分别用于压缩和监听自动刷新,grunt.loadNpmTasks用于加载插件;grunt.registerTask用于执行任务。在项目根目录下执行命令grunt dev,就会启动JavaScript文件压缩和自动刷新功能。
Grunt的优点是灵活,它可以执行自定义的任务,并且有大量的可复用的插件封装好了常见的构建任务。
Grunt的缺点是集成度不高,要写很多配置后才可以用,无法做到开箱即用。
2. Gulp
Gulp是一个基于流的自动化构建工具,除了可以管理和执行任务之外,还支持监听文件、读写文件。Gulp被设计得非常简单,只通过5种方法就可以支持几乎所有的构建场景:gulp.task用于注册一个任务,gulp.run用于执行任务,gulp.watch用于监听文件的变化,gulp.src用于读取文件,gulp.dest用于写文件。
Gulp的最大特点是引入了流的概念,同时提供了一系列常用的插件去处理流,流可以在插件之间传递。Gulp的示例代码如下:
01 var gulp = require('gulp');
02 var jshint = require('gulp-jshint');
03 var sass = require('gulp-sass');
04 var concat = require('gulp-concat');
05 var uglify = require('gulp-uglify');
06 gulp.task('sass', function() {
07 gulp.src('./scss/*.scss')
08 .pipe(sass())
09 .pipe(gulp.dest('./css'));
10 });
11 gulp.task('scripts', function() {
12 gulp.src('./js/*.js')
13 .pipe(concat('all.js'))
14 .pipe(uglify())
15 .pipe(gulp.dest('./dist'));
16 });
17 gulp.task('watch', function(){
18 gulp.watch('./scss/*.scss', ['sass']);
19 gulp.watch('./js/*.js', ['scripts']);
20 });
代码解析:
- 第01~05行引入Gulp和相关插件。
- 第06~10行通过gulp.task('sass', function() {}编译SCSS任务。其中第07行通过gulp.src读取文件,第08行通过pipe管道加载插件,第09行输出CSS文件。
- 第11~16行通过gulp.task('scripts', function() {}合并压缩JavaScript文件。
- 第17~20行通过gulp.task('watch', function() {}监听文件的变化。
Gulp的优点是好用又不失灵活,既可以单独完成构建,也可以和其他工具搭配使用。其缺点和Grunt类似,集成度不高,要写很多配置后才可以用,无法做到开箱即用。
可以将Gulp看作Grunt的加强版。相对于Grunt,Gulp增加了监听文件、读写文件、流式处理的功能。
3. webpack
webpack是一个打包模块化JavaScript的工具,在webpack里一切文件皆模块,通过Loader转换文件,通过Plugin注入钩子,最后输出由多个模块组合成的文件。webpack专注于构建模块化项目。
webpack具有很大的灵活性,通常在项目中编写webpack.config.js配置处理文件的方式,示例代码如下:
module.exports = {entry: './app.js',output: {filename: 'bundle.js'}
}
其中,entry是所有模块的入口,webpack从入口开始递归解析出所有依赖的模块;output将入口所依赖的所有模块打包成一个bundle.js文件并输出。
webpack专注于处理模块化的项目。通过webpack,现在使用React、Vue、Angular等搭建的项目能做到开箱即用、一步到位,并且可以通过Plugin扩展很多功能。webpack社区庞大而活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展。
简单来说,webpack会遍历项目中的所有文件,如JavaScript、CSS、SCSS、图片、模板等,并创建它们的依赖关系图,该依赖关系图用于描述各个模块之间的依赖关系。根据依赖关系图,对项目中的各模块进行组合和打包,形成一个bundle.js文件,在这个文件中可以很容易地插入HTML文件并用于应用程序。
webpack在打包的同时还会对各文件进行编译。把浏览器不能识别的语法(例如ES 6的语法、Node.js的模块化、Sass)编译成CSS,将TypeScript编译成JavaScript等,转换成浏览器能够识别的语法。
webpack在打包时可以根据配置对代码进行压缩、优化,以减小网络传输过程中文件的体积。最典型的做法是把所有变量名都精简为一个字母,所有的换行符和缩进都去掉。如图8.1所示是webpack打包后的JS文件。
webpack的功能还有很多,例如代码分割、自动刷新等。代码分割就是提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。自动刷新是指监听本地源代码的变化,自动重新构建、刷新浏览器。
webpack官方网站首页中的一张图片形象地展示了webpack的作用,如图8.2所示。
目前,随着单页应用的流行,大多数团队在开发新项目时会采用“模块化+新语言+新框架"的方式。webpack可以为这些模块化项目提供一站式的解决方案、良好的生态链和维护团队,从而提供良好的开发体验并保证项目质量。
webpack的配置项很多,具体可以参考官方网站文档(https://webpack.js.org/concepts/)。本节介绍几个重要且常用的配置项。
在对webpack进行配置之前,首先要安装webpack。在终端输入如下代码:
npm install webpack webpack-cli --save-dev
webpack-cli是一个用来在命令行中运行webpack的工具,可以用来处理命令行参数。
通常在项目根目录下增加webpack.config.js文件,在该文件中编写代码进行webpack的配置。例如,在webpack.config.js文件中添加以下代码:
01 const path = require('path');
02 const HtmlWebpackPlugin = require('html-webpack-plugin');
03
04 module.exports = {
05 entry:'./src/index.js',
06 output:{
07 path: path.join(__dirname, '/dist'),
08 filename: 'bundle.js'
09 },
10 module: {
11 rules: [
12 {
13 test: /\.(js|jsx)$/,
14 exclude: /node_modules/,
15 use: {
16 loader: 'babel-loader'
17 }
18 }
19 ]
20 },
21 plugins: [
22 new HtmlWebpackPlugin({
23 template: './src/index.html'
24 })
25 ]
26 }
代码解析:
- 第01行引入Node.js内置模块path,用于获取文件路径并更改文件的位置。
- 第02行引入插件html-webpack-plugin,用于生成一个HTML文件,这个HTML文件用于引用打包后的JavaScript文件。因为JavaScript文件必须放到HTML文件中才可以在浏览器中执行。
- 从第04行开始定义module.exports对象,其中包含一些属性,例如entry、output、module、plugins等。
- 第05行的entry属性用于指定webpack应该从哪个文件开始,以便创建内部依赖关系图。这里是src下的index.js文件。
- 第06行的output属性指定应该在哪里生成打包后的文件以及打包后的文件的名称。output.path用于指定文件存储位置,output.filename用于指定文件名称。
- 第10~20行的module指定需要哪些loader。loader指定webpack应该怎样处理特定类型的文件。注意,webpack默认只理解JavaScript和JSON类型的文件,对于项目中使用的其他类型文件或语言,例如PNG、JPG、GIF格式的图片文件或者SCSS、LESS文件,需要在这里加载相应的loader插件进行处理。此处用正则表达式匹配所有后缀是.js或.jsx的文件,且排除/node_modules/下的文件,使用babel-loader对这些文件进行编译处理。还有很多别的loader插件,例如处理CSS和SCSS文件的style-loader、css-loader、sass-loader,处理图片的url-loader等。
- 第21~25行的plugins是插件属性,用于扩展webpack的功能。这里使用html-webpack-plugin插件将src/index.html作为模板文件,所有打包后的文件都将自动放入该HTML文件中。html-webpack-plugin插件还有更多的配置,具体可以参考官方文档。插件还有mini-css-extract-plugin,用于将CSS提取到单独的文件中,即为每个包含CSS的JavaScript文件创建一个CSS文件,terser-webpack-plugin用于压缩JavaScript文件。
最后,要处理ES 6代码。ES 6是2015年发布的JavaScript语言标准,它引入了新的语法和API,例如class、let、for...of、promise等,但是这些JavaScript新特性只被最新版本的浏览器支持。低版本浏览器并不支持。因此,低版本浏览器需要一个转换工具,把ES 6代码转换成浏览器能识别的代码。Babel就是这样的一个工具,它是JavaScript语法的编译器。
Babel工具在使用之前需要先进行配置。
首先在项目根目录下创建一个.babelrc文件,它是一个JSON格式的文件,用来保存Babel工具的配置。webpack中的babel-loader加载后会从项目根目录下的.babelrc文件中读取配置。
在.babelrc配置文件中,主要是对预设(presets)和插件(plugins)进行配置。.babelrc配置文件一般如下:
{"presets": ["es2015","react"]
}
其中,presets属性告诉Babel要转换的源代码使用了哪些新的语法特性,它是一组Plugins的集合。上面的代码表示先用React转换,然后用ES 2015(ES 6)转换。
以上配置中用到的loader或plugins,如果不是webpack内置的,那么在使用前需要先安装,例如编译CSS和SCSS文件的loader,使用npm install css-loader style-loader sass-loader --save-dev进行安装。
webpack配置好以后,可以在package.json文件中增加如下代码:
"scripts": {"dev": "webpack --config webpack.config.js"
},
在scripts属性中,npm允许通过名称引用本地安装的Node.js包。上面的代码表示在开发dev模式下运行webpack,在终端命令行中输入npm run dev时执行webpack --config webpack.config.js。
在实际项目中,需要根据特定情况使用不同的配置文件,例如,开发时执行webpack.dev.config.js;当需要打包部署到生产环境时,执行webpack.prod.config.js。这些webpack文件的配置项也要根据用途进行不同的配置,例如开发环境时需要配置webpack-dev-server,但是生产环境时需要配置CSS、JS压缩等。
到目前为止,每次进行更改都需要重新构建代码。对于开发中频繁修改代码并且要即时查看页面情况来说,这是非常麻烦且影响开发效率的。
webpack提供了一个实时重新加载的Web服务器——webpack-dev-server,它可以自动构建和刷新页面。可以在终端输入下面的代码安装:
npm install webpack-dev-server --save-dev
安装后需要更新package.json中script的dev,代码如下:
"dev": "webpack serve --mode development"
在webpack.config.js中增加以下代码:
devServer: {hot: true,port: 8080,compress: true,headers: {'Access-Control-Allow-Origin': '*'},proxy: {'/api': {target: 'http://localhost:3000',pathRewrite: { '^/api': '' },},}
}
代码解析:
- Hot:true表示启用模块热替换,该功能会在应用程序运行过程中,替换、添加或删除模块,而无需重新加载整个页面,可以加快开发速度。
- port指定监听请求的端口号。
- compress:true表示启用gzip压缩。
- headers表示为所有响应添加headers。
- 'Access-Control-Allow-Origin':'*'表示允许所有域名跨域访问。
- proxy用来设置代理。上面的代码中,假如有接口/api/users,它实际上会将请求代理到http://localhost:3000/users。
pathRewrite表示将接口中的/api替换为空。
本节选自《React.js+Node.js+MongoDB企业级全栈开发实践》,获出版社和作者授权共享。
相关文章:

前端开发中的webpack打包工具
前端技术发展迅猛,各种可以提高开发效率的新思想和框架层出不穷,但是它们都有一个共同点,即源代码无法直接运行,必须通过转换后才可以正常运行。webpack是目前主流的打包模块化JavaScript的工具之一。 本章主要涉及的知识点有&am…...
Mybatis配置-数据库厂商标识(databaseIdProvider)
MyBatis可以根据数据库供应商执行不同的语句。多数据库供应商支持是基于映射语句的databaseId属性。MyBatis将加载所有没有databaseId属性或具有与当前数据库匹配的databaseId属性的语句。如果找到具有和不具有databaseId的相同语句,则后者将被丢弃。要启用多供应商…...

【Java】使用递归的方法获取层级关系数据demo
使用递归来完善各种业务数据的层级关系的获取 引言:在Java开发中,我们通常会遇到层层递进的关系型数据的获取问题,有时是树状解构,或金字塔结构,怎么描述都行,错综复杂的关系在程序中还是可以理清的。 这…...

工业6轴机械臂运动学逆解(解析解)
工业6轴机械臂运动学逆解(解析解) 通常工业机械臂采用6旋转轴串连的形式,保证了灵活性,但为其运动学逆解(即已知机械臂末端的位姿 P P P,求机械臂各个旋转轴的旋转角)带来了较大的困难ÿ…...

管理类联考——数学——真题篇——按题型分类——充分性判断题——蒙猜A/B
老规矩,看目录,平均3-5题 文章目录 A/B2023真题(2023-19)-A-选项特点:两个等号;-判断需联立的难易:难,看着感觉需要联立,所以判断联立需要有理论支撑,不然还…...
为什么GRU和LSTM能够缓解梯度消失或梯度爆炸问题?
1、什么是梯度消失(gradient vanishing)? 参数更新过小,在每次更新时几乎不会移动,导致模型无法学习。 2、什么是梯度爆炸(gradient exploding)? 参数更新过小大,破坏了…...
【力扣100】146.LRU缓存
添加链接描述 class DLinkedNode:def __init__(self, key0, value0):self.key keyself.value valueself.prev Noneself.next Noneclass LRUCache:def __init__(self, capacity: int):self.cache dict()# 使用伪头部和伪尾部节点 self.head DLinkedNode()self.tail D…...

【Vue中给输入框加入js验证_blur失去焦点进行校验】
【Vue中给输入框加入js验证_blur失去焦点进行校验】 通俗一点就是给输入框加个光标离开当前文本输入框时,然后对当前文本框内容进行校验判断 具体如下: 1.先给文本框加属性 blur“validatePhoneNumber” <el-input v-model“entity.telephone” blur…...

vue3项目引入电子签名(可横屏竖屏)
实现效果:(左边横屏,右边竖屏) 前言:【使用开源项目smooth-signature 实现签名的功能。Gitee 地址是 :GitHub - linjc/smooth-signature: H5带笔锋手写签名,支持PC端和移动端,任何前…...
mysql中count(*)、count(1)、count(主键)、count(字段)的区别
文章目录 count函数的语义count(主键)count(1)count(*)count(字段)替代方案explain或者show table status中间表或者其他数据库计数 以下分析都是基于 select count(?) from table 这个语句来分析,不带过滤条件。 count函数的语义 count() 是一个聚合函数&#x…...
Nginx生成自签名证书从而添加域名的HTTPS访问
数字证书 ## 原理参考 https://mysticaldream.github.io/2023/05/certificate/## https://blog.csdn.net/m0_52440465/article/details/130713591 简介 数字证书是由证书颁发机构(CA)签名并颁发的电子文件,用于建立网络连接的身份认证和加密通信。SSL 证书是数字证书的一种。…...

无框架Java转go语言写http与tcp请求
项目地址 https://github.com/cmdch2017/http_tcpServer 项目结构 如何快速上手 http篇 1、controller包就相当于RestController,这里返回了一个Person对象,当你需要新建一个接口时,再新写一个func仿照下面的方法就行了 package control…...

【Git】Git基本操作
文章目录 Git 是什么Git 的优点Git 安装Linux UbuntuLinux CentOsWindows Git 基本操作1. 创建 Git 本地仓库2. 配置 Git3. Git工作区、暂存区和版本库4. 添加文件5. 查看 .git 文件6. 修改文件7. 版本回退 Git 是什么 Git是一个免费的、开源的分布式版本控制系统,…...

JavaSE学习笔记 Day20
JavaSE学习笔记 Day20 个人整理非商业用途,欢迎探讨与指正!! 上一篇 文章目录 JavaSE学习笔记 Day20十七、数据结构与算法17.1算法17.1.1冒泡排序17.1.2选择排序17.1.3插入排序17.1.4三个排序的区别 17.2顺序表17.2.1顺序表代码实现17.2.2顺…...

【蓝桥杯选拔赛真题52】python空调模式 第十四届青少年组蓝桥杯python 选拔赛比赛真题解析
目录 python空调模式 一、题目要求 1、编程实现 2、输入输出...

Android Studio: 解决Gradle sync failed 错误
文章目录 1. 前言2. 错误情况3. 解决办法3.1 获取gradle下载地址3.2 获取gradle存放目录3.3 替换并删除临时文件3.4 触发Try Again 4. 执行成功 1. 前言 今天调试项目,发现新装的AS,在下载gradle的过程中,一直显示连接失败,Gradl…...
【手写数据库】从零开始手写数据库内核,行列混合存储模型,学习大纲成型了
目录 专栏内容: 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以…...

机器学习中的一些经典理论定理
PAC学习理论 当使用机器学习方法来解决某个特定问题时,通常靠经验或者多次试验来选择合适的模型、训练样本数量以及学习算法收敛的速度等。但是经验判断或多次试验往往成本比较高,也不太可靠,因此希望有一套理论能够分析问题难度、计算模型能…...

c语言:成本100元,40%的利润怎么计算|练习题
一、利润的计算公式: 利润售价-成本 售价成本/(1-利润率) 二、用c语言代码表示为: 如图: 三、计算源代码【带注释】 #include <stdio.h> int main() { float cost;//成本变量 int prof_rate;//利润率变量 float price;//…...

【Python必做100题】之第二十二题(复制列表)
题目:将一个列表的数据复制到另一个列表中 重点:确保复制到位要导入copy方法进行深度复制 代码如下: #将一个列表的数据复制到另一个列表中 import copy list [1,2,3,4] print(list) list1 copy.copy(list) list[0] 30 print(list) pri…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...