webapck 基本配置以及plugin和loader的用法

可以结合慕课网的视频来读这篇文章,地址:http://www.imooc.com/learn/802

Webpack简介:

给JS准备的一个打包工具,可以把很多的模块打包成很好的静态,且有一个自己的特性叫做代码分割 ,webpack有个整个loader的概念,通过loader可以处理各种各样的文件,可处理css common.js 图片文件 AMD less文件 es6 自定义文件如:vue文件等。

官方的定义:它是一个模块的打包器。

大概的处理过程:左边 .css .js .png 等都视为一个模块通过箭头之间有依赖关系的模块群之后webpack会对依赖的模块群进行处理把它打包成浏览器可以直接运行的JS文件和CSS文件还有真实的图片

Webpack的最大特点是代码分割;
代码分割:在项目中只是加载当时只需要的那部分文件;

####### Webpack的目标:

  • 切分它的依赖数,会把它的依赖数切分到不同的代码块里,然后按需
    加载这些代码块(类似于懒加载概念)
  • 为了保持初始化的加载时间更少
  • 任何一个静态的资源都是被视为一个模块,在项目中被引用(在开发过程中有很多的便利)
  • 它可以整合一些第三方的类库,并且把第三方类库也视为一个模块,并在项目中引用
  • 打包的过程中可以自定义,几乎每一个部分都可以自定义,做一些自己想做的事情,非常适合大型项目
Webpack和其他打包工具的不同:
  • code Spliting 代码分割
  • loaders
  • 模块热更新(在开发过程中大大提高的调试和效率)

webpack 安装

进入目录 cd xxx
建立一个文件夹 如:mkdir webpack-text
进入文件的 cd wabpack-text
在文件下初始化 npm init
全局安装webpack:npm install webpack -g
初始化完之后装webk:npm install webpack --save-dev
安装完之后可以看见项目下有 package.json和一个node_modules的一个文件,安装完之后用编译器打开当前目录,就可以创建开始编码了,写好了之后,就可以在命令中输入如:
Webpack hello.js hello.bundle.js webpack直接跟文件的名称后面再去跟打包后的名称
这就完成一次简单的打包操作
操作成功之后它会给我们一部分值(在命令行中可以看到以下参数):

  • 哈希值 webpack版本
  • 这次打包花费的时间
  • Asset 显示这次打包生成的文件
  • size这次打包文件的大小
  • Chunks 这次打包的分块
  • chunk Names 这次打包的块名称
打包文件后在文件中看到的效果

Webbpack 支持三种的模块化方式AMD commonjs es6的模块化


图中画圈的部分用的就是commonjs
图中webpack把上上图中画圈的commonjs中的require 转换成webpack内置的__webpack_require_(1)
图中如果没有给webpack安装专门处理css的loader就会报错

安装好之后还要指定相应的loader 才可以引入如:require(‘css-loader!./style.css’) 加上之后就可以执行了

image.png

要是引入的css生效还需要借助 style-loader! 如:require(‘style-loader!css-loader!./syle.css’)

image.png
image.png
图中要使引入的css生效,还的引入style-loader

很多人就有了疑问,我每次都得加这么多loader么?那不是很麻烦

对引入的css的文件,还有一种处理方式:在命令行输入 :
Webpack hello.js hello.bund --module-bind’css=style-loader!css-loader’ 这个方法也很麻烦,每次文件改变都得输入这个命令,下面是更简便方法,文件改变打包的文件也自动更新、自动打包。
对于以上两种方法也和繁琐可以通过文件自动打包,自动更新 如:Webpack hello.js hello.bund --module-bind’css=style-loader!css-loader’ --watch
Webpack 还有可以看到打包的过程的方法 : 右下可以看到百分比读条(右下可以看到短暂的百分比读条)
Webpack hello.js hello.bund --module-bind’css=style-loader!css-loader’ --progress

特别注意:上图path中的要写对

webpack的基本配置以及webpack配置里面的一些参数的功能

webpack 的配置文件 在webpack下建立一个 webpack.config.js 的文件 为什么要这样建立配置文件:
如果直接使用webpack这个命令的话,webpack会在根目录下寻找webpack.config.js 把它作为默认的配置取运行
配置文件的最基础的配置

 module.exports = {
               entry: ‘./src/srcipt/main.js’,  //表示配置入口
               output:  {
                        path:  ‘./dist/js’,   //指明打包以后的文件放到什么地方
                        filename: ‘bundle.js’  //打包以后的文件名
                           } 
                       }

配置好之后直接在命令行输入 webpack 就可以执行了

若给配置改个名的处理方法 如 配置不叫 webpack.config.js 而是 webpack.dev.config.js
可以通过命令行来通过webpack的参数config来指定 如:
Webpack --config webpack.dev.config.js 这样就生效了

