0 webpack概论

0.1 为什么需要WebPack

现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决SCSS,Less……新增样式的扩展写法的编译工作。所以现代化的前端已经完全依赖于WebPack的辅助了。

现在最流行的三个前端框架,可以说和webpack已经紧密相连,框架官方都推出了和自身框架依赖的webpack构建工具。

  • React.js+WebPack
  • Vue.js+WebPack
  • AngluarJS+WebPack
    从此可以看出,无论你前端走那条线,你都要有很强的Webpack知识,才能祝你成为这个框架领域的大牛。

0.2 什么是WebPack

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。

Webpack主要包括以下三个重点

  • 打包:可以把多个Javascript文件打包成一个文件,减少服务器压力和下载带宽。
  • 转换:把拓展语言转换成为普通的JavaScript,让浏览器顺利运行。
  • 优化:前端变的越来越复杂后,性能也会遇到问题,而WebPack也开始肩负起了优化和提升性能的责任。

如图所示

0.3 安装WebPack

WebPack的安装必须安装node,可以通过 node -v来查看node安装情况和版本,如果没有安装,要先安装node才可以继续进行。

如果已经安装过node可以进行webpack的安装

  1. 先对机器进行全局的安装

npm install -g webpack

  1. 对项目目录进行安装

    • 全局安装完成后,我们还要进行一个项目目录的安装。在用npm安装前,我们先要进行一下初始化,初始化的主要目的是生成package.json文件。

      npm n init

    • 输入下面命令进行项目目录的安装:
      npm install –save webpack

这里的参数–save是要保存到package.json中,dev是在开发时使用这个包,而生产环境中不使用。

  • 开发环境:在开发时需要的环境,这里指在开发时需要依赖的包。
  • 生产环境:程序开发完成,开始运行后的环境,这里指要使项目运行,所需要的依赖包。
  1. 查看webpack版本

webpack -v


0.4 第一个Demo

新建一个文件夹,之后在文件夹中按照刚才所说,(1.初始化项目,2.安装webpack)。
进入目录再建立两个文件夹,分别是src文件夹和dist文件夹:

  • src文件夹:用来存放我们编写的javascript代码,可以简单的理解为用JavaScript编写的模块。
  • dist文件夹:用来存放供浏览器读取的文件,这个是webpack打包成的文件。
  1. 编写程序文件

文件夹建立好后,我们在dist文件下手动建立一个index.html文件,并写入下面的代码。

/dist/index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>jspang webpack</title>
</head>
<body>
<div id="title"></div>
<script src="./bundle.js"></script>
</body>
</html>

这里引入了一个JavaScript的bundle.js文件。这个文件现在还没有,这是用webpack执行打包命令后生产的文件。
我们的index.html写好后,接下来在src文件夹下建立entery.js的文件,用于编写我们的JavaScript代码,也是我们的入口文件。

src/entery.js

1
document.getElementById('title').innerHTML='Hello Webpack';

  1. Webpack打包

webpack 入口文件 打包后存放的路径

执行的结果如下图:
如图所示
命令执行成功后,会在dist目录下出现bundle.js文件,这时我们就可以在浏览器中预览结果了,网页中显示出了Hello Webpack的信息。


1 详解配置文件

1.1 入口出口

webpack.config.js就是Webpack的配置文件,这个文件需要自己在项目根目录下手动建立。建立好后我们对其进行配置,先看下面的代码(webpack.config.js的基本结构),这是一个没有内容的标准webpack配置模版。

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
const path = require('path');
module.exports={
//入口文件的配置项
entry:{},
//出口文件的配置项
output:{},
//模块:例如解读CSS,图片如何转换,压缩
module:{},
//插件,用于生产模版和各项功能
plugins:[],
//配置webpack开发服务功能
devServer:{}
}
  • entry:配置入口文件的地址,可以是单一入口,也可以是多入口。
  • output:配置出口文件的地址,在webpack2.X版本后,支持多出口配置。
  • module:配置模块,主要是解析CSS和图片转换压缩等功能。
  • plugins:配置插件,根据你的需要配置不同功能的插件。
  • devServer:配置开发服务功能,后期我们会详细讲解。
  1. entry选项(入口配置)

    这个选项就是配置我们要压缩的文件一般是JavaScript文件(当然也可以是CSS…..)。按照刚才的代码这里要填写的是src目录下的entery.js文件。

    wepback.config.js中的entry选项

    1
    2
    3
    4
    5
    //入口文件的配置项
    entry:{
    //里面的entery是可以随便写的
    entry:'./src/entry.js'
    },
  2. output选项(出口配置)

