webpack学习笔记(踩坑笔记)

认识webpack

webpcak是基于JS应用的前端模块化打包工具,强调模块化(核心)打包
流行打包工具:webpack,grunt,gulp

特别是IE

前端模块化规范方案:AMD, CMD, CommonJS(node), ES6(不需要底层支撑,可以直接用)

前端模块化概念:
在ES6之前,我们如果想进行模块化开发,必须借助于其他工具进行模块化开发,在我们完成项目后,还需处理模块间的依赖关系,最终进行整合打包。

而webpack的出现,使这些问题迎刃而解,webpack的核心是让我们尽可能的进行模块化开发,与此同时,还会帮助我们处理模块间的依赖关系。

此外,webpack不仅限于对.js文件的模块化,例如css,png,jpg,json等在webpack中都可以当做模块来使用。

打包的概念:理解了webpack可以帮助我们进行模块化开发,并且能够处理模块间的各种复杂关系,打包的概念就很容易理解了。

打包,就是将webpack中的各种资源模块进行打包合并成一个或者多个包(Bundle)

于此同时,在打包过程当中,webpack还会对资源进行处理,例如一些压缩图片的操作等,将scss转成浏览器能识别的css,将ES6相关语法转成目前浏览器高度普遍支持的ES5语法,将TypeScript转成JS等等操作。

webpack的安装

首先我们得明确一点,webpack能够正常运行必须依赖Node环境来实现。

与此同时,node环境为了可以正常执行各种各样的的代码语言,其中必须必须包含各种依赖的包,也就是常说的npm工具(node packages manger)。

为了方便理解,我们可以把npm工具看成手机上的应用商店,你想下载什么软件,就直接去找,然后点击下载,npm工具使用的原理也是如此大同小异,只需要相关的指令加上对应的包名即可下载到本地项目文件夹。

安装操作
安装webpack之前首先需要安装node.js,因为node.js自带了软件包管理工具npm

查看自己的node版本号和npm版本号:

node -v
npm -v

全局安装webpck(版本号:3.6.0,vue cli2稳定支持版本)

npm i [email protected] -g
语法糖解释:
i选项是install的缩写(安装的意思)
-g 全局安装(global的缩写)
@后跟版本号

局部安装webpack

cd 进入相对于的目录
npm i [email protected] --save-dev
关于--save-dev的解释:它是开发时依赖,项目打包完成后,不需要继续使用。

查看webpack版本号:

webpack --version

webpack全局安装和局部安装的区别:
选择全局安装可以在任何一款流行的代码编译工具的终端打开,包括cmd窗口打开,这些都是全局安装的。

webpack的起步及基本使用体验。

新建2个基本目录结构:



我们要做的就是通过webpack工具将src下面的代码打包放入dist进行发布。

我们开发代码一般在源码目录下进行。

首先在根目录新建一个index.html,有一个基本骨架即可,切记切记不需要写外部引入.js文件,因为我们使用commonjs和ES6规范写的,浏览器是不认识。
在src目录下新建一个main.js文件作为程序的主要入口文件。


1.使用CommonJS模块化规范演示写代码,然后用webpack工具打包。

math.js文件作为导出口,main.js作为导入口。


image.png

打开VSC终端,将入口文件main.js进行打包,而math.js是作为导出口,是不需要我们进行同样的操作的,因为webpack会自动帮我们处理main.js所依赖关系的文件和包。


关于在VSC里面检测不到版本号和打包报错,看这篇:
https://www.jianshu.com/p/34470e43503b

通过上述wenbpack指令打包完成后,我们可以看到dist目录下多了一个bundle.js文件。



有了这个bundle.js文件后,我们就可以在Index.html里面用script标签外部引入了。



控制台查看我们CommonJS模块导出导入有没有成功。

2.下面在src目录下新建一个info.js脚本文件,使用ES6模块化规范思想。



再次运行webpack指令。



我们可以看到ES6模块化的控制台输出了。

webpack的配置