在有配置的情况下怎么加参数 :
可以配合npm的脚本 package.json 中的 “scripts”中定义一段脚本 :
“webpack”: “Webpack --config webpack.config.js --progress --display-module --colors”
在脚本中定义好之后就可以在命令行中输入:
npm run webpack 脚本就可以运行了

数组的方式:入口文件放到数组里面
 module.exports = {
               entry: [‘./src/srcipt/main.js’,’./src/script/a.js’],  //表示配置入口  处理文件多的话另一种写法
               output:  {
                        path:  ‘./dist/js’,   //指明打包以后的文件放到什么地方
                        filename: ‘bundle.js’  //打包以后的文件名
                           } 
                       }
图中是后台运行打包数组的总的文件的情况
图中的0模块就是把两个不相干的入口文件,把它们require到一起,相当于打包到一起了,这样就可以在开发中使用它了

#######entry是对象的方式

图中要是entry是对象的模式,下面output需要写成[name ]、[hash]、[chunkhash]这三种,若写成bundle.js这种的,就会报错
图中红色圆圈是上上那个图中[name]-[hash]

注意:文件上面的哈希值互相不一样了,可以认为是文件的版本号,也可以认为是MD5值(MD5算法就是为了保证每个文件的唯一性),也就是说只有当这个文件发生改变的时候,这个哈希值才会变化,这个特点,在我们的项目中对静态资源版本号的管理是非常有用的,平时我们项目中上线的时候,正好需要只上线那些已经被我们改过的文件

生成项目中的的html页面文件

就想上面对象为入口的话,它的文件名是[name]是不确定的,难道每一次这种打包都要手动去设置路径吗,那岂不是非常麻烦:用webpack的插件来解决这个问题

先用npm install html-webpack-plugin --save-dev

好了之后去webpack的配置文件webpack.confing.js中

用commonjs的方法引入webpack的插件模块
图中对引入的进行初始化
做完上述的操作在命令行中输入npm run webpack就可以了,如下图:(红线的部分说明已经生效)

但是上面有一个弊端就是插件生成的index.html文件是在js中,而在我们自定义的index.html之间没有建立任何的联系,这是不满足项目的需求的,下图

自定义的index.html和插件生成的index.html建立联系

解决方法:在配置文件的plugins 的初始化对象传参(这是为了让咱们自定义的index.html和文件中生成的index.html建立联系)

解决方法
context

把生成号的html放到dist中而js需要放到js的文件中,在配置中如下操作:

image.png

Plugins 还有什么参数呢,还可以指定我们生成的名称(filename),还有我们可以直接指定想吧我们的脚本放在头部还是body标签里面,如下图:

plugins参数
title
在index.html中取title的值

通过上两幅图的方法就可以取到在plugin中设置title的值

data
在index.html中取data的值

通过上面两个获取data的值

htmlWebpackPlugin中的属性files和options对象中的键值
htmlWebpackPlugin中的属性files和options对象中的键值

上两个图是对htmlWebpackPlugins下files和options 属性中插件参数的遍历

图中一部分放到head中,一部分放到body中
pulicPath用法

puliPath在页面中的显示

上两个图就是output中的pulicPath就是设置上线时候的前面的网址

上线的时候需要压缩用minify属性