出口配置是用来告诉webpack最后打包文件的地址和文件名称的。按照刚才代码应该打包到dist目录下。

1
2
3
4
5
6
7
//出口文件的配置项
output:{
//打包的路径文职
path:path.resolve(__dirname,'dist'),
//打包的文件名称
filename:'bundle.js'
},

filename:是打包后的文件名称,这里我们起名为bundle.js。

现在webpack.config.js的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const path = `require`('path');
module.exports={
//入口文件的配置项
entry:{
entry:'./src/entry.js'
},
//出口文件的配置项
output:{
//输出的路径,用了Node语法
path:path.resolve(__dirname,'dist'),
//输出的文件名称
filename:'bundle.js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{},
//插件,用于生产模版和各项功能
plugins:[],
//配置webpack开发服务功能
devServer:{}
}

多入口、多出口配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const path = `require`('path');
module.exports={
//入口文件的配置项
entry:{
entry:'./src/entry.js',
//这里我们又引入了一个入口文件
entry2:'./src/entry2.js'
},
//出口文件的配置项
output:{
//输出的路径,用了Node语法
path:path.resolve(__dirname,'dist'),
//输出的文件名称
filename:'[name].js'
},
//模块:例如解读CSS,图片如何转换,压缩
module:{},
//插件,用于生产模版和各项功能
plugins:[],
//配置webpack开发服务功能
devServer:{}
}

在入口文件配置中,增加了一个entry2.js的入口文件(这个文件你需要自己手动建立),这时候要打包的就有了两个入口文件。
在代码14行我们把原来的bundle.js修改成了[name].js。
[name]的意思是根据入口文件的名称,打包成相同的名称,有几个入口文件,就可以打包出几个文件

1.2 服务和热更新

设置webpack-dev-server

要执行webpack-dev-server是要先用

npm install webpack-dev-server –save-dev

来进行下载的。下载好后,需要配置一下devServer。最简单的devServer配置项只有四个。先看一下代码

1
2
3
4
5
6
7
8
9
10
devServer:{
//设置基本目录结构
contentBase:path.resolve(__dirname,'dist'),
//服务器的IP地址,可以使用IP也可以使用localhost
host:'localhost',
//服务端压缩是否开启
compress:true,
//配置服务端口号
port:1717
}
  • contentBase:配置服务器基本运行路径,用于找到程序打包地址。
  • host:服务运行地址,建议使用本机IP,这里为了讲解方便,所以用localhost。
  • compress:服务器端压缩选型,一般设置为开启(暂时不了解)。
  • port:服务运行端口,建议不使用80,很容易被占用,这里使用了1717.

终端中输入webpack-dev-server启动项目

当然我们也可以在package.json中配置一下项目启动

1
2
3
"scripts": {
"server":"webpack-dev-server"
},

在npm run server 启动后,它是有一种监控机制的(也叫watch)。它可以监控到我们修改源码,并立即在浏览器里给我们更新。

注意:这里只是我们的webpack3.6版本支持,在3.5版本时要支持热更新还需要一些其他的操作。

webpack并不鼓励全局安装webpack。这时候需要配置package.json里的scripts选项,我们以前的课程已经学习了配置 webpack-dev-server命令,在这个命令下面我们再加一个build命令进行打包项目使用。

1
2
3
4
"scripts": {
"server": "webpack-dev-server --open",
"build":"webpack"
},

配置完成后,可以在控制台输入npm run build 进行打包。

1.3 CSS文件打包

Webpack在生产环境中有一个重要的作用就是减少http的请求数,就是把多个文件打包到一个js里,这样请求数就可以减少好多。
在打包之前,需要先对当然我们也可以在package.json中配置一下项目启动webpack.config.js里的Loaders配置项进行了解。
Loaders
Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以通过脚本和工具,从而对不同的文件格式进行特定处理。
比如:

  • 可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
  • 可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
  • 可以把React中的JSX转换成JavaScript代码。

注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。

以下配置是对ES6配置

1
2
3
4
5
6
7
8
9
10
module:{
rules: [
{
test:/\.js$/,
loader:'babel-loader',
exclude:/dist/,
query: { presets: ['es2015']}
},
]
}

  • test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
  • use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
  • include/exclude:手动添加必须处理的文件(文件夹)/屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)。

