跳至主要內容

06:Webpack

三思原创大约 16 分钟前端vue前端vuejs

Webpack是一个模块化打包工具,可以帮助将不同资源和文件打包合并在一起,还附带CSS预处理等功能。通过安装Node.js和npm来安装webpack,全局和局部安装后即可进行打包操作。使用webpack.config.js文件进行配置,简化打包过程,提高开发效率。

image
image

Vue自学笔记6:Webpack

webpack是用来打包项目的,也可以帮助到后面vueCli(脚手架)的学习

本文章为观看B站codewhy老师教学视频自学vuejs过程中记录的笔记,对视频进行了清晰的整理。
(帮大家节省自己整理笔记的时间啦,剩下的时间一定要去上机实操,多多练习!!)
ps:最全最新Vue、Vuejs教程,从入门到精通_哔哩哔哩_bilibiliopen in new window(附上视频链接!)

五、Webpack详解

1. 认识webpack

1.1 什么是Webpack?

Webpack是模块化打包机 或者 模块打包工具。 首先,认为它是一个工具,帮助我们更好的处理事情的。
打包: 如何理解? 假设我们需要寄快递。我们将许多的物品都放进了一个纸皮箱,然后进行封箱。 这就是打包。 对应到前端开发来说,就是将很多的的 css文件,js文件等“物品”,全都写进一个js文件,而不是在一个html页面通过script,link标签去引入多个静态资源。
模块化: 其实不同的css,不同的js就是一个模块。比如说,一个index.html,通常会有一个index.css,一个index.js,还有其他的css,js。这些不同的文件都可以看做不同的模块。不同的模块有各自的作用。
总结:用这个工具,帮助我们将不同的资源和文件,进行打包,也就是合并在一个文件里面。 但是不仅仅 如此,它还附加了一些更好用的功能。
附加功能

  1. CSS 预处理。将 Less, Sass 编译成css
  2. ES6 语法 转成 ES5 …(等待学习后补充)

作用: 进行重新加载编译。实际就是将浏览器不认识的语法编译成浏览器认识的语法。比如less编译成css,ES6 语法 转成 ES5等等。

减少io请求。通常我们在请求后,会返回一个html到浏览器。

这时,我们如果打开控制台,就会发现在html页面通过script,link等标签引用的静态资源, 浏览器会再次发出请求去获取这些资源。但是webpack的打包,将所有的静态资源都合并好了,减少了io请求。

1.2 和grunt/gulp的对比

grunt/gulp的核心是Task,我们可以配置一系列的task,并且定义task要处理的事务(例如ES6、ts转化,图片压缩,scss转成css) 之后让grunt/gulp来依次执行这些task,而且让整个流程自动化。 所以grunt/gulp也被称为前端自动化任务管理工具。 什么时候用grunt/gulp呢 ? 如果你的工程模块依赖非常简单,甚至是没有用到模块化的概念。 只需要进行简单的合并、压缩,就使用grunt/gulp即可。 但是如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的webpack了。 所以,grunt/gulp和webpack有什么不同呢? grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心。 webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。

2. webpack的安装

webpack的使用需要依赖于node环境(就像Java依赖于JDK一样)

安装步骤:

安装webpack首先需要安装Node.js,Node.js自带了软件包管理工具npm 查看自己的node版本:

全局安装webpack(-g表示全局安装)