上面的webpack都是手动打包代码,每次写代码,都要输入一行长长的命令进行更新,如何做到智能打包呢?只要简单输入一个webpack就可以打包了,这就涉及到webpack配置了。

新建一个webpack.config.js文件,命名固定。




到这一步,打开VSC的终端,输入npm init





将原来webpack目录下写好的文件统统复制一份放到webpack配置目录下。

打开终端,直接输入webpack,不再需要敲长长的路径指令。



打包成功。

总结:将出口文件和入口文件放进配置文件,就可以直接使用webpack进行打包,更方便了。

将webpack.config.js映射到npm run当中去
找到并打开我们刚刚加进来的package.json文件,找到脚本所在行。



手动添加build脚本,完成映射,这样我们就可以敲npm run build指令了。

(学习了vue-cli后,我们会看到有npm run start /npm run server / npm run dev等等映射指令,都是经过webpack进行打包映射的。)

我们把dist下面的bundle.js文件删掉测试下刚刚配置好的映射npm run bulid指令。



我们发现bundle.js文件又被恢复了,证明我们映射的npm run build是成功了的。



webpack全局安装和局部安装的问题
我们现看下自己的现在全局安装的webpack版本号,发现是4.44.1的版本了。


而我们手头上的项目当时用的webpack的3.6.0的版本进行配置的,依赖的也是3.6.0的版本。

用4.44.1的webpack版本去配置3.6.0的webpack版本会报错。

这时候就要在本地安装依赖了,在本地安装一个webpack3.6.0的版本。


--save-dev的解释:开发时依赖,在项目开发的时候要用到webpack,项目开发完成打包上传到服务器后,项目运行起来就不在需要webpack了。(还有一个叫运行时依赖的)

安装完成后,我们重新打开package.json文件进行查看,发现多出了一个名叫devDependencies的代码行。



与此同时,我们发现文件夹下多出一个node_modules的文件夹。


image.png

打开它,我们能找到webpack依赖的相关信息文件。

只要是在终端敲webpack都是全局安装的,webpcak本地(局部)安装的是在package.json里面的脚本行配置,npm run build默认是找局部的,本地找不到,才会找全局。


总结:1.出入口文件的配置,2.weback局部安装的配置。

loader的使用

loader是webpack中一个非常核心的概念。

webpack可以用来做什么?

通过上面的例子,我们发现我们主要用webpack来处理我们写的js规范代码,并且webpack会帮助我们自动处理JS之间的相关依赖。

但是,在实际开发中,我们不仅仅只有基本的JS代码的处理,我们有时候也要加载CSS,图片,ES6转ES5,TypeScript转ES5,scss,sass还有less转css,.jsx文件和.vue文件转js文件等等。

对于webpack本身的能力来说,这些转化是不支持的,怎么办?

这时候呢,需要给webpack拓展对应的loader。

loader使用过程:
步骤一:通过npm安装需要的loader
步骤二:在webpack.config.js中的module关键字进行配置。

接下来进入代码视图(以打包CSS为例子作为index.html的引用)
首先我们整理下文件夹,在src目录下新建一个名叫JS文件夹放置.js脚本代码文件,将原先其他的.js文件拖拽进去放置,只要把main.js裸露出来就好。


在src目录下新建一个名叫CSS的文件夹,用于放置.css文件,在CSS目录下,创建一个nomal.css文件,写入简单的样式用于测试。

在main.js入口文件做css包的依赖。

然后打开终端,输入npm run build,我们发现报错了。

我们打开webpack中文官方网站提供的文档:
https://www.webpackjs.com/loaders/#%E6%A0%B7%E5%BC%8F
找到它,点击超链接进去看解决方案。

首先打开终端安装

安装完成后,打开webpack.config.js进行相关配置。

配置好后,终端再次运行npm run build,我们发现又报错了。

原因是当前版本太高了,需要降低版本(使用2.0.2版本)。

终端再次测试npm run build 报错解除。

配置和安装完css-loader后,我们还需要在webpack.config.js里面配置style-loader和在终端安装style-loader,不然是样式没有生效的。


再次执行npm run build
我们看下刚刚index.html的效果,打包的是normal.css文件。