loader的三种写法

第一种写法:直接用use。

1
2
3
4
5
6
7
8
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
},

第二种写法:把use换成loader。

1
2
3
4
5
6
7
8
module:{
rules:[
{
test:/\.css$/,
loader:['style-loader','css-loader']
}
]
},

第三种写法:用use+loader的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module:{
rules:[
{
test:/\.css$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader"
}
]
}
]
},

打包CSS文件:

在/src目录下建立index.css文件

./src/css/index.css

1
2
3
4
body{
background-color: red;
color: white;
}

CSS文件建立好后,需要引入到入口文件中,才可以打包到,这里我们引入到entry.js中。
/src/entery.js中在首行加入代码:

1
import i css from './css/index.css';

CSS和引入做好后,我们就需要使用loader来解析CSS文件了,这里我们需要两个解析用的loader,分别是style-loader和css-loader。

style-loader:

它是用来处理css文件中的url()等路径问题

npm install style-loader –save-dev

css-loader

它是用来将css插入到页面的style标签。

npm n install –save-dev css-loader

loaders配置:

两个loader都下载安装好后,我们就可以配置我们loaders了。
修改webpack.config.js中module属性中的配置代码如下:

webpack.config.js

1
2
3
4
5
6
7
8
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
},

1.4 配置JS压缩

JS代码,在上线之前,都是需要进行压缩的,在没有webpack和gulp这些工具前,你可能需要找一个压缩软件或者在线进行压缩,在Webpack中可以很轻松的实现JS代码的压缩,它是通过插件的方式实现的,这里我们就先来引入一个uglifyjs-webpack-plugin(JS压缩插件,简称uglify)。

注意:虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装。

引入

我们需要在webpack.config.js中引入uglifyjs-webpack-glugin插件

1
const uglify = `require`('uglifyjs-webpack-plugin');

引入后在plugins配置里new一个 uglify对象就可以了,代码如下。

1
2
3
plugins:[
new uglify()
],

这时候在终端中使用webpack进行打包,你会发现JS代码已经被压缩了。

