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

Vue自学笔记6:Webpack
webpack是用来打包项目的,也可以帮助到后面vueCli(脚手架)的学习
本文章为观看B站codewhy老师教学视频自学vuejs过程中记录的笔记,对视频进行了清晰的整理。
(帮大家节省自己整理笔记的时间啦,剩下的时间一定要去上机实操,多多练习!!)
ps:最全最新Vue、Vuejs教程,从入门到精通_哔哩哔哩_bilibili(附上视频链接!)
五、Webpack详解
1. 认识webpack
1.1 什么是Webpack?
Webpack是模块化打包机 或者 模块打包工具。 首先,认为它是一个工具,帮助我们更好的处理事情的。
打包: 如何理解? 假设我们需要寄快递。我们将许多的物品都放进了一个纸皮箱,然后进行封箱。 这就是打包。 对应到前端开发来说,就是将很多的的 css文件,js文件等“物品”,全都写进一个js文件,而不是在一个html页面通过script,link标签去引入多个静态资源。
模块化: 其实不同的css,不同的js就是一个模块。比如说,一个index.html,通常会有一个index.css,一个index.js,还有其他的css,js。这些不同的文件都可以看做不同的模块。不同的模块有各自的作用。
总结:用这个工具,帮助我们将不同的资源和文件,进行打包,也就是合并在一个文件里面。 但是不仅仅 如此,它还附加了一些更好用的功能。
附加功能:
- CSS 预处理。将 Less, Sass 编译成css
- 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.**bilibili.com/video/BV15**741177Eh?p=80&spm_id_from=pageDriver&vd_source=507e428c4f7818b4cbe408245176625e]
4.3 less文件处理(less-lorder)
我们还是先创建一个less文件,依然放在css文件夹中 引入Less
安装less 和 less- loder 我们这里还安装了less,因为webpack会使用less对less文件进行编译
其次,修改对应的配置文件,添加一个rules选项,用于处理.less文件
4.4 图片文件处理(url-lorder)
- 首先,我们在项目中加入两张图片:一张较小的图片test01.jpg(小于8kb),一张较大的图片test02.jpeg(大于8kb),待会儿我们会针对这两张图片进行不同的处理
- 我们先考虑在css样式中引用图片的情况
- 图片处理,我们使用url-loader来处理,依然先安装url-loader
- 修改webpack.config.js配置文件:
- 再次打包,运行index.html,就会发现我们的背景图片选出了出来。 而仔细观察,你会发现背景图是通过base64显示出来的,这也是limit属性的作用,当图片小于8kb时,对图片进行base64编码
- 如果大于8kb,我们需要安装file-loader
再次打包,就会发现dist文件夹下多了一个图片文件
- 修改文件名称 我们发现webpack自动帮助我们生成一个非常长的名字,这是一个32位hash值,目的是防止名字重复。 但是,真实开发中,我们可能对打包的图片名字有一定的要求 比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复 所以,我们可以在options中添加上如下选项: img:文件要打包到的文件夹 name:获取图片原来的名字,放在该位置 hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位 ext: 使用图片原来的扩展名
但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确,默认情况下,webpack会将生成的路径直接返回给使用者。但是,我们整个程序是打包在dist文件夹下的,所以这里我们需要在路径下再添加一个dist/
4.5 ES6的语法转成ES5(babel-loader)
- 如果希望将ES6的语法转成ES5,那么就需要使用babel。而在webpack中,我们直接使用babel对应的loader就可以了。
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
- 配置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文件,通过浏览器查看效果,十分麻烦.
使用了本地服务器可以免去上面的流程,实时刷新查看修改后的效果
- webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果
- 不过它是一个单独的模块,在webpack中使用之前需要先安装它
-
npm install --save-dev webpack-dev-server@2.9.1
- webpack.config.js文件配置修改如下
- contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist
- port:端口号
- inline:页面实时刷新
- historyApiFallback:在SPA页面中,依赖HTML5的history模式
- 我们可以再配置另外一个scripts:
- –open参数表示直接打开浏览器
最后在终端通过命令npm run dev就可以实现该功能了(注意你所在的路径是不是你的项目路径)