本章节,我们一起来探讨以下问题:如何对编译后的文件进行gzip压缩,如何让开发环境的控制台输出更加高逼格,如何更好的对编译后的文件进行bundle分析等。

1 gzip压缩

如果你想节省带宽提高网站速度,压缩是一种简单有效的方法。我们模拟一次html的请求,想象一下浏览器和服务器的对话:

  1. 浏览器:嘿,给我来一个 index.html文件
  2. 服务器:好的,让我去找找它是不是在~
  3. 服务器:找到它了,我会返回一个成功的状态码(200 ok),我正在发送文件……
  4. 浏览器:100kb? 我滴天……等啊……等啊,好的,下载下来了

那现在问题在哪呢?

好吧,这系统是正常的,但是太低效了,坦白讲100kb是一大段的文字,HTML是冗余的,每一个标签都有一个几乎相同的闭合标签。虽然通篇文字都有重复,但是只要你砍掉任何的内容,html都不会正常显示。

当文件太大的时候有什么好办法呢,就是gzip压缩它。

如果我们传输一个替代原始大文件的zip的压缩文件给浏览器,就会节省带宽和下载时间。当浏览器可以下载zip文件,解压,并且渲染给用户。下载很快,页面加载也很快。现在,这个浏览器–服务器的会话大概是这样的:

  1. 浏览器:嘿,给我来一个index.html,如果要有,给我来一个压缩版的可以吗
  2. 服务器:容我找找……好,满足你
  3. 服务器:yep,找到了,马上传给你。
  4. 浏览器:太棒了,只有10kb,我来解压,并且渲染给用户。

情况很简单:文件越小,下载更快,用户感受更好。下面我们讲讲通过webpack如何对文件进行gzip压缩。

(1)前期准备

开启gzip压缩,需要在webpack配置文件中添加一个plugin,而我们希望把是否开启gzip压缩做成可配置化,也就是说,这个gzip的plugin可以选择添加也可以不添加。
我们在config.js中的build下添加一个配置项,取名为productionGzip

productionGzip:true,

另外,我们还需要修改下webpack.prod.conf.js。首先我们把原来export出来的配置对象放一个变量webpackConfig中,这样,我们可以后续访问的到plugins数组,并且可以追加plugin。稍微修改webpack.prod.conf.js,就像这样:

    const webpackConfig=merge(baseWebpackConfig, {
mode: 'production',
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash:16].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true,
cssModule:config.base.cssModule,
cssModuleExcludePath:config.base.cssModuleExcludePath
})
},
plugins: [
new HtmlWebpackPlugin({
template: config.build.index,
inject: 'body',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
}),
new CleanWebpackPlugin([config.build.assetsRoot], { allowExternal: true }), //导出css
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[hash].css'),
chunkFilename: utils.assetsPath('css/[id].[hash].css'),
}),
],
optimization: {
minimizer: [
new UglifyJSPlugin(),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: true
? {
map: { inline: false }
}
: {}
})
],
splitChunks: {
chunks: "all",
minChunks: ,
cacheGroups: {
framework: {
priority: ,
test: "framework",
name: "framework",
enforce: true,
reuseExistingChunk: true
},
vendor: {
priority: ,
test: /node_modules/,
name: "vendor",
enforce: true,
reuseExistingChunk: true
}
}
}
}
}); if (config.build.productionGzip) {
//添加gzip压缩插件
} module.exports = webpackConfig;
(2)添加gzip压缩插件

安装gzip插件:compression-webpack-plugin

npm i compression-webpack-plugin --save-dev
(3)使用插件

使用只要把CompressionWebpackPlugin的实例对象追加到plugins内即可。支持传入一个配置对象,相关说明:

  1. filename 压缩后的文件名
  2. algorithm 算法 默认gzip
  3. test 针对文件的正则表达式规则,符合规则的文件被压缩
  4. threshold 文件大于这个值的会被压缩
  5. minRatio 压缩率 默认0.8

