前端开发中的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	});

代码解析:

  1. 第01~05行引入Gulp和相关插件。
  2. 第06~10行通过gulp.task('sass', function() {}编译SCSS任务。其中第07行通过gulp.src读取文件,第08行通过pipe管道加载插件,第09行输出CSS文件。
  3. 第11~16行通过gulp.task('scripts', function() {}合并压缩JavaScript文件。
  4. 第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	}

代码解析:

  1. 第01行引入Node.js内置模块path,用于获取文件路径并更改文件的位置。
  2. 第02行引入插件html-webpack-plugin,用于生成一个HTML文件,这个HTML文件用于引用打包后的JavaScript文件。因为JavaScript文件必须放到HTML文件中才可以在浏览器中执行。
  3. 从第04行开始定义module.exports对象,其中包含一些属性,例如entry、output、module、plugins等。
  4. 第05行的entry属性用于指定webpack应该从哪个文件开始,以便创建内部依赖关系图。这里是src下的index.js文件。
  5. 第06行的output属性指定应该在哪里生成打包后的文件以及打包后的文件的名称。output.path用于指定文件存储位置,output.filename用于指定文件名称。
  6. 第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等。
  7. 第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压缩等。

本节选自《React.js+Node.js+MongoDB企业级全栈开发实践》,获出版社和作者授权共享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/254697.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法-动态规划

动态规划算法 应用场景-背包问题 介绍 动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题&#xff0…

【运维笔记】mvware centos挂载共享文件夹

安装mvware-tools 这里用的centos安装 yum install open-vm-tools 设置共享文件夹 依次点击:选项-共享文件夹-总是启用-添加,安装添加向导操作添加自己想共享的文件夹后。成功后即可在文件夹栏看到自己共享的文件夹 挂载文件夹 临时挂载 启动虚拟机&…

视频推拉流EasyDSS互联网直播/点播平台构建户外无人机航拍直播解决方案

一、背景分析 近几年,国内无人机市场随着航拍等业务走进大众,出现爆发式增长。无人机除了在民用方面的应用越来越多,在其他领域也已经开始广泛应用,比如公共安全、应急搜救、农林、环保、交通 、通信、气象、影视航拍等。无人机使…

什么是工业互联网平台?

1.什么是工业互联网平台? 1.1 工业互联网平台的定义 工业互联网平台是一个连接设备与服务、数据与人的跨行业、跨领域的全新工业平台。工业互联网平台利用了互联网、物联网、大数据、AI等技术,集成各类工业设备,不断采集和分析数据&#xff…

数据库动态视图和存储过程报表数据管理功能设计

需求:需要将ERP的报表数据挪到OA中,但是OA表单设计不支持存储过程动态传参,所以需要设计一个系统,可以手动配置,动态显示原本ERP的报表数据,ERP报表是存在数据库的视图和存储过程中 思路:因为E…

Which local search operator best 4 SPVRPTW:or and 2-opt*

这篇文献的研究背景是对车辆路径问题(VRP)的局部搜索移动算子进行测试,其中包括分割配送和时间窗口的车辆路径问题。 VRP涉及根据各种约束条件为客户提供货物的最优路线。当配送的时间窗口和分割配送选项被引入时,问题变得更加复…

Kotlin 笔记 -- Kotlin 语言特性的理解(一)

函数引用、匿名函数、lambda表达式、inline函数的理解 双冒号对函数进行引用的本质是生成一个函数对象只有函数对象才拥有invoke()方法,而函数是没有这个方法的kotlin中函数有自己的类型,但是函数本身不是对象,因此要引用函数类型就必须通过双…

arcgis javascript api4.x加载天地图cgs2000坐标系

需求&#xff1a;arcgis javascript api4.x加载天地图cgs2000坐标系 效果&#xff1a; 示例代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"wid…

vscode使用remote ssh到server上 - Node进程吃满CPU

起因&#xff1a;Node进程吃满CPU 分析 我发现每次使用vscode的remote插件登陆到server后&#xff0c;就会出现node进程&#xff0c;不太清楚干什么用的&#xff0c;但是绝对和它有关。 查找原因 首先找到了这篇文章&#xff0c;解决了rg进程的问题&#xff1a; https://blo…

克服端口顺序影响,使用PCAN实现固定设备ID/通道分配

来源&#xff1a;虹科智能互联 虹科干货 | 克服端口顺序影响&#xff0c;使用PCAN实现固定设备ID/通道分配 原文链接&#xff1a;https://mp.weixin.qq.com/s/Ik2fp9sWyI9MiQOOHO1dCA 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 多设备协同工作是常见的需求…

Mac managing Multiple Python Versions With pyenv 【 mac pyenv 管理多个python 版本 】

文章目录 1. 简介2. 安装2.1 brew 安装 pyenv2.2 脚本安装 3. pyenv 安装 Python4. 卸载 python5. 管理 python 1. 简介 Pyenv 是一个用于管理和切换多个 Python 版本的工具。它允许开发人员在同一台计算机上同时安装和使用多个不同的 Python 版本&#xff0c;而无需对系统进行…

Apache Seatunnel本地源码构建编译运行调试

Apache Seatunnel本地源码构建编译运行调试 文章目录 1. 环境准备1.1 Java环境1.2 Maven1.3 IDEA1.4 Docker环境1.5 Mysql8.0.281.6 其它环境准备 2. 源码包下载3. idea项目配置3.1 项目导入3.2 maven配置3.3 项目JDK配置3.4 项目启动参数配置3.4.1 seatunnel项目启动参数配置3…

SpringBoot+WebSocket

SpringBootWebSocket 1.导入依赖&#xff1a; -- Spring Boot 2.x 使用 javax.websocket-- Spring Boot 3.x 使用 jakarta.websocket<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId&g…

git基础命令(小白适合看)

作者&#xff1a;爱塔居 欢迎大佬指正 1.git add 跟上文件地址 要注意斜杆&#xff0c;然后文件地址就是我们修改文件的地址。 就比如git add xx/xx/xx.x&#xff0c;记得加后缀&#xff0c;然后如果是几个文件&#xff0c;就加空格 例如 git add xx/xx/xx.x yy/yy/yy.y 2.…

机器翻译:跨越语言边界的智能大使

导言 机器翻译作为人工智能领域的瑰宝&#xff0c;正在以前所未有的速度和精度&#xff0c;为全球沟通拓展新的可能性。本文将深入研究机器翻译的技术原理、应用场景以及对语言交流未来的影响。 1. 简介 机器翻译是一项致力于通过计算机自动将一种语言的文本翻译成另一种语言的…

BearPi Std 板从入门到放弃 - 先天神魂篇(3)(RT-Thread I2C设备 读取光照强度BH1750)

简介 使用BearPi IOT Std开发板及其扩展板E53_SC1&#xff0c; SC1上有I2C1 的光照强度传感器BH1750 和 EEPROM AT24C02&#xff0c; 本次主要就是读取光照强度; 主板: 主芯片: STM32L431RCT6LED : PC13 \ 推挽输出\ 高电平点亮串口: Usart1I2C使用 : I2C1E53_SC1扩展板 : LE…

Linux服务器性能优化小结

文章目录 生产环境监测常见专业名词扫盲服务器平均负载服务器平均负载的定义如何判断平均负载值以及好坏情况如果依据平均负载来判断服务器当前状况系统平均负载和CPU使用率的区别 CPU上下文切换基本概念3种上下文切换进程上下文切换线程上下文切换中断上下文切换 查看上下文切…

视频号链接提取器详细使用指南,教你轻松下载号视频!

视频号下载提取器的使用方法会因不同工具而略有差异&#xff0c;但大体上可以按照以下步骤进行操作&#xff1a; 1. 找到一个适合的视频号下载提取器&#xff1a;可以在微信搜一搜中输入关键词“超级短视频去水印解析助手”&#xff0c;选择进入公众号、获取在线视频下载提取工…

12.18_黑马数据结构与算法笔记Java

目录 thinking:orElse? thinking:map.computerifabsent? thinking&#xff1a;subString&#xff1f; 184 哈希表 问2 解释拆分 185 哈希算法 概述 186 哈希算法 Object.hashCode 187 哈希算法 String.hashCode 188 哈希算法 冲突测试 189 哈希算法 MurmurHash 190…

【轮式移动机器人课程笔记3】移动机器人运动学简介

文章目录 写在前面L3 移动机器人运动学简介3.1 运动学概述3.2 研究机器人运动学的意义3.3 机器人运动的描述3.4 机器人正微分运动学3.5 机器人逆微分运动学3.6 总结 写在前面 前两节课介绍了移动机器人、机械手、类型&#xff0c;本节课重点讲解移动机器人运动学相关知识&…