局部安装webpack(后续才需要) –save-dev`是开发时依赖,项目打包后不需要继续使用的。

为什么全局安装后,还需要局部安装呢? 在终端直接执行webpack命令,使用的全局安装的webpack 当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack

3. webpack的起步

3.1 准备工作

3.2 js文件的打包

使用打包后的文件:

4. webpack的配置

4.1 webpack.config.js

第一层简化

简化在终端打包的代码(webpack --entry ./src/main.js -o ./dist/bundle.js --mode=development),直接输入webpack就行了 要手动创建一个webpack.config.js文件

CODE_BLOCK_0

4.2 package.json

第二层简化

但是真正做项目时,并不会使用输入webpack来进行打包,而是用npm run build来进行打包(当然这里的build是自定义的)

1) 首先创建package.json包

(这个包一定在一开始创建项目的时候就创建好了,这里讲并不代表到这里才能创建package.json,而是旨在重温如何创建package.json)

通过npm init,为该项目创建package.json文件,用来存储该项目的一些信息

package.json的作用,详见Node的笔记

2) 配置package.json中的scritpts对象

这个还有一个好处:如果不采用这种形式而是老方法,打包时会默认用全局的webpack版本;但如果使用该方法,会首先采用局部的,如果没有再采用全局的

3) 局部安装webpack

目前,我们使用的webpack是全局的webpack,如果我们想使用局部来打包呢? 因为一个项目往往依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题。

所以通常一个项目,都有自己局部的webpack。 这里我们让局部安装webpack3.6.0

CODE_BLOCK_1

--save-dev表示该模块是开发时依赖,仅会在开发时会使用到

5. loader的使用

4.1 什么是loader?

4.2 css文件处理(css-lorder,style-lorder)

1) css-loder

css-loader只负责加载css文件,但不负责将css具体样式嵌入到文档中

安装:

CODE_BLOCK_2

wepack.config.js配置:

CODE_BLOCK_3

注意:style-loader需要放在css-loader的前面。(指的是上面代码段的第七行)
为什么会将style-loader放在前面呢?
答案:这次因为webpack在读取使用的loader的过程中,是按照从右向左的顺序读取的。

2) style-loader

style-loder负责将样式加载到DOM中

安装:

CODE_BLOCK_4

3) .css文件的导入

整理一下逻辑:

  • .css文件被引入到main.js
  • main.js通过webpack的打包到bundle.js中 (其中css-lorder,style-style负责.css的文件)
  • 最后在index.html中只需要引入bundle.js就行

(该部分知识点视频地址:)[https://www.open in new window​**bilibili.com/video/BV15open in new window**​741177Eh?p=80&spm_id_from=pageDriver&vd_source=507e428c4f7818b4cbe408245176625eopen in new window]

4.3 less文件处理(less-lorder)

我们还是先创建一个less文件,依然放在css文件夹中 引入Less

安装less 和 less- loder 我们这里还安装了less,因为webpack会使用less对less文件进行编译

其次,修改对应的配置文件,添加一个rules选项,用于处理.less文件

4.4 图片文件处理(url-lorder)

  1. 首先,我们在项目中加入两张图片:一张较小的图片test01.jpg(小于8kb),一张较大的图片test02.jpeg(大于8kb),待会儿我们会针对这两张图片进行不同的处理
  2. 我们先考虑在css样式中引用图片的情况

  1. 图片处理,我们使用url-loader来处理,依然先安装url-loader

  1. 修改webpack.config.js配置文件:

  1. 再次打包,运行index.html,就会发现我们的背景图片选出了出来。 而仔细观察,你会发现背景图是通过base64显示出来的,这也是limit属性的作用,当图片小于8kb时,对图片进行base64编码
  2. 如果大于8kb,我们需要安装file-loader

再次打包,就会发现dist文件夹下多了一个图片文件

  1. 修改文件名称 我们发现webpack自动帮助我们生成一个非常长的名字,这是一个32位hash值,目的是防止名字重复。 但是,真实开发中,我们可能对打包的图片名字有一定的要求 比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复 所以,我们可以在options中添加上如下选项: img:文件要打包到的文件夹 name:获取图片原来的名字,放在该位置 hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位 ext: 使用图片原来的扩展名

但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确,默认情况下,webpack会将生成的路径直接返回给使用者。但是,我们整个程序是打包在dist文件夹下的,所以这里我们需要在路径下再添加一个dist/

4.5 ES6的语法转成ES5(babel-loader)

  1. 如果希望将ES6的语法转成ES5,那么就需要使用babel。而在webpack中,我们直接使用babel对应的loader就可以了。 npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
  2. 配置webpack.config.js文件

重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法

5. webpack中配置Vue

以前都是通过script标签来引用vue,接下来通过模块化来管理vue

5.1 安装

通过npm安装vue模块:

CODE_BLOCK_5

首先以之前的形式来写vue

在main.js中import vue模块,并且new一个Vue对象

打包项目 – 错误信息 打包过程没有任何错误(因为只是多打包了一个vue的js文件而已)但是运行程序,没有出现想要的效果,而且浏览器中有报错

这个错误说的是我们使用的是runtime-only版本的Vue,什么意思呢? 这里我只说解决方案:Vue不同版本构建,后续我具体讲解runtime-only和runtime-compiler的区别。 所以我们修改webpack的配置,添加如下内容即可:

5.2 el和template区别

正常运行之后,我们来考虑另外一个问题:

  • 如果我们希望将data中的数据显示在界面中,就必须是修改index.html
  • 如果我们后面自定义了组件,也必须修改index.html来使用组件
  • 但是html模板在之后的开发中,我并不希望手动的来频繁修改,是否可以做到呢?

定义template属性:

  • 在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例之后可以管理它其中的内容
  • 这里,我们可以将div元素中的内容删掉,只保留一个基本的id为div的元素
  • 但是如果我依然希望在其中显示的内容,应该怎么处理呢?
  • 我们可以再定义一个template属性,完整代码如下:

如果同时有el和template,template的代码会替代掉index.html中#app中的内容

重新打包,运行程序,显示一样的结果和HTML代码结构

el和template模板的关系是什么呢?

  • 在我们之前的学习中,我们知道el用于指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听等等。
  • 而如果Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。

这样做有什么好处呢?

  • 这样做之后我们就不需要在以后的开发中再次操 index.html,只需要在template中写入对应的标签即可

但是,书写template模块非常麻烦怎么办呢?

  • 没有关系,稍后我们会将template模板中的内容进行抽离。 会分成三部分书写:template、script、style,结构变得非常清晰。

5.3 Vue的终极使用方案

将上面图片中的使用方式进一步的升级

将Vue组件化:

main.js文件:

CODE_BLOCK_6

将Vue模块化:

再升级

在以上代码中可以看出:第3行到第22行其实就是一个对象,那我们就可以将这一段代码封装在app.js文件中(在该文件中再模块化导出),再在main.js中导入即可

app.js文件(将其放置vue文件夹中):

CODE_BLOCK_7

main.js文件:

CODE_BLOCK_8

使用.Vue文件(终极形态):

再升级

使用App.vue文件来代替app.js文件,并记得在main.js文件中导入

App.vue文件:

技巧:vscode中安装vetur扩展,在.vue文件中打<>可以快捷生成.vue文件的框架

main.js文件:

CODE_BLOCK_9

此时npm run build打包时会报错,是因为没有对应的lorder处理.vue文件,需要安装vue-loader和vue-template-compiler

安装vue-loader和vue-template-compiler:

安装:

npm install vue-loader vue-template-compiler --save-dev

  • vue-loader负责加载.vue文件
  • vue-template-compiler负责编译vue

最后修改webpack.config.js的配置文件:

6. plugin的使用

6.1认识plugin

plugin是什么?

  • plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
  • webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。

loader和plugin区别

  • loader主要用于转换某些类型的模块,它是一个转换器。
  • plugin是插件,它是对webpack本身的扩展,是一个扩展器。

plugin的使用过程:

  • 步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
  • 步骤二:在webpack.config.js中的plugins中配置插件。

6.2 添加版权的Plugin(BannerPlugin)

该插件名字叫BannerPlugin,属于webpack自带的插件 按照下面的方式来修改webpack.config.js的文件:

重新打包程序:查看bundle.js文件的头部,看到如下信息

6.3 打包html的plugin(HtmlWebpackPlugin)

在不使用该插件之前,dist文件夹里是没有index.html文件的,但是发布的dist文件夹中必须有该文件

所以需要将index.html文件打包到dist文件夹中,这个时候就可以使用HtmlWebpackPlugin插件 HtmlWebpackPlugin插件可以为我们做这些事情:

  • 自动生成一个index.html文件(可以指定模板来生成)
  • 将打包的js文件,自动通过script标签插入到body中(意思就是:没有该插件时,没打包的index.html文件中需要手动为其通过<script>​标签来引入bundle.js文件。使用该插件后,没打包的index.html文件无需手动引入(就是没有<script src="./dist/bundle.js"></script>​这行代码),该插件会帮助你自动在dist文件夹中的打包后的index.html中自动添加该行代码)

安装HtmlWebpackPlugin插件

  • npm install html-webpack-plugin --save-dev

修改webpack.config.js文件中plugins部分

这里的template表示根据什么模板来生成index.html 另外,我们需要删除之前在output中添加的publicPath属性 否则插入的script标签中的src可能会有问题

6.4 js压缩的Plugin(uglifyjs-webpack-plugin)

我们使用一个第三方的插件uglifyjs-webpack-plugin,并且版本号指定1.1.1,和CLI2保持一致 -npm install uglifyjs-webpack-plugin@1.1.1 --save-dev​ 修改webpack.config.js文件

7 搭建本地服务器(webpack-dev-server)

为解决的问题场景:

之前我们在对页面进行了改动,要查看效果时,需要先webpack打包,然后打开index.html文件,通过浏览器查看效果,十分麻烦.

使用了本地服务器可以免去上面的流程,实时刷新查看修改后的效果

  1. webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果
  2. 不过它是一个单独的模块,在webpack中使用之前需要先安装它
  • npm install --save-dev webpack-dev-server@2.9.1
  1. webpack.config.js文件配置修改如下

  • contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist
  • port:端口号
  • inline:页面实时刷新
  • historyApiFallback:在SPA页面中,依赖HTML5的history模式
  1. 我们可以再配置另外一个scripts:
  • –open参数表示直接打开浏览器

最后在终端通过命令npm run dev就可以实现该功能了(注意你所在的路径是不是你的项目路径)