要配置test,我们在config.js的build属性下新增加一个配置项,取名productionGzipExtensions,是一个数组,定义了那些后缀的文件要被压缩。

productionGzipExtensions: ['js', 'css'],

然后这样通过正则表达式:

    new RegExp('\\.(' +
config.build.productionGzipExtensions.join('|') +
')$')

配置的后缀会符合规则被gzip压缩。
在webpack.prod.conf.js详细的配置如下:

    if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: ,
minRatio: 0.8
})
)
}

执行命令查看:

npm run build

查看编译后生成的js,多了.gz文件,这个就是gzip压缩后的文件,把它们上传到服务器,并且服务器开启gzip的功能即可。

bundle分析工具
 
编译后,我们不能直观地知道那些组件被编译到哪些文件中。通过bundle分析工具,可以直观地看清楚这个问题。好处是帮助我们更好地优化代码和改进编译。
(1) 安装webpack-bundle-analyzer
npm install --save-dev webpack-bundle-analyzer
(2)配置是否启用的参数

在config.js文件的build属性下增加配置项bundleAnalyzerReport,用来表示是否开启分析。这个变量会不停修改,所以我们希望会在npm命令后面加上--report 就表示最后启动bundle分析,不加就不会启动bundle分析。怎么做?通过process.env.npm_config_report可以获取到npm命令的配置

bundleAnalyzerReport: process.env.npm_config_report
(3)使用

在webpack.prod.conf.js增加如下代码:

    if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
(4)执行命令

分别以下2个执行试试看吧

npm run build
npm run build --report

通过增加--report 编译成功后会启动Webpack Bundle Analyzer。默认是http://127.0.0.1:8888。你可以直观看到每个文件有哪些模块被编译进去。

美化终端的提示
 
在编译过程中,我们希望在终端能给出提示,编译成功给出我们自定义的一些说明。
(1)ora和chalk

这里需要介绍2个npm库。ora是一个能让你在终端提示状态的库,chalk是方便我们美化输出的文本。
我们先安装这2个库。

npm i --save-dev ora chalk
(2)修改编译的方法

看看我们原先的build方法,打开package.json,在scripts属性下找到build属性,可以看到它的值是
webpack --config build/webpack.prod.conf.js
通过webpack命令在终端去编译,我们无法获取webpack的编译状态,webpack还提供了webpack方法,通过webpack方法编译,编译结束可以执行回调函数。我们需要美化终端的显示,希望在编译中能显示编译的状态,编译结束提示编译成功,很有必要修改成通过webpack方法来编译。
在build目录下新增加一个build.js文件:内容如下:

    const ora = require('ora');
const chalk = require('chalk')
const webpack = require('webpack')
const webpackConfig = require('./webpack.prod.conf');
const spinner = ora('编译中...\n').start();
webpack(webpackConfig, function (err, stats) {
if (err) {
spinner.fail("编译失败");
console.log(err);
return;
}
spinner.succeed('编译已结束. \n'); process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n');
console.log(chalk.cyan(' 编译成功!\n'))
console.log(chalk.yellow(
' 提示: 编译后的文件可以上传并且部署到服务器\n' +
' 通过file:// 打开index.html不会起作用.\n'
))
})

stats是编译结束后webpack回调回来的参数,包含了编译后的文件信息。
修改package.json的build属性:

"build": "node build/build.js",

最后重新执行编译命令看看吧

npm run build

观察终端的输出,是不是漂亮了很多。当然你可以自己定制输出的内容。

