抓住2019年的尾巴,迎接2020年的到来~
给自己的2019年画上一个完美的句号。
引言
webpack
对于现在的前端开发的你来说,不算陌生,你或许没有真正去了解过它是如何使用的,但你的项目中确实使用过它,因为你项目的打包编译都跟他息息相关~
前阵子刚好在研究webpack
以及其源码相关的知识,如果你跟我一样,好奇webpack
又是怎么工作的?那些奇奇怪怪的配置都是什么东西?分别代表什么意思?
那你不妨花几分钟阅读一下,跟我一起学习回顾一下如何从0到1去了解webpack
的知识, 配置你项目需要的webpack
~
pass
:本文以 webpack4
为例~
什么是webpack?
什么是 webpack
?
官方文档 是这么说:
webpack
是一个现代 JavaScript
应用程序的静态模块打包器(module bundler)
。当 webpack
处理应用程序时,它会递归地构建一个依赖关系图(dependency graph)
,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
。
其实,它就是一个模块化打包工具,它所做的事情就是分析你的项目结构,找到JavaScript
模块并对其进行代码转换(scss
转换为css
、Typescript
转换为 Javscript
),文件优化(压缩JavaScript
、CSS
、HTM
L、图片等),模块合并 (把模块分类合并成一个文件)等一系列的操作,最终打包为合适的格式在让你的项目可以在浏览器中运行~
盗用官网的一张图,其主要工作原理就如下图所示~
核心概念
在真正上手 webpack
之前,我们需要对其几个 核心概念 有所了解
-
Entry
:入口路径,webpack
执行构建的第一步的输入文件。 -
Module
:模块,在webpack
里一切皆模块,一个模块对应着一个文件,webpack
会从配置的Entry
开始递归找出所有依赖的模块。 -
Chunk
:代码块,一个Chunk
由多个模块组合而成,用于代码合并与分割。 -
Loader
:模块转换器,用于把模块原内容按照需求转换成新内容,例如scss
到css
的转换等,构建模块的第一步就是使用loader来加载并处理模块内容 -
Plugin
:扩展插件,webpack
的重要组成部分,其webpack
源码的很多核心功能也都是插件实现的,由于webpack
提供了在不同的生命周期内提供了很多不同的hooks
钩子函数,插件的工作原理就是在webpack
构建流程中的不同的(hooks
)时机注入扩展逻辑来改变构建结果或做个性化操作。 -
Output
:输出结果,在webpack
经过一系列处理后最终代码后输出配置。
整个流程串起来大概就是:
webpack
启动后会从Entry
里配置的Module
开始递归解析 Entry
依赖的所有 Module
。 每找到一个 Module
,就会根据配置的Loader
去找出对应的转换规则,对 Module
进行转换后,再解析出当前 Module
依赖的 Module
。
这些模块会以 Entry
为单位进行分组,一个 Entry
和其所有依赖的 Module
被分到一个组也就是一个Chunk
。最后 webpack
会把所有 Chunk
转换成文件输出,在这整个流程中 webpack
会在不同的生命周期内执行配置的 Plugin
里定义的逻辑。
了解了上面的一些概念和流程之后,接下来,我们一步步来配置,打包我们的项目~
初始化项目
创建文件夹
首先,我们创建一个你喜欢的文件夹,并通过 npm init -y
来初始化项目配置,并在其目录下创建一个我们源代码的目录src
和一个打包后的文件输入目录dist
。
创建入口文件 index.js
然后我们在 src
目录下创建一个 index.js
文件,作为我们的打包入口文件,并写上我们熟悉的 console.log('hello world');
作为打包内容。
安装webpack
webpack4
之后将 webpack
和 cli
分成了两个包,我们需要通过 npm install webpack webpack-cli -D
安装我们所需的 webpack
依赖。
ok~ 准备就绪!
遗憾的是,你还是不能直接进行打包,因为我们的 webpack
是在项目下安装的,所以不能直接运行,想要正确运行webpakc
我们可以有下面2种方式:
- 使用
npx
命令,可以直接运行node_modules/.bin
目录下的命令 - 通过配置
package.json
中的scripts
脚本命令进行执行
为了贴近我们的项目,这里我们选择第二种方式
配置package.json
脚本
我们打开package.json
文件,并在 scripts
中配置下面的代码:
"dev" : "webpack --mode development",
"build" : "webpack --mode production",
dev
表示开发模式,build
是生产模式,不同在于 dev
会有很多方便我们开发调试的功能,比如代码不压缩混淆,有开发服务器之类的,我们学习阶段采用 dev
即可~
创建配置文件
这时候,我们已经可以通过 npm run dev
命令打包我们的代码,并在dist
目录下看到我们打包后的 main.js
文件了~
你可能很诧异的蹦出一句:
因为到此,你发现自己什么都还没配置,咋就可以打包了!!
这是因为 webapck4
为了简化我们开发人员繁琐的配置工作,在内部写好了一套配置,惊不惊喜,意不意外!!
那我这肯定不能答应了,不然不就打我脸了么!
要想加载自己的配置,我们需要在我们的项目根目录下创建 webpack.config.js
文件,并创建我们的基础配置。
//path
const path = require('path');
//配置信息
module.exports = {
//入口文件
entry : './src/index.js' ,
//出口文件
output : {
//打包后路径,只能写绝对路径
path : path.resolve(__dirname,'dist'),
//打包后文件名
filename : '[name].[hash].js'
},
//模块转换规则
module : {
},
//插件
plugins : [
],
//开发服务器
devServer : {
}
}
我们注意到 output
中的 filename
中有一个 [name]
,[hash]
,其中name
是 entry
的名字,默认是 main
,hash
是打包根据内容后计算出的一个 hash
值,保证文件的唯一性,可以通过[hash:8]
表示取其前8位。
现在运行 npm run dev
在 dist
目录下就会打包出类似 main.47bfc309d4ba9b75d346.js
的文件。
这里,我们为了方便,先将其改成 main.js
创建index.html
文件
为了方便我们在浏览器测试,我们在我们的 dist
目录创建一个 index.html
,并引入我们编译好的main.js
文件,如下:
//index.html
<!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>webpack</title>
</head>
<body>
<div id="app">webpack</div>
<script src="main.js"></script>
</body>
</html>
我们在 index.js
文件下加上这么一句话:
document.querySelector('#app').style.color='red';
测试一下打包后的文件好不好使。
运行 npm run dev
,打开我们的 index.html
预览,不出意外的话,结果应该和我一样,页面的 webpack
文字变红,控制台输出 hello world
;
至此,我们才将我们的项目基础配置搞定~
加载css
如果我们现在想加入 css
文件,优化我的样式,首先在 src
目录下创建 stylesheets
目录,并添加 index.css
文件,我们就先以 body { background : #f2f2f2; }
为例,之后在 index.js
中通过 import './stylesheets/index.css'
的方式导入样式文件。
如果现在我们直接进行打包肯定会报错,因为 css
文件并不是 js
模块,webpack
在打包的时候没法直接处理,需要借助转换工具,这转换工具就是 Loader
。
- 什么是
Loader
?
Loader
就是文件转换器,通过使用不同的Loader
,webpack
就可以把不同的文件都转成js
文件,比如CSS
、ES6/7
、JSX
等,它通常有下面几个配置项:
-
test
:匹配处理文件的扩展名的正则表达式 -
use
:loader
名称,就是你要使用模块的名称 -
include/exclude
:手动指定必须处理的文件夹或屏蔽不需要处理的文件夹 -
query
:为loaders
提供额外的设置选项
接下来,我们来使用 style-loader
,css-loader
来处理我们的 css
文件。
执行 npm install style-loader css-loader -D
进行安装 loader
在 webpack.config.js
中的module
下面添加解析规则:
module : {
rules : [{
test : /\.css$/,
use : ['style-loader','css-loader']
}]
},
通常来说,loader
有下面三种书写方式,上面是通过 use
方式,还有两种方式分别是 直接使用 loader
和使用 use + loader
:
//直接使用loader
module: {
rules: [{
test: /\.css/,
loader:['style-loader','css-loader']
}]
}
//use + loader 的方式
module: {
rules: [{
test: /\.css/,
include: path.resolve(__dirname,'src'),
exclude: /node_modules/,
use: [{
loader: 'style-loader',
options: {
insert:'top'
}
},'css-loader']
}]
}
要注意的是配置多个 loader
是 有顺序 的,webpack
会安装配置的 loader
顺序 从右向左 执行的,配置的时候要格外注意!
拿我们上面的 style-loader
和 css-loader
来说,两个loader
配置的顺序不可调换,因为 css-loader
是解析处理css
里的url
路径,并将css
文件转换成一个模块,style-loader
是 将css
文件变成style
标签插入到head
中的。
现在我们 npm run dev
试试,打包没有报错,预览 index.html
也成功生效,很赞!
配置开发服务器
到此你有没有发现,我们在平时的开发过程中,怎么没有遇到说让我每次通过预览dist
下的 index.html
来看我们打包效果的,这是由于我们平时的开发中会在自己本地起一个服务器,来帮我们做这件事。
现在,我们也来试试~
- 通过
npm i webpack-dev-server –D
安装我们的开发服务器依赖 - 修改我们的启动脚本,将原来的
package.json
中的dev
脚本修改为webpack-dev-server --open
,其中--open
是自动打开浏览器的意思
此时,直接运行 npm run dev
是看不到我们预期的效果的,因为我们还没有对我们的服务器进行配置。
我们在 webpack.config.js
的 devServer
下添加如下配置:
devServer : {
contentBase : path.resolve(__dirname,'dist'),
host : 'localhost' ,
port : 8000 ,
compress : true
}
-
contentBase
配置开发服务运行时的文件根目录,也就是静态资源访问地址 -
host
开发服务器监听的主机地址 -
port
开发服务器监听的端口,默认是 8080 -
compress
开发服务器是否启动gzip
等压缩
ok,运行 npm run dev
,是不是效果非常棒!
要注意的是,webpack dev server
产生的打包文件是在 内存中!,是 内存中!,硬盘是访问不到的,怎么验证这一点呢?
很简单,你可以删除掉你dist
目录下的 main.js
,重新运行 npm run dev
,你可以看到 dist
目录下并没有 main.js
,但你访问 localhost:8000
确实能正确访问,并且访问 http://localhost:8000/main.js
也能看到打包后的源码,证明它产生的打包文件确实是在你的 内存中。
注意,我们这里打包出来的只有一个 main.js
文件和一个index.css
文件,index.html
文件是我们手动添加进去的,不是打包产生的,如果删掉 index.html
是无法正确访问页面的,内存里可没有 index.html
文件。
我们可以在终端看到以下这些内容:
这些都是我们在启动开发服务器的时候 webpack
给我们的页面注入的 websocket
连接,你可以在你的页面调试器的 network
中的 ws
里看到,
其重要作用就是,监控你文件的变化,可以帮助你重新刷新页面,让你看到更改后的效果,你可以修改一下 index.js
文件试试~
自动生产HTML文件
我们之前是在 dist
目录下写好了 index.html
文件,并在里面通过 script
标签引入我们打包后的内容,即 main.js
~
还记得我们之前打包后的 filename
中可以加入一个 hash
值也区别不同的文件,如果 hash
值发生变化了,我们的 index.html
岂不是找不到资源了?所以我们希望自动能产出HTML
文件,并在里面引入产出后的资源,这样就不必为上面的问题担心了。
我们删除掉 dist
目录下的 index.html
文件,并在 src
目录下创建一个 index.html
文件,我们称它为模板,以它为模板产生 html
文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>webpack</title>
</head>
<body>
<div id="app">webpack</div>
</body>
</html>
这时,我们需要接触到第一个插件 html-webpack-plugin
!
之前也说了,插件在 webpack
中有很重要的作用,在 webpack
的构建流程中,plugin
用于处理更多其他的一些构建任务,模块代码转换的工作由 loader
来处理,除此之外的其他任何工作都可以交由 plugin
来完成。
- 首先我们需要通过
npm install html-webpack-plugin -D
去安装它。 - 然后在
webpack.config.js
中plugins
下去配置它(需要先通过require
引入)
//自动产出HTML模版
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
hash: true,
minify: {
removeAttributeQuotes: true,
removeComments: true
}
})
其中 template
是指定模板文件,filename
是指定产出后的文件名,hash
是为了避免缓存,可以在产出的资源后面添加hash
值,minify
是 压缩相关的配置,minify.removeAttributeQuotes
是为了去掉属性的双引号,minify.removeComments
是为了压缩文件,删除模板中的注释。
此时,我们运行 npm run dev
访问 localhost:8000
发现已经可以正常访问了,但是 dist
目录下却没有任何东西,因为我们之前提到了,开发服务器打包的文件是写入内存中的,不是硬盘里。
为了方便我们看效果,我们在 package.json
中的 scripts
中在增加一行 "dev-build": "webpack --mode development"
用来打包我们开发环境的代码。
运行 npm run dev-build
脚本,完成之后可以发现 dist
目录已经打包出来了 index.html
文件 和 main.[hash].js
文件,打开 index.html
文件可以发现标签的双引号已经没去掉了,并且引入的脚本也自动加上了 ?[hash]
值。
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=UTF-8>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Title</title>
</head>
<body>
<div id=app>webpack</div>
<script type=text/javascript src=main.e6570abab6c2814d1608.js?e6570abab6c2814d1608></script></body>
</html>
预览 index.html
文件,一切也都正常。
pass
:webpack4
以后,如果你看到终端输入有下面这么怪异的一行,
而正巧你又是一个 强迫症患者,在 webpack.config.js
中添加 stats: { children: false }
即可。
支持图片
前端项目中肯定少不了图片资源,如果我们直接在 css
或者 js
文件中引入图片资源去打包,那么肯定是通不过了,因为 webpack
无法识别图片资源,因为图片也不是一个有效的模块。
此时,我们需要引入这个两个 loader
去解决它, file-loader url-loader
,file-loader
解决CSS
等文件中的引入图片路径问题,url-loader
当图片小于limit
的时候会把图片base64
编码,大于limit
参数的时候还是使用file-loader
进行拷贝
- 通过
npm install file-loader url-loader -D
下载依赖 - 在
src
目录下创建一个images
文件夹,存放几张你喜欢的图片 - 在
index.js
和index.css
中引入图片,并将其插入到页面中去(我这里以本地的avatar.jpg
和scene.jpg
为例)
//index.js
import Avatar from './images/avatar.jpg'
let img = new Image();
img.src = Avatar;
document.body.appendChild(img);
//index.css
body{
background-color: #f2f2f2;
background-image: url("../images/scene.jpg");
background-repeat: no-repeat;
}
- 在
webpack.config.js
中的module
下面添加如下配置
{
test:/\.(png|jpg|gif|svg|bmp)$/,
use:{
loader: 'url-loader',
options: {
limit: 10 * 1024,
outputPath: 'images/'
}
}
}
options
中的 limit
就是图片的限制,这里我指定的是 10kb
,小于 10kb
的图片会以 base64
编码输出,outputPath
指定了拷贝文件输出目录,默认是dist
目录下。
现在我们 npm run dev-build
走一波~
也不报错,运行 index.html
文件,也很正常!
编译less 和 sass
现在开发过程中,为了简化我们书写 css
的过程,我们一般项目中引入了 less
和 sass
这样的预加载器~
同样的你不处理之前 webpack
是不认识 less
和 sass
文件的,毕竟它不是一个 js
模块,我们通过需要借助 less-loader
和 sass-loader
来处理这些文件~
- 通过运行
npm install less less-loader -D
npm install node-sass sass-loader -D
分别安装loader
- 在
webpack.config.js
中添加loader
解析规则
{
test: /\.less/,
use: ['style-loader', 'css-loader', 'less-loader']
}, {
test: /\.scss/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
这样,你就可以放心在你的项目里引入 css
预处理了~
分离css
因为CSS
的下载和js
可以并行,当一个HTML
文件很大的时候,那么页面加载肯定会非常慢,那么我们希望可以把CSS
单独提取出来加载,为每个包含 CSS
的 JS
文件创建一个 CSS
文件,按需加载。
我们需要 mini-css-extract-plugin
这么一个插件
- 通过
npm install mini-css-extract-plugin -D
安装模块依赖 - 在
webpack.config.js
中plugins
下去配置一下
new MiniCssExtractPlugin({
filename: 'css/[name].[hash].css',
chunkFilename: "css/[id].css"
})
除此之外,我们的还需要做一个操作就是将我们之前处理css
的 style-loader
改写成下面这种形式:
{
test: /\.css$/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader']
},{
test: /\.less/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'less-loader']
}, {
test: /\.scss/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'sass-loader']
}
趁热打铁,赶紧来试试,npm run dev-build
进行打包~
预览 index.html
页面,打开控制台network
可以发现下载文件的时候多出了一个 main.css
文件,并且我们 html
的 head
头,已经换成了 link
方式,并且你的 dist
目录下会多出一个 css
的文件夹,里面存放打包后的 css
文件。
tips
: 如果你在外部的css
文件中文件中引入图片,而图片放在了images
目录下,那么打包上线后的图片会出现 404
的情况,你可以查看打包后的 css
文件,就可以反向是路径的问题,需要配置一下 publicPath
即可~
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '/'
}
}
注意,这个一般是在 服务器 上会出现,本地打包后没有起服务也是看不到的。
处理CSS3属性前缀
我们在书写 css
的时候,为了浏览器的兼容性,有时候我们必须加入-webkit
,-ms
,-o
,-moz
这些浏览器前缀,但我们又不想去书写这些繁琐的东西,这时候可以交给我们 postcss
来处理~
postcss
的主要功能只有两个:
- 第一个就是前面提到的把
CSS
解析成JavaScript
可以操作的 抽象语法树结构(Abstract Syntax Tree,AST)
- 第二个就是调用插件来处理
AST
并得到结果
我们首先通过 npm install postcss-loader autoprefixer -D
来安装依赖
想要这个 postcss
正常工作,我们需要配置两个东西
- 在根目录下创建
postcss.config.js
配置文件,表示使用autoprefixer
来进行补全
module.exports={
plugins:[require('autoprefixer')]
}
- 在
webpack.config.js
中修改并添加对css
处理的loader
{
test: /\.css$/,
use: [{
loader: MiniCssExtractPlugin.loader
}, 'css-loader', 'postcss-loader'],
include: path.join(__dirname, './src'),
exclude: /node_modules/
}
这里我在我的 index.css
中添加了如下测试代码:
//index.css
::placeholder {
color: orange;
}
并在我的 index.js
中创建了一个 input
控件:
//index.js
let input = document.createElement('input');
document.body.appendChild(input);
运行 npm run dev-build
打包,预览 index.html
,打开调试工具的的 sources
板块,查看 main.css
, 发现对应的前缀已添加,并且我页面的 input
已经变成了 orange
~
转义ES6/ES7
虽然 es6
和 es7
的代码我们已经或多或少都在项目中,但是大部分浏览器对于 es6
和 es7
代码的支持度并不高,很大部分的浏览器还是只能解析 es5
的代码,为了让我们能正常使用 es6
、es7
的代码,我们需要借助 webpack
对其进行转义,转成 es5
代码。
我们需要借助 babel
这个工具,它是一个编译JavaScript
的平台,可以把ES6/ES7
的代码转义为ES5
代码。
- 通过
npm install babel-loader @babel/core @babel/preset-env -D
安装依赖 - 在
webpack.config.js
中添加babel-loader
,因为babel-loader
只是告诉了webpack
怎么处理ES6
,ES7
代码,但它并不会将ES6
,ES7
代码翻译成向后兼容版本的代码,因此需要指定一个preset
,它包含了代码转换的规则
{
test: /\.js$/,
loader : 'babel-loader' ,
exclude:'/node_modules/'
}
- 在我们的项目根目录创建一个
.babelrc
的文件来配置,用来配置我们的babel
相关
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"> 1%",
"last 2 versions"
]
},
"debug":true //调试使用
}
]
]
}
- 我们在
index.js
文件中添加以下代码测试一下,并打包测试一下:
const test = (n)=> {
return new Promise(function (resolve) {
setTimeout(()=>{
resolve([1,2,3,4].map(v=>v * v ))
},n*1000)
}).then(res=>{
console.log(res);
})
}
console.log(test)
查看打包后的文件,发现转换的不够彻底,只能针对语法进行了转换,对于 Promise
、map
这些高级用法并没有被转换,这肯定是不行的,我们还要想办法把这些新的特性,兼容到低版本的浏览器里。
我们还需要 babel
提供的另一个工具—— polyfill
,
-
npm install @babel/polyfill -D
安装它 - 在我们的入口文件
index.js
最顶部添加import '@babel/polyfill'
- 运行
npm run dev-build
编译打包,虽然控制台好想没啥变化,但是我们的打包的文件main.js
发生了很大变化,很明显的一点,体积大了好几十倍
这是由于为了兼容低版本浏览器,polyfill
里面添加了很多辅助代码来帮助实现比如 Promise
和 map
这些新特性,默认情况下会被添加到每一个需要它的文件中,并且会全局注入,造成全局污染,如果我们在开发框架之类的,可能会发生冲突。
我们加了 debug
可以在终端看到,确实是加入了不少插件:
为了解决这个问题,我们引入 @babel/runtime
这个模块,来避免重复导入的问题
如果是写第三方库或者框架
- 运行
npm install @babel/runtime @babel/plugin-transform-runtime -D
安装模块依赖 - 配置
@babel/runtime
,并修改一下preset-env
的配置,加上useBuiltIns: 'usage'
,表示会根据业务需求自动转换需要转换的新语法
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"targets": {
"browsers": [
"> 1%",
"last 2 versions"
]
},
"debug":true //调试使用
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": true
}
]
]
}
- 配置完成,ok,我们再来运行
npm run dev-build
打包一次试试
终端日志可以看到注入的辅助代码大幅度较少,文件的大小也大幅度减少,赞!
拷贝静态文件
我们有些项目中的文件,不是 js
,也不是 css
, 图片之类的,比如 README.md
这些静态资源,我也希望能打包到我的项目里,怎么办呢?
其实就是文件的拷贝操作,我们只需要将这些文件拷贝到目标目录下即可,我们可以利用 copy-webpack-plugin
这个插件
- 运行
npm run copy-webpack-plugin -D
安装插件 - 在项目目录下创建一个
static/README.md
的测试文件 - 修改
webpack.config.js
, 将插件添加到配置里去
new CopyWebpackPlugin({
from: path.resolve(__dirname,'src/static'),
to:path.resolve(__dirname,'dist/static')
})
from
是静态资源目录源地址,to
是要拷贝文件的目标地址,so easy~
npm run dev-build
打包运行!
可以发现我们的 dist
目录已经将 src/static
的文件拷贝到了 dist/static
中
打包前清空
我们修改了文件之后,每次打包都会在 dist
目录下产生一个新的 main.[hash].js
, 随着我们打包次数的增加,dist
目录下会生产出一堆的 main.[hash].js
,不出意外,你的dist
目录应该已经有不少了~
为了保证我们每次看到的都是最新的打包资源,而不受之前打包文件的干扰,这里我们需要引入另一个插件—— clean-webpack-plugin
- 通过
npm install clean-webpack-plugin -D
下载插件 - 在
webpack.config.js
中plugins
下去配置它
plugins:[
new CleanWebpackPlugin()
]
pass
:该插件引入方式是稍微有点不同,通过以下这种方式引入:
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
现在,每次打包前都会先清空 dist
目录下的文件,然后才产出打包后的文件,这样看起来就清晰多了!
服务器代理
我们在开发时,有时候希望在同域名下发送 API
请求 ,那么代理某些 URL
会很有用,代理 API
的配置对于 webpack
来说,配置就非常简单了,只需要在 proxy
中添加代理规则即可
proxy : {
"/api/test": {
target: 'http://lohost:3000/',
secure: false,
changeOrigin: true,
pathRewrite: {
'^/api/test': '/test'
}
}
上面这行配置,就可以将 /api/test
开头的接口地址,会被代理到 http://localhost:3000/test
下,如果是https
接口,需要配置 secure
这个参数 为 true
,如果接口跨域,需要配置changeOrigin
这个参数为 true
压缩JS和CSS
我们现在打包出来的文件无论是 js
和 css
都是源文件,我们希望在打包的时候压缩我们的代码,一来是为了安全,二来是可以减少我们打包文件的体积。
我们选择使用terser-webpack-plugin
来压缩js
文件,替换掉之前的 uglifyjs-webpack-plugin
,解决uglifyjs
不支持es6
语法问题,使用 optimize-css-assets-webpack-plugin
来压缩 css
文件
- 运行
npm install terser-webpack-plugin optimize-css-assets-webpack-plugin -D
安装插件 - 在
webpack.config.js
中引入并配置插件
new TerserPlugin({
parallel: true,
cache: true
}),
new OptimizeCSSAssetsPlugin({
assetNameRegExp:/\.css$/g,
cssProcessor:require('cssnano')
})
TerserPlugin
中的 parallel
代表开启多进程,cache
代表设置缓存,OptimizeCSSAssetsPlugin
中加载了一个 cssnano
的东西, cssnano
是PostCSS
的CSS
优化和分解插件,会自动采用格式很好的CSS
,并通过许多优化,以确保最终的生产环境尽可能小。
现在我们在继续打包一次!
查看我们打包后的文件,可以发现 js
和 css
文件都没打包成了一行,搞定!
结语
ok~ 看到这里,想必你对 webpack
已经有了一个比较完善的认识,对常见的一些配置打包的 loader
或者 plugin
都有一定的了解了,总结会发现,套路基本都差不多,需要什么 loader
和 plugin
只要去对应去查找即可~
emmm
,其实 webpack
的功能非常强大,配置也是相当的多样化,这里只是列举了一些比较常见的功能,对你来说也只是一个抛砖引玉的作用,它的内部实现也是相当的复杂,想要真正弄懂 webpack
,还是需要多下一番苦功夫的~
对了,2019年还有几个小时就结束了~
2020年,加油~
网友评论