我们来看一下目前的整体配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const path=`require`('path');
const uglify = `require`('uglifyjs-webpack-plugin');
module.exports={
entry:{
entry:'./src/entry.js',
entry2:'./src/entry2.js'
},
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].js'
},
module:{
rules:[
{
test:/\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
plugins:[
new uglify()
],
devServer:{
contentBase:path.resolve(__dirname,'dist'),
host:'192.168.0.104',
compress:true,
port:1717
}
}

1.5 HTML文件的发布

devServer和JS压缩的冲突

开发环境中是基本不会对js进行压缩的,在开发预览时我们需要明确的报错行数和错误信息,所以完全没有必要压缩JavasScript代码。
而生产环境中才会压缩JS代码,用于加快程序的工作效率。
devServer用于开发环境,而压缩JS用于生产环境,在开发环境中作生产环境的事情所以Webpack设置了冲突报错。
在实际开发中,webpack配置文件是分开的,开发环境一个文件,生产环境一个文件。

打包HTML文件

使用npm进行安装包。

npm install –save-dev html-webpack-plugin

配置webpack.config.js文件,引入我们的html-webpack-plugin插件。

const htmlPlugin= require(‘html-webpack-plugin’);

在webpack.config.js里的plugins里进行插件配置,配置代码如下

1
2
3
4
5
6
7
new htmlPlugin({
minify:{
removeAttributeQuotes:true
},
hash:true,
template:'./src/index.html'
})

  • minify:是对html文件进行压缩,removeAttrubuteQuotes是去掉属性的双引号。
  • hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
  • template:是要打包的html模版路径和文件名称。

在终端中使用webpack,进行打包。你会看到index.html文件已经被打包到我们的dist目录下了,并且自动为我们引入了路口的JS文件。

1.6 CSS中的图片处理

具体操作

在src目录下新建一个images文件夹,把图片放入images文件夹。

在index.html文件中增加一个放置div的标签(需要注意的是这里修改的是src下的index.html文件,不是dist下的,这点新手很容易弄混,要格外注意),代码如下。

1
<div id="tupian"></div>

编写css文件,把你用的图片作为背景显示。

1
2
3
4
5
#tupian{
background-image: url(../images/manhua.png);
width:466px;
height:453px;
}

编写完成后,我们可以试着用webpack去打包一下。你会发现终端中是报错的

安装file-loader和url-loader

npm install –save-dev file-loader url-loader

  • file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。

  • url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

配置url-loader,webpack.config.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//模块:例如解读CSS,图片如何转换,压缩
module:{
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},{
test:/\.(png|jpg|gif)/ ,
use:[{
loader:'url-loader',
options:{
limit:500000
}
}]
}
]
},
  • test:/.(png|jpg|gif)/是匹配图片文件后缀名称。
  • use:是指定使用的loader和loader的配置参数。
  • limit:是把小于500000B的文件打成Base64的格式,写入JS。

file-loader和url-loader关系

url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:

1.文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);

2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。

也就是说,其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上file-loader。

1.7 CSS分离

CSS分离:extract-text-webpack-plugin
webpack官方其实并不建议这样作,他们认为CSS就应该打包到JavasScript当中以减少http的请求数。

安装

npm install –save-dev extract-text-webpack-plugin

引入

const extractTextPlugin = require(“extract-text-webpack-plugin”);

设置Plugins

new extractTextPlugin(“/css/index.css”)

这里的/css/index.css是分离后的路径位置。这部配置完成后,包装代码:还要修改原来我们的style-loader和css-loader。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module:{
rules: [
{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},{
test:/\.(png|jpg|gif)/ ,
use:[{
loader:'url-loader',
options:{
limit:500000
}
}]
}
]
},

图片路径问题

利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确。最好的解决方案是使用publicPath解决

publicPath:是在webpack.config.js文件的output选项中,主要作用就是处理静态文件路径的。

在处理前,我们在webpack.config.js 上方声明一个对象,叫website。

1
2
3
var website ={
publicPath:"http://192.168.1.108:1717/"
}

注意,这里的IP和端口,是你本机的ip或者是你devServer配置的IP和端口。

然后在output选项中引用这个对象的publicPath属性。

1
2
3
4
5
6
7
8
//出口文件的配置项
output:{
//输出的路径,用了Node语法
path:path.resolve(__dirname,'dist'),
//输出的文件名称
filename:'[name].js',
publicPath:website.publicPath
},

配置完成后,你再使用webpack命令进行打包,你会发现原来的相对路径改为了绝对路径,这样来讲速度更快。

1.7 处理HTML中的图片

在webpack中是不喜欢你使用标签来引入图片的,但是我们作前端的人特别热衷于这种写法,国人也为此开发了一个:html-withimg-loader。他可以很好的处理我们在html 中引入图片的问题。因为是国人开发的,文档都是中文,所以学习起来还是比较简单的。