【webpack系列】从零搭建 webpack4+react 脚手架(五)的更多相关文章

  1. 【webpack系列】从零搭建 webpack4+react 脚手架(一)

    搭建一个React工程的方式有很多,官方也有自己的脚手架,如果你和我一样,喜欢刨根究底,从零开始自己一行一行代码创建一个React脚手架项目,那你就来对地方了.本教程是针对React新手,以及对web ...

  2. 【webpack系列】从零搭建 webpack4+react 脚手架(四)

    经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架.如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦 ...

  3. 【webpack系列】从零搭建 webpack4+react 脚手架(三)

    本章节,我们对如何在脚手架中引入CSS,如何压缩CSS,如何使用CSS Modules,如何使用less,如何使用postcss等问题进行展开学习. 1 支持css (1)在app目录,新建一个css ...

  4. 【webpack系列】从零搭建 webpack4+react 脚手架(二)

    html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发 ...

  5. 从零搭建Spring Boot脚手架(1):开篇以及技术选型

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...

  6. 初探webpack之从零搭建Vue开发环境

    初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...

  7. 从零搭建Spring Boot脚手架(2):增加通用的功能

    1. 前言 今天开始搭建我们的kono Spring Boot脚手架,首先会集成Spring MVC并进行定制化以满足日常开发的需要,我们先做一些刚性的需求定制,后续再补充细节.如果你看了本文有什么问 ...

  8. 从零搭建Spring Boot脚手架(3):集成mybatis

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文集成了一些基础的功能,比如统一返回体.统一异常处理.快速类型转换.参数校验等常用必备功能,并编写了一些单元测试进行验证,今天 ...

  9. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...

随机推荐

  1. docker核心概念与配置安装

    一.Docker的三大核心概念: 镜像(image)  容器(container) 仓库(repository) 1.Docker镜像类是与虚拟机镜像,可以把它理解为一个只读的模板. 不仅仅是操作系统 ...

  2. .net core引用错误的Entity Framework而导致不能正常迁移数据的解决办法

    本人刚学.net core,因此在学习过程中会遇上许许多多的坑.每一位初学者最大的问题在于资料的查看不仔细或是没有正确理解里面的内容,导致在后面自己在不知道错误的情况下做了一个小动作.对于完全没有理解 ...

  3. [源码分析]StringBuffer

    [源码分析]StringBuffer StringBuffer是继承自AbstractStringBuilder的. 这里附上另外两篇文章的连接: AbstractStringBuilder : ht ...

  4. 关于 Microsoft Dynamics CRM has encountered an error 弹窗的问题

    最近用 IE 测试 CRM 网站的时候发现一个问题:时不时会弹出“Microsoft Dynamics CRM has encountered an error”的小框框,而且还不是在特定位置才会弹出 ...

  5. 分库分表后跨分片查询与Elastic Search

    携程酒店订单Elastic Search实战:http://www.lvesu.com/blog/main/cms-610.html 为什么分库分表后不建议跨分片查询:https://www.jian ...

  6. JavaScript表单验证的相关事件

    1.  表单元素: a)         Input标签:文本框(text)—密码框(password)—单选—复选框—文件—图像—隐藏—按钮—提交—重置,表单元素都在input标签 b)       ...

  7. C# - 设计模式 - 虚模式

    虚模式 问题场景 子类从抽象派生是为了解耦,但为了适应新的变化,可能需要向抽象类添加新功能,假如在添加新功能之前已经有100个子类实现了抽象,那么接下来你得在100个子类中去重写向抽象添加的新功能. ...

  8. [经验交流] CentOS7 docker 使用 overlay 存储

    关于 docker overlay 存储相比 device mapper 的优势,可以在 google 上搜索相关资料.在 ubuntu 16.04.2 上可以直接使用 overlay 存储,而在 C ...

  9. 2018-2019-20175315 实验一 《Java开发环境的熟悉》实验报告

    2018-2019-20175315实验一 <Java开发环境的熟悉>实验报告 一.实验内容及步骤 实验1 1.用mkdir建立“20175303exp1”的目录 2.在“20175303 ...

  10. 在windows下安装php redis扩展

    我在本地是phpstudy集成环境,但是没有redis扩展,需要自己安装 1.先看清楚自己的php配置,在安装对应的 php_redis.dll 和 php_igbinary.dll php_redi ...