上面学了js,css文件的打包处理,下面演示less文件处理

在CSS目录下,创建一个special.less文件



来到入口文件main.js做less的依赖。

终端输入npm run built ,不出意外的话还是会报错。

同上面css的解决方案,已经有经验了,打开webpack官网
https://www.webpackjs.com/loaders/#%E6%A0%B7%E5%BC%8F
找到less相关的资料,点击超链接,看解决方案。

安装less-loader

在webpack.config.js配置less-loader

终端运行npm run build,版本太高了,报错了。

指定版本号安装。

安装完成后再次执行,npm run build
报错解除。

来到main.js文件给页面添加文字。

再次运行npm run build
看下页面效果,less语法的样式生效了。

打包图片处理
在src目录下新建一个名叫img的文件夹,顺带放置进去2张图片。

打开CSS目录下的normal.css样式文件,将图片作为页面的背景。

如果终端直接执行npm run build的话,肯定会报错,报错提示我们去安装合适的loader,同上面遇到的情况一样。

所以我们去官网看教程,点击蓝色字体的超链接,看解决方案。



安装url-loader:

npm install --save-dev url-loader
报错的话,一般和版本号有关,所以指定版本号很重要。
npm i --save-dev [email protected]

打开webpack.config.js进行配置。


拓展:早期DOS操作系统只支持后缀3位,常见的.htm和.jpg文件格式,到了window操作系统,才有了.html和jpeg格式(支持后缀4位),区别不大。

当我们运行npm run build 的时候报错了,提示我们没有找到'file-loader',这是因为webpack.config.js文件的file-loader的limit参数的限制问题。


limit参数限制是个致命的玩意,如果不留意,非常容易报错,出现上面报错的,解决方案看这篇。
https://www.jianshu.com/p/b26b252dc78c
报错解除后,我们看到了index.html的页面(刚刚写在normal.css的背景图片url样式)。


查看body的样式,为什么这里有个base64?

这跟我们设置webpack.config.js文件的url-loader下的limit参数有关。

当加载图片大于limit时,需要安装file-loader,否则打包报错。
使用file-loader在这篇:https://www.jianshu.com/p/b26b252dc78c

ES6语法处理

如果ES6语法没有转成ES5,那么意味着可能一些对ES6还不支持的浏览器没有办法很好的运行我们的项目代码。

我们可以看下dist目录下的bundle.js文件的ES6语法。

如果希望我们的ES6语法转成ES5,那么就需要babel。

所以我们需要安装babel对应的loader.
官网教程:https://www.webpackjs.com/loaders/babel-loader/

我们安装的跟官网的参数有点不一样。

npm i -S -D babel-loader@7 babel-core babel-preset-es2015

语法糖解释:
-S 是--save的缩写
-D 是-dev
--save-dev 的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖。
devDependencies 中记录的是项目在开发过程中需要使用的一些文件,
在项目最终运行时是不需要的也就是说我们开发完成后,最终的项目中是不需要这些文件的。

配置webpack.config.js文件

我们只需要复制官网的这一部份,修改下参数,放到我们的webpack.config.js文件即可。



终端执行 npm run build 重新打包,查看bundle.js文件,发现其中的内容变成了ES5语法(const变成var了)

webpack中配置Vue

使用Vuejs进行开发,是以特殊的文件来组织vue的组件的,所以我们要学习如何在webpack环境中集成Vuejs

因为我们后续的实际项目也会使用vue,所以并不是开发时依赖,去掉-dev参数.

npm i vue -S
语法糖:--save简写-S

安装成功后显示:


打开main.js入口文件做vue的依赖。


来到index.html文件做vue实例的挂载。



重新npm run build打包,看下页面效果,其实页面效果并没有出来,还直接报错了。



这是因为vue在构建最终的版本时,构建了2类版本


所以我们要使用的是runtime-compiler版本,打开webpack.config.js文件进行配置,使用alias别名的方式指定runtime-compiler版本。


终端运行npm run build 重新打包
报错解除,效果出来了。