如何把图片放到指定的文件夹下

打包后的图片并没有放到images文件夹下,要放到images文件夹下,其实只需要配置我们的url-loader选项就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module:{
rules: [
{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},{
test:/\.(png|jpg|gif)/ ,
use:[{
loader:'url-loader',
options:{
limit:5000,
outputPath:'images/',
}
}]
}
]
},

这回你再执行打包就可以把图片打包到images文件夹里了。

html-withimg-loader

安装:

npm install html-withimg-loader –save

配置loader:
webpack.config.js

1
2
3
4
{
test: /\.(htm|html)$/i,
use:[ 'html-withimg-loader']
}

1.8 Less和Sass的打包和分离

  1. Less

Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。也就是说Less给我们枯燥单一的样式文件加入了编程机制,这让我们这些前端程序员很受用,所以在工作中大部分程序员都使用了Leess开发。

打包Less文件

安装:
要使用Less,我们要首先安装Less的服务,当然也是用npm来进行安装。

npm install –save-dev less

还需要安装Less-loader用来打包使用。

npm n install –save-dev less-loader

写loader配置:

安装好后,需要在webpack.config.js里编写loader配置,当然要想正确解析成CSS,还是需要style-loader和css-loader的帮助

webpack.config.js

1
2
3
4
5
6
7
8
9
10
{
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
}]
}

编写一个less文件

现在webpack的配置好了,我们还需要编写一个less文件,这里明文为black.less.里边只做一件是就是把一个层的背景设置成黑色。

black.less

1
2
3
4
5
6
@base :#000;
#gogo{
width:300px;
height:300px;
background-color:@base;
}

引入到我们entery.js文件中

import less from ‘./css/black.less’;

这样我们就可以把less文件进行打包了。我们可以使用webpack命令打包试一试。

把Lees文件分离。

extract-text-webpack-plugin这个插件,想把Less文件分离出来的方法跟这个几乎一样

1
2
3
4
5
6
7
8
9
10
11
12
{
test: /\.less$/,
use: extractTextPlugin.extract({
use: [{
loader: "css-loader"
}, {
loader: "less-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}

配置好后,你会发现less被分离到了index.css文件里。

  1. Sass

SASS的配置,其实你会了Less得配置,SASS的配置可以很轻松的学会

安装SASS打包的loader

node-sass:因为sass-loader依赖于node-sass,所以需要先安装node-sass

npm n install –save-dev node-sass

sass-loader:

npm install –save-dev sass-loader

在用npm安装时,这个loader很容易安装失败,最好使用cnpm来进行安装。如果你安装一直报错,最好是把node_modules文件夹删除后,再重新安装。
编写loader配置

1
2
3
4
5
6
7
8
9
10
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}

Sass文件的编写

1
2
3
4
5
6
7
$nav-color: #FFF;
#nav {
$width: 100%;
width: $width;
height:30px;
background-color: $nav-color;
}

把SASS文件分离。

1
2
3
4
5
6
7
8
9
10
11
12
{
test: /\.scss$/,
use: extractTextPlugin.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}

1.9 CSS3优化

  1. 自动处理CSS3属性前缀

CSS3已经成了前端的必会技能,但是你一定为那些属性需要加前缀,那些属性不需要加前缀而头疼。can i use网站,可以查询这些,但是每次都查实在是编码效率太低了。

什么是属性前缀

1
2
-webkit-transform: rotate(45deg);
transform: rotate(45deg);

为了浏览器的兼容性,有时候我们必须加入-webkit,-ms,-o,-moz这些前缀。目的就是让我们写的页面在每个浏览器中都可以顺利运行。

PostCSS
PostCSS是一个CSS的处理平台,它可以帮助你的CSS实现更多的功能,但是今天我们就通过其中的一个加前缀的功能,初步了解一下PostCSS。

安装

需要安装两个包postcss-loader 和autoprefixer(自动添加前缀的插件)

npm install –save-dev postcss-loader autoprefixer

postcss.config.js

postCSS推荐在项目根目录(和webpack.config.js同级),建立一个postcss.config.js文件。

postcss.config.js

1
2
3
4
5
module.exports = {
plugins: [
require('autoprefixer')
]
}

这就是对postCSS一个简单的配置,引入了autoprefixer插件。让postCSS拥有添加前缀的能力,它会根据 can i use 来增加相应的css3属性前缀。

编写loader

对postcss.config.js配置完成后,我们还需要编写我们的loader配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
test: /\.css$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader",
options: {
modules: true
}
}, {
loader: "postcss-loader"
}
]
}