注:[www.npmjs.com中搜html-webpackplugin(http://www.npmjs.comhtml-webpack-plugin) 可以看到webpack中的插件的使用和说明

Webpack插件的多页面应用

根据不同的页面可以指定不同的模块(或者根据不同的页面指定相同的模板),不下图:

webpack中plugin的多页面应用
吧模块里手动引入的指向生成完的那个文件去掉

注:如果用chunks或excludeChunks来引入模块的话,index.html 里面不能有任何注释,否则会疯狂报错

chunks用法

把配置里面的inject:‘body’ 自动引入发到body里面,chunks只加载需要的块就可以了
上面的这种方法需要一一去对应,就显得非常的麻烦,所有就提供了另外一个参数(excludeChunks[除了那个都是要加载的])

excludeChunks用法

再往下深入一点,如果我们要把页面的性能达到极致的话,吧初始化的脚本直接嵌入到页面,而不以链接的形式引入在页面,如下图就是以链接形式引入页面的,这种方式会增加http请求


链接的方式

GitHub中的实例

上图是githup里面webpack的初始haul的脚本直接嵌入到页面的方法

有同学会想到既然我们webpack这个配置文件中运行js,那我们为什么不调用nodejs的读取文件的API直接读取我们想要引入进来的文件呢
但是会有一个问题,就是直接引入这个文件,不会经过webpack处理的,而你想要引用这个经过webpack流处理过后的文件,通过这种方式你是做不到的。

那么通过什么方式能做到呢,通过compilation(webpack它自身暴露出来的给我们可以使用的一个引用)

通过files对象中chunks.main.entry来截取字符串

截取到没有publicPath的地址

上两图的操作就可以直接拿到不带publicPath 的路径,若htmlWebpackPlugin.files.chunks.main.entry 只是这样写,没有后面的substr(..)的话,获取到的还是带有publicPath的路径,之后就可以如下图中的方法取到它里面的内容:


webpack自身暴露出来的方法compilation

公共部分直接嵌入页面

上图公用的是上面的红圈部分是直接嵌入页面,而下面的a、b、c是引入进来的。

总结webpack中plugin的内容:首先讲到了如何使我们的html和我们的动态的生成的文件名称一一对应上,然后我们探查了一下这个htmlWebpackPlugin究竟通过它能够怎么样的自定义我们的这个html,并且可以通过模块,还有它里面的一些参数,如何传参;之后我们一起学习了多页面的时候,如何通过htmlWebpackPlugin来生成多个html,最后我们一起深入的探究了一下怎么通过htmlWebpackPlugin并且结合模板的方式,去吧我们的生成的js里面的内容直接inline的形式引入到我们的html里面中

什么是Loader以及Loader的特性

#######loader的定义:
loader只是处理资源文件的,也就是说它接受资源文件为一个参数,然后它处理完了之后会返回一个新的资源,这么一个过程就是loader的处理。比如说你用 了loader,就可以告诉webpack处理的这个CoffeScript或者是JSX的时候去使用loader,就可以处理这两种webpack不支持的这两种格式。
#######Loader的特性:

  • 可以是被串联的 如:之前的 css-loader!style-loader! 这种串联的方式去使用loader
  • 可以是同步也可以是异步的
  • 可以在nodejs环境下去运行
  • 可以接受一些参数
  • 可通过正则表达式,指定的后缀名,在这个配置中就可指定这个某一个后缀名的文件有某个loader来执行(这是一个它的特点)
  • loader可以通过npm来安装 npm install
  • loader可以获取configuration (也就是webpack的配置)
  • 我们的插件可以给loader更多的特性
  • loader还可以生产额外的文件(除了处理我们指定的文件之外,loader还可以生产额外的文件)

#######使用loader的方式有三种:

  • 在require中就可以指定指定这个loader 如[ require( “./loader! ./dir/file.txt” ) ] [ require( “ !style!css!less!bootstrap/less/bootstap.lesss ” ) ]
  • 这配置在我们的配置文件
  • 直接使用CLI(在命令行中 webpack --module-bind jade --module-bind ‘css=style!css’)

三种方式的的第一种和第三种都用过了,这个用第二种在配置文件的使用:

在配置文件中

[http://babeljs.io/docs/setup/#installation(http://babeljs.io/docs/setup/#installation) 点击Build systems中的webpack 可以看到:

安装babel-loader
通常之后我们还的给它一个配置 {
                    “presets”: [ “es2015” ] 
// babel 也有自己的的插件都在更新和落实,给各个浏览器支持,不断的发布草案,不断的修订
//我们可以通过指定presets来告诉我们 这个babel-loader 知道来转换某一些特性,为我们的js,若这个时候你需要它转换为所有的特性,直接指定latest(包括es2015,es2016,es2017)
}        
//指定presets其实就是告诉babel-loader 怎么去处理这个我们这些的js,给不同的特性,我们需要转换哪个个特性

那么怎么去指定这个插件,涉及到之前说的参数的问题,直接loader 指定一个参数如下两图:


三种方式指定loader

persets用法

注:指定完之后还的安装这个插件:


安装babrel-preset-latest
在配置中指定presets

也可以通过上图的方式来指定presets,这样我们就不用再我们的配置文件中指定了

babel-loader

注意:在配置中loader:’babel’这样写是会报错的,调好好久,一点不要省略babel后面的loader(之前webpack1.x的时候可以省略,但是webpack2.0就不可以省略)

图中是babel后面不加loader所报的错误
babel-loader打包时间长

打包的时间长,原因在loader上,因为babel-loader是非常耗时的转换,那么如何去改善呢

Loaders定义的参数有五个 exclude 排除范围 (如:某一目录下不让去处理)【一些打包过后的文件不希望去处理】如下图:


loaders参数

exclude的用法

include 指定包含的范围
loaders可以把一长串的loader一个数组表示

注意:Webpack中的Using Loaders只说了一些简单的定义如何去使用,真正的文档是在 Configuration

图中红圈的部分意思是只打包src目录下的,而exclude意思排除范围(不去打包的范围)
用了exclude后的时间

用了exclude 之后吧已经打包好的文件排除了,不进行二次打包之后,执行效果很快

condition

Condition可以是一个正则表达式,也可以是一个字符串(包含着绝对路径的),还可以是一个函数或者是包含着绝对路径的一个数组

exclude

总结:安装了babel之后,如何通过webpack的配置来使我们的webpack来处理es6中的代码,把es6代码转换成可以运行的es代码

处理项目中的css

安装style-loader 和css-loader
npm install style-loader css-loader --save-dev

loaders中的配置

引入完画红圈的部分,就可以在js中处理css文件了

!串联loader

flex布局兼容浏览器效果还不是很好,需要加前缀(手动加前缀太麻烦),webpack里面也有加前缀的loader 是:postcss-loader(它是一个后处理器)
先安装上npm install postcss-loader --save-dev
还需要安装 npm install autoprefixer --save-dev
在安装一个 npm install precss --save-dev

postcss-loader

引入autoprefixer

特别注意:上图是再创建一个新的postcss.config.js文件,里面写上上述内容
注:这一点webpac2.0 和webpack1.0也是有很大差别的


加前缀的效果图

从外部引进的css文件,也是可以的

注:webpack2.0 之后从外部引入文件不用在里面loader里面加入importloader=1,可以直接执行postcss-loader了
webpack 处理less和sass
首先安装less-loader:npm install less-loader --save-dev 若没有安装less,先安装less:npm install less
之后在loaders数组里新增一个匹配规则:


less的配置

loader 的处理方式是从右到左的,less-loader或sass-loader处理完了以后,再处理postcss-loader
Sass的处理和less的处理方式一样,也是在loaders里面新增一个匹配规则
处理项目中模板文件
模板

可以看到项目中有一个模板layer.html,通常处理这种模板的文件的做法,是webpack把这个模板文当做字符串进行处理,还有就是把这个webpack当做已经编译好的一个处理函数
打开webpack的官网,可以看到左边有一个List of loaders,进入,右边有目录点击templating,之后就可以看到出到出来模板的相关loader都在这里列出来了


在layer.js中引入layer.html

如上图在layer.js 中吧模板引入进来,.html文件是作为一个字符串进行处理

图中把layer模块放到app.js中

别忘了在index.html中加ID

处理模块还需要安装 npm install html-loader --save-dev
安装好之后在loaders规则中加一个匹配规则

html-loader
图中是引入模块成功后的的页面

实际项目中,更复杂,需要用到模板语法;
假设模块是.ejs结尾的模板;

ejs模板

首先安装npm install ejs-loader --save-dev


处理ejs模板需要的配置
把layer下的文件在改成tpl 表示模板,之后在loaders里面在匹配一下规则

如上图,layer.js 文件也的变动,图中当我们载入ejs模板的时候,webpack官网有说明,它会返回的是一个function,所以tpl它就不代表字符串了,它表示已经编译过的一个函数,那么函数时干什么用的呢,可以在app.js中传入我们所需要的数据,如下图:

tpl模块中的数据设置

完成后的效果图

Jsx表示react框架 用的非常广的一个loader,已经被寄生到了babel这个工具里面了,只需要一个写设置,就可以支持jsx

处理项目中图片文件以及其他文件

处理图片文件分几种情况:
第一种 css文件里面会有很多图片文件
第二种 模板里面直接引入某一张图片
第三种 最底部文件 index.html中对图片的引用

css中引入图片

引入图片之后,先安装 npm install file-loader --save-dev
只有在loaders中增加对图片处理的规则


配置中制定规则file-loader处理图片

图中命令行中已经显示图片被打包了

上面是指定第一种情况,在css中根据路径来打包图片文件

index.htm中引入图片

在index.html中直接引入图片一会直接被loaders匹配的设置好的规则处理好,显示在页面(第三种)

图中是解决在模块中引入图片的方法(第二种)

图片打包后的输入地址,想改变它的地址,从默认下放到dist的目录下,如果我们要改变它的话,给loader加一些参数


name中占位符
name中占位符的用法 ext

在命令行中看到的效果

安装url-loader:npm install url-loader --save-dev
url-loader 其实和 file-loader 很类似,但是可以指定一个参数,limit这个参数,limit是当你的图片或者文件大小,大于了你指定的limit后,它就会直接丢给file-loader去处理,然而当你小于limit指定的大小限制的时候,它会把的文件或者图片转为base64的编码,它就不在是一个url了

limit用法

使用limit的效果图img中成了base64

上图limit设置一个大于它图片的大小,在页面中转换成了base64(文件一下就变大了很多,影响了文件的大小),可以通过这种方式来区分哪些图片应该打包成图片,哪些图片应该打包成base64

压缩图片 需要安装:npm install image-webpack-loader --save-dev

压缩图片

loaders可以包含多个loader;
Limit改变的,小于了,图片的大小,图片压缩打包之后图片大小变小(比原来的文件都小)

谢谢读者朋友耐心读完这篇文章。

推荐阅读更多精彩内容