template和el的关系,在vue实例里面同时写了template和el,template会将el给替换掉

SPA:单页面应用(simple page web application)--用前端路由跳转vue-router

所以index.html的挂载点里面是不包含任何vue代码的(不会在这里写),因为会被template替换掉,我们只需要保留挂载点即可。

在main.js的vue实例里写入vue代码。

运行npm run build看下效果,发现页面是被替换了,显示的是template的内容,所以验证了template会替换掉el,提醒我们不要在挂载点(绑定的el:"#app")里面写入任何vue代码。


但这样写的template显然是不合适,我们需要将其抽成一个组件


我们npm run build看下效果

效果可以实现了,但是这样的代码还是不好,因为我们的组件的是个对象,它还可以抽离成单个文件。
在src目录下创建一个名叫vue的目录,创建一个app.js文件。


我们npm run build看下效果

但这样的代码还是不好的,因为vue的模板template和vue脚本没有做到分离

所以我们还可以抽离,在vue目录下创建App.vue文件。



我们将app.js代码抽离成App.vue



执行npm run build,但我们会发现报错了。

报错提示我们去配置对应的loader


注释:vue-template-compiler是编译模板的意思,安装的是开发时依赖。

安装完成后,来到webpack.config.js进行vue-loader的相关配置。



注释:/正则表达(匹配所有.vue结尾的文件)/

执行npm run build,继续报错了。



报错提示我们缺失了一个plugin(插件)

这是因为vue-loader版本太高的原因导致的,v14开头的版本号往上都要安装插件了。

我们可以找到package.json文件,查看下当前项目当中的vue-loader版本号,已经是15.9.3的版本了。



所以我们要做到是降低版本号,手动修改成v14版本以下的版本号。



在package.json中手动修改版本号后,要在终端要重新运行安装依赖
npm i

安装完成依赖后,继续npm run build,到这里,所有的报错都解除了


降低版本号,是其中一种解除报错的方法,另外一种是去官网装插件。

最后抽成了组件化开发的思想,实现2个.vue文件的父子组件嵌套

在vue目录下创建一个HelloWorld.vue文件



执行npm run build进行编译

小结:组件化开发最终形成组件树。

拓展:配置.vue后缀省略的操作(类似还又.css,.js等后缀文件)
我们原来的文件都是带后缀的(下图),这是因为没有做后缀的相关的配置。


如果我们想省略后缀的话,打开webpack.config.js文件,找到resolve对象。


配置extensions


参数注释:
resolve对象 一般用于解决路径问题。
extensions参数 解决拓展名的问题

这里的.vue后缀就可以去掉了。


最后npm run build 进行编译,可以看到效果,如果没有配置extensions参数,直接省略了文件后缀名是会报错的。

总结:从基础的一步一步抽离的话,我们不知不觉间已经接近了vue的脚手架了的.vue文件,整个框架也稍微清晰了。(整个生态)

plugin插件的使用

1.什么plugin?
plugin中文是插件的意思,通常是用于对某个现有框架进行拓展,插件的出现是为了优化框架和拓展框架的功能而衍生出来的。

举个栗子,webpac中的插件,就是对webpack现有功能的各种拓展,比如打包优化,文件压缩等待。

2.loader和plugin的区别:
loader主要用于转换某些类型的模块,确切的说,它是一个转换器又是一个加载器,使用其他的模块或文件时需要加载相应的loader。

plugin是插件,它是对webpack本身功能的拓展,相当于一个拓展器。

3.plugin的使用过程
步骤一:通过npm安装需要使用到的plugins(某些webpack已经自带内置的插件是不需要安装的)

步骤二:在webpack.config.js中的plugins参数中配置插件。


(1)添加版权声明插件,BannerPlugin(横幅插件),这个插件的作用就是些类似上面截图的版权声明。

打开webpack.config.js文件通过CommonJS语法require导入webpack模块,然后增加plugins参数,通过new webpack实例来使用。


运行npm run build进行编译,编译完成后,找到dist目录下的bundle.js文件进行打开,我们看到版权声明已经添加进来了。