提取CSS
配置提取CSS的loader配置.

1
2
3
4
5
6
7
8
9
10
{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader'
]
})
}

  1. 消除未使用的CSS
    像Bootstrap这样的框架往往会带有很多CSS。在项目中通常我们只使用它的一小部分。就算我们自己写CSS,随着项目的进展,CSS也会越来越多,有时候需求更改,带来了DOM结构的更改,这时候我们可能无暇关注CSS样式,造成很多CSS的冗余。

PurifyCSS

使用PurifyCSS可以大大减少CSS冗余,比如我们经常使用的BootStrap(140KB)就可以减少到只有35KB大小。这在实际开发当中是非常有用的。

安装PurifyCSS-webpack

从名字你就可以看出这是一个插件,而不是loader。所以这个需要安装还需要引入。 PurifyCSS-webpack要以来于purify-css这个包,所以这两个都需要安装。

npmn i -D purifycss-webpack purify-css

这里的-D代表的是–save-dev ,只是一个简写。

引入glob

因为我们需要同步检查html模板,所以我们需要引入node的glob对象使用。在webpack.config.js文件头部引入glob。

引入purifycss-webpack
同样在webpack.config.js文件头部引入purifycss-webpack

1
const PurifyCSSPlugin = `require`("purifycss-webpack");

配置plugins

引入完成后我们需要在webpack.config.js里配置plugins。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
plugins:[
//new uglify()
new htmlPlugin({
minify:{
removeAttrubuteQuotes:true
},
hash:true,
template:'./src/index.html'
}),
new extractTextPlugin("css/index.css"),
new PurifyCSSPlugin({
// Give paths to parse for rules. These should be absolute!
paths: glob.sync(path.join(__dirname, 'src/*.html')),
})
]

这里配置了一个paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了。

注意:使用这个插件必须配合extract-text-webpack-plugin这个插件

配置好上边的代码,我们可以故意在css文件里写一些用不到的属性,然后用webpack打包,你会发现没用的CSS已经自动给你删除掉了。在工作中记得一定要配置这个plugins,因为这决定你代码的质量,非常有用。

1.10 给webpack增加babel支持

Babel是什么?

Babel其实是一个编译JavaScript的平台,它的强大之处表现在可以通过便宜帮你达到以下目的:

  • 使用下一代的javaScript代码(ES6,ES7….),即使这些标准目前并未被当前的浏览器完全支持。

  • 使用基于JavaScript进行了扩展的语言,比如React的JSX。

Babel的安装与配置

Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析ES6的babel-preset-es2015包和解析JSX的babel-preset-react包)。

我们先一次性安装这些依赖包

cnpm c install –save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

在webpack中配置Babel的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
test:/\.(jsx|js)$/,
use:{
loader:'babel-loader',
options:{
presets:[
"es2015","react"
]
}
},
exclude:/node_modules/
}

现在你已经可以用webapck转换ES6的语法兼容各个浏览器了,我们可以修改一下entry.js的代码如下

1
2
3
4
5
import css from './css/index.css';
{
let jspangString = 'Hello Webpack'
document.getElementById('title').innerHTML=jspangString;
}