(2)打包html的插件,HtmlWebpackPlugin插件

为什么需要打包html的插件?

因为项目开发完成后,我们需要真实发布项目,我们是把整个dist目录上传到服务器的,发布的是dist文件中的内容,但是dist目录下并没有index.html这个文件,那么打包的js文件就没有意义了,因为我们的index.html在src源码根目录下放置着。

所以,我们需要将src源码根目录下的index.html文件打包到dist文件夹中,这个时候就用到了HtmlWebpackPlugin插件

HtmlWebpackPlugin插件可以帮助我们实现的功能:

  • 在dist目录下自动生成一个index.html文件(可以指定模板来生成)
  • 将打包的js文件,自动通过script标签插入到body中

安装HtmlWebpackPlugin插件

npm i html-webpack-plugin -S -D

使用插件,修改webpack.config.js文件中的plugis部分内容如下:

  • 通过require引入html-webpack-plugin模块
  • 在plugins参数中配置new HtmlWebpackPluginl()来使用插件。



    重新打包编译 运行npm run build

我们发现dist目录下多出了一个index.html文件。



我们打开dist目录下的index.html文件,有些要注意的部分。


  • 注释掉pubilcPath默认的dist路径



  • 添加实例挂载点
    首先来到src目录下的index.html文件,删掉脚本行引入,只需要保留挂载的即可。


因为我们dist目录下的index.html文件是根据src目录下的index.html文件的模板生成的。

修改webpack.config.js文件中的plugis部分,找到new HtmlWebpackPluginl(),配置template参数,内容如下:


接下来我们需要验证效果,所以要将dist目录下的所有文件全部删除(保留一个空的dist文件夹即可)。



运行npm run build 进行编译
我们发现了刚刚删除的所有文件都自动生成新的(恢复了)。



打开dist目录下的index.html文件。

(3)JS脚本的压缩插件

为什么需要压缩脚本文件?

  • 在项目发布只之前,尽量要压低文件大小,这和用户体验有关,我们日常也在应用商店下载软件app,都会留意以下软件的大小,有些app只有几十M不到,有些过百M的,那当然是几十M的下载更快一些,所以我们要对js文件进行压缩处理.

  • 我们使用的是第三方插件 uglifyjs-webpack-plugin
    uglify是丑化的意思,它的实际效果就是将js文件下的空格字符给删除掉(因为我们的代码编写规范习惯都是层层缩进的,导致了出现了很多很多的空格,空格看起来好像什么,但空格也是字符,占用字节大小的),几千空格字符累计起来,它的字节可不小,此外,JS中定义的一些变量名也会用其他字符进行转译,注释也会被删掉。

  • 这样就达到了整体的压缩效果。

安装第三方插件 uglifyjs-webpack-plugin,指定版本号1.1.1和cli2保持一致

npm i [email protected] -S -D

在webpack.config.js文件中通过require引入使用插件。


修改webpack.config.js文件中的plugis部分内容如下:


运行npm run build 编译

我们打开dist目录下的bundle.js查看压缩后的丑化效果。


我们看到了密密麻麻难以看懂的代码,这就是这个第三方插件的效果,丑是丑了点,但实现了文件的压缩。

搭建本地务器(涉及node知识)

为什么要搭建本地服务器?需求是什么?

  • 搭建本地服务器可以实现浏览器页面自动刷新的功能,也就是达到实时加载的效果.

  • 本地服务器搭建好后,会提供给我们一个服务器的端口号,这个就好像vue-cli提供的8080服务器端口号。

  • 有了它,不再需要去手动点击刷新了页面了(我们以前写的代码都是手动刷新的,只能说,编写单个html文件的时候还好)

  • 换到项目中,你要不停的运行npm run build 这条编译指令(上面一步步走来,我们已经体验过了,实在是繁琐),这样的开发效率实在太慢了,一个简单浏览器的页面刷新,就能把人折腾够呛。

  • 当然了,现在有些代码编译器安装某些插件也可以实现单页面的实时加载了,例如VSC的LIve Server插件。

基于node.js搭建本地服务器

  • webpack提供了一个可选的本地开发服务器,这个本地服务器是基于node.js进行搭建的,它的内部采用的是express框架,可以是实现浏览器实时加载刷新的效果。(也是就是让浏览器自动刷新显示我们修改后的代码效果)

webpack-dev-server是webpack的一个单独模块,使用之前需要安装

npm i -S -D webpack-dev-server
指定版本号安装:
npm i -S -D [email protected](相当于vue2脚手架的版本,还对应webpack3.6.0的版本)

devserver是webpack的一个选项,它可以设置如下属性

  • contentBase: 为哪一个文件夹提供本地服务,默认是根文件夹,这里要填写./dist
  • port: 是端口号
  • inline: 页面实时刷新,填写的是布尔值
  • historyApiFallback: 在SPA页面中,依赖HTML5的history模式

webpack.config.js文件配置修改如下:

package.json文件做添加脚本指令映射,如下

现在我们运行 npm run dev,因为在webpack.config.js中没有指定port,默认的是本地8080端口.

我们可以复制网址去打开看看效果,这样本地服务器就被搭建起来了。



修改下我们项目的代码,发现我们浏览器自动刷新的效果也起来了,不再需要手动点击刷新。

细节补充:

但这样我们还是要手动点击8080端口的链接打开,这里我们还可以在package.json中配置一个--open的参数,或者在webpack.config.js中devServer添加属性open: true来达到自动打开8080端口(二选一)



--open参数就是在我们运行npm run dev的时候,浏览器自动帮助我们打开本地8080服务器端口,不再需要复制链接去打开。

webpack配置文件的抽离

因为有些配置是我们开发的时候要用到的配置,到了发布的时候有些配置并不需要了,比如我们的本地服务器搭建,我们之所以要搭建本地服务器是为了提高我们的代码开发测试效率,项目完成发布后,这个搭建好本地服务器是不再需要的了,所以要做到将其抽离出去,做成单个js文件。

所以,我们要实现的就是开发时的配置和发布时的配置分别放置。

在当前项目下,创建一个build目录,放置三份脚本配置文件,将webpack.config.js一分为三,各自实现自己该有的配置(如右图所示)。



一分为三后的各自配置。



base.config.js
//公共配置
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.css$/,//正则表达式
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.less$/,
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader" // translates CSS into CommonJS
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8196,
                            name: 'img/[name].[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.js$/,//匹配JS文件
                exclude: /(node_modules|bower_components)/,//只需转化src目录下的代码,其他文件夹的排除在外
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['es2015']
                    }
                }
            },
            {
                test: /\.vue$/,
                use: ['vue-loader']
            }
        ]
    },
    resolve: {
        extensions: ['.css', '.js', '.vue'],
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    },
    plugins: [
        new webpack.BannerPlugin('最终版权归qinfubin所有'),
        new HtmlWebpackPlugin({
            template: 'index.html'
        }),
    ]
}

最终编译发布的时候,需要的是,base.config.js和production.config.js
开发中需要的是,base.config.js和dev.config.js

我们最终要发布上传到服务器,所以现在我们要对base.config.js和production.config.js配置文件进行合并,dev.config.js是我们开发的时候要用到,项目完成后不需要了。

安装webpack-merge

npm i webpack-merge -S -D
带版本号的:
npm i [email protected] -S -D
注释:merge就是合并的意思

安装完webpack-merge后,production.config.js配置文件的配置如下:



dev.config.js配置文件的配置如下:


将webpack.config.js一分为三并且配置合并后,它也没必要存在了,可以进行删除。

接下来,手动配置package.json的脚本映射,因为我们的路径变了,要指向到build目录下。


接下来,修改base.config.js配置文件的path参数下dist路径指向(因为这个路径指向不更改的话,npm run build之后默认打包到build目录下了,而我们要打包到的是dist目录下)



最后执行2次编译
npm run build
npm run dev



出现这个就算完成了一分为三的配置抽离任务了.

你可能感兴趣的:(webpack学习笔记(踩坑笔记))