上面的代码使用了ES6的let声明方法。如果你不使用Babel来进行转换,你会发现打包出来的js代码没有作兼容处理,使用了Babel转换的代码是进行处理过的。

.babelrc配置

虽然Babel可以直接在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,如果卸载webapck.config.js中会非常的雍长不可阅读,所以我们经常把配置卸载.babelrc文件里。

在项目根目录新建.babelrc文件,并把配置写到文件里。

.babelrc

1
2
3
{
"presets":["react","es2015"]
}

.webpack.config.js里的loader配置

1
2
3
4
5
6
7
{
test:/\.(jsx|js)$/,
use:{
loader:'babel-loader',
},
exclude:/node_modules/
}

ENV:

现在网络上已经不流行babel-preset-es2015,现在官方推荐使用的是babel-preset-env

首先需要下载

npm n install –save-dev babel-preset-env

然后修改.babelrc里的配置文件。其实只要把之前的es2015换成env就可以了。

1
2
3
{
"presets":["react","env"]
}

2. Webpack应用

2.1 打包后如何调试

在使用webpack时只要通过简单的devtool配置,webapck就会自动给我们生产source maps 文件,map文件是一种对应编译文件和源文件的方法,让我们调试起来更简单。

在配置devtool时,webpack给我们提供了四种选项。

  • source-map:在一个单独文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;(source map只适用于开发阶段)
  • cheap-module-source-map:在一个单独的文件中产生一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便。
  • eval-source-map:使用eval打包源文件模块,在同一个文件中生产干净的完整版的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定要不开启这个选项。
  • cheap-module-eval-source-map:这是在打包文件时最快的生产source map的方法,生产的 Source map 会和打包后的JavaScript文件同行显示,没有影射列,和eval-source-map选项具有相似的缺点。

四种打包模式,有上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对执行和调试有一定的影响。

简单的配置:

1
2
3
4
5
6
7
8
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/app/main.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
}
}

2.2 开发和生产并行设置

依赖不同

一个项目中是有开发环境和生产环境的,这两个环境的依赖也是不同的。

  • 开发依赖:只在开发中用来帮助你进行开发,简化代码或者生成兼容设置的以来包。你可以打开package.json来查看,devDependencies的下面的这些包为开发使用的包。这些包在生产环境中并没有用处。

  • 生产依赖:就是比如我们的js使用了jquery,jquery的程序要在浏览器端起作用,也就是说我们最终的程序也需要这个包,这就是生产依赖。这些包在dependencies中。

假如我们要在项目中使用jquery库,这时候我们一般有三种安装方法

  • 第一种:

npm install jquery

安装完成后,你会发现在package.json中并不存在这个包的依赖。如果你项目拷贝给别人继续开发,或者别人和你git合作,再次下载项目npm install时就会缺少这个jquery包。项目就会无法正常运行,所以这也是我们最不赞成的安装方法。

  • 第二种:

npm n install jquery –save

安装完成后,它存在于package.json的dependencies中,也就是说它是生产环境需要依赖的包(上线时需要的依赖包)。

  • 第三种:

npm install jquery –save-dev

安装完成后,它存在于package.json的devDependencies中,也就是说它是开发环境中需要的,上线并不需要这个包的依赖。

安装全部项目依赖包:

npm install

安装生产环境依赖包

npm install –production

配置生产和开发并行

我们在以前的配置中设置了一个变量website,用于静态资源正确找到路径。那如果生产环境和开发环境不一样,而且我们需要来回切换,这时候我们需要更好的设置方法。

1
2
3
var website={
publicPath:"http://192.168.0.104:1717/"
}

修改package.json命令

其实就是添加一个dev设置,并通过环境变量来进行区分,下面是package.json里的值。

1
2
3
4
5
"scripts": {
"server": "webpack-dev-server --open",
"dev":"set type=dev&webapck",
"build": "set type=build&webpack"
},

修改webpack.config.js文件

可以利用node的语法来读取type的值,然后根据type的值用if–else判断。

1
2
3
4
5
6
7
8
9
if(process.env.type== "build"){
var website={
publicPath:"http://192.168.0.104:1717/"
}
}else{
var website={
publicPath:"http://****/"
}
}

Mac下的package.json设置

MAC电脑下需要把set换成export,并且要多加一个&符,具体代码如下

1
2
3
4
5
"scripts": {
"server": "webpack-dev-server --open",
"dev":"export type=dev&&webpack",
"build": "export type=build&&webpack"
},

2.3 webpack模块化配置

JS中的模块化实现

1
2
3
4
function jspang(){
alert('jspang.com:'+'webpack');
}
module.exports=jspang;

上面的代码是一个最简单的es6模块化写法,我们声明了一个jspang方法,并且把这个方法用module.exports进行暴露出去。然后我们在入口文件中用import进行引入,并进行使用。

1
2
import jspang from './jspang.js';
jspang();

我们了解如何作Javascript的模块化后,其实webpack的模块化和上边的过程很类似。

webpack模块

首先在根目录,新建一个webpack_config文件夹,然后新建entry_webpack.js文件,代码如下:

entry_webpack.js

1
2
3
4
5
6
7
8
//声明entry变量
const entry ={};
//声明路径属性
entry.path={
entry:'./src/entry.js'
}
//进行模块化
module.exports =entry;

配置的模块化代码编写好以后,需要在webpack.config.js中引入,注意这里的引入只能使用require的方法。

1
const entry = require("./webpack_config/entry_webpack.js")

然后在入口文件部分,修改成如下代码

1
entry:entry.path,

这时候你可以再次使用npm run dev 进行测试,你会发现模块化成功了。

2.4 打包第三方类库

引入JQuery

安装JQuery

npm install –save jquery

安装时需要注意的时Jquery最终要在生产环境中使用,所以我们这里要使用–save进行安装。

修改entry.js文件

安装好后,还需要引入到我们的entry.js中,这里直接使用import进行引入就可以。

import $ from ‘jquery’;

这里引入是不需要我们写相对路径的,因为jquery的包是在node_modules里的,只要写一个包名jquery,系统会自动为我们查找的。

引入好后我们就可以在entry.js里使用jquery,我们可以加入下面的代码,然后进行测试。

1
$('#title').html('Hello JSpang');

用plugin引入

如果你觉的上面的方法和webpack没什么关系,只是普通的引入,webpack只是负责了一下打包,这样并没有全局感。那再学习一种在webapck.config.js中配置的方法,这种不需要你在入口文件中引入,而是webpack给你作了全局引入。这个插件就是ProvidePlugin。

ProvidePlugin是一个webpack自带的插件,Provide的意思就是装备、提供。因为ProvidePlugin是webpack自带的插件,所以要先再webpack.config.js中引入webpack。

1
constc  webpack = require('webpack');

在webpack.config.js里引入必须使用require,否则会报错的

引入成功后配置我们的plugins模块,代码如下。

1
2
3
4
5
plugins:[
new webpack.ProvidePlugin({
$:"jquery"
})
],

配置好后,就可以在你的入口文件中使用了,而不用再次引入了。这是一种全局的引入,在实际工作中也可以很好的规范项目所使用的第三方库。

vue 最好这么引入

2.5 watch的正确使用方法

watch的配置

1
2
3
4
5
6
7
8
watchOptions:{
//检测修改的时间,以毫秒为单位
poll:1000,
//防止重复保存而发生重复编译错误。这里设置的500是半秒内重复保存,不进行打包操作
aggregateTimeout:500,
//不监听的目录
ignored:/node_modules/,
}

配置好后,我们就可以痛快的使用watch了,在大型项目中,这大大加快了我们的开发效率,不用反复的手动打包了。

最后更新: 2018年12月23日 21:20

原始链接: http://linjiad.github.io/2018/12/21/webpack3-X/

× 请我吃糖~
打赏二维码