如何输出Webpack构建分析

输出Webpack构建信息的 .json文件:

webpack --profile --json > starts.json

说明:

  1. --profile:记录构建中的耗时信息。

  2. --json:以json格式输出构建结果,最后只输出一个json文件(包含所有的构建信息)。

web可视化查看构建分析

得到了webpack构建信息文件 starts.json,如何进行很好的可视化查看?

1、可视化分析工具Webpack Analyse

Webpack Analyse是个在线Web应用,上传 starts.json文件就可以。

2、webpack-bundle-analyzer

安装:

npm i -g webpack-bundle-analyzer

生成 starts.json后,直接在其文件夹目录执行

webpack-bundle-analyzer

浏览器会打开对应网页并展示构建分析文档地址webpack-bundle-analyzer。

3、webpack-dashboard

webpack-dashboard是一款统计和优化webpack日志的工具,可以以表格形势展示日志信息。其中包括构建过程和状态、日志以及涉及的模块列表。

4、jarvis

jarvis是一款基于webapck-dashboard的webpack性能分析插件,性能分析的结果在浏览器显示,比webpack-bundler-anazlyer更美观清晰GitHub文档地址。

安装:

npm i -D webpack-jarvis

webpack.config.js配置:

const Jarvis = require("webpack-jarvis");

plugins: [

new Jarvis({

watchOnly: false,

port: 3001 // optional: set a port

})

];

参数说明:

  • port:监听的端口,默认1337,监听面板将监听这个端口,通常像http://localhost:port/。

  • host:域名,默认localhost,不限制域名。

  • watchOnly:仅仅监听编译阶段。默认为true,如果高为false,jarvis不仅仅运行在编译阶段,在编译完成后还保持运行状态。

  • 界面:看到构建时间为: Time:11593ms(作为优化时间对比)。

webpack配置优化

webpack在启动时会从配置的Entry出发,解析出文件中的导入语句,再递归解析。

对于导入语句Webpack会做出以下操作:

  1. 根据导入语句寻找对应的要导入的文件;

  2. 在根据要导入的文件后缀,使用配置中的Loader去处理文件(如使用ES6需要使用babel-loader处理)。

针对这两点可以优化查找途径:

1、优化Loader配置

Loader处理文件的转换操作是很耗时的,所以需要让尽可能少的文件被Loader处理。

{

test: /\.js$/,

use: [

'babel-loader?cacheDirectory',//开启转换结果缓存

],

include: path.resolve(__dirname, 'src'),//只对src目录中文件采用babel-loader

exclude: path.resolve(__dirname,' ./node_modules'),//排除node_modules目录下的文件

},

2、优化resolve.modules配置

resolve.modules用于配置webpack去哪些目录下寻找第三方模块,默认是 ['node_modules'],但是,它会先去当前目录的 ./node_modules查找,没有的话再去 ../node_modules最后到根目录。

所以当安装的第三方模块都放在项目根目录时,就没有必要安默认的一层一层的查找,直接指明存放的绝对位置。

resolve: {

modules: [path.resolve(__dirname, 'node_modules')],

}

3、优化resolve.extensions配置

在导入没带文件后缀的路径时,webpack会自动带上后缀去尝试询问文件是否存在,而 resolve.extensions用于配置尝试后缀列表;默认为 extensions:['js','json']

当遇到 require('./data')时webpack会先尝试寻找 data.js,没有再去找 data.json;如果列表越长,或者正确的后缀越往后,尝试的次数就会越多。

所以在配置时为提升构建优化需遵守:

  1. 频率出现高的文件后缀优先放在前面。

  2. 列表尽可能的小。

  3. 书写导入语句时,尽量写上后缀名。

因为项目中用的 jsx较多,所以配置 extensions:[".jsx",".js"]

基本配置后查看构建速度: Time:10654ms,配置前为 Time:11593ms

使用DllPlugin优化

在使用webpack进行打包时候,对于依赖的第三方库,如react、react-dom等这些不会修改的依赖,可以让它和业务代码分开打包。

只要不升级依赖库版本,之后webpack就只需要打包项目业务代码,遇到需要导入的模块在某个动态链接库中时,就直接去其中获取;而不用再去编译第三方库,这样第三方库就只需要打包一次。

接入需要完成的事

  1. 将依赖的第三方模块抽离,打包到一个个单独的动态链接库中。

  2. 当需要导入的模块存在动态链接库中时,让其直接从链接库中获取。

  3. 项目依赖的所有动态链接库都需要被加载。

接入工具(webpack已内置)

  1. DllPlugin插件:用于打包出一个个单独的动态链接库文件。

  2. DllReferencePlugin:用于在主要的配置文件中引入 DllPlugin插件打包好的动态链接库文件。

配置webpack_dll.config.js,构建动态链接库

const path = require('path');

const DllPlugin = require('webpack/lib/DllPlugin');

module.exports = {

mode: 'production',

entry: {

// 将React相关模块放入一个动态链接库

react: ['react','react-dom','react-router-dom','react-loadable'],

librarys: ['wangeditor'],

utils: ['axios','js-cookie']

},

output: {

filename: '[name]-dll.js',

path: path.resolve(__dirname, 'dll'),

// 存放动态链接库的全局变量名,加上_dll_防止全局变量冲突

library: '_dll_[name]'

},

// 动态链接库的全局变量名称,需要可output.library中保持一致,也是输出的manifest.json文件中name的字段值

// 如react.manifest.json字段中存在"name":"_dll_react"

plugins: [

new DllPlugin({

name: '_dll_[name]',

path: path.join(__dirname, 'dll', '[name].manifest.json')

})

]

}

webpack.pro.config.js中使用

const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');

...

plugins: [

// 告诉webpack使用了哪些动态链接库

new DllReferencePlugin({

manifest: require('./dll/react.manifest.json')

}),

new DllReferencePlugin({

manifest: require('./dll/librarys.manifest.json')

}),

new DllReferencePlugin({

manifest: require('./dll/utils.manifest.json')

}),

]

注意:在 webpack_dll.config.js文件中, DllPlugin中的name参数必须和 output.library中的一致;因为 DllPlugin的name参数影响输出的 manifest.json的name;而 webpack.pro.config.js中的 DllReferencePlugin会读取 manifest.json的name,将值作为从全局变量中获取动态链接库内容时的全局变量名。

执行构建

  1. webpack--progress--colors--config./webpack.dll.config.js

  2. webpack--progress--colors--config./webpack.prod.js

html中引入dll.js文件。

构建时间对比: ["11593ms","10654ms","8334ms"]

HappyPack并行构建优化

核心原理:将webpack中最耗时的loader文件转换操作任务,分解到多个进程中并行处理,从而减少构建时间。

接入HappyPack:

  1. 安装: npm i-D happypack

  2. 重新配置 rules部分,将 loader交给 happypack来分配。

代码:

const HappyPack = require('happypack');

const happyThreadPool = HappyPack.ThreadPool({size: 5}); //构建共享进程池,包含5个进程

...

plugins: [

// happypack并行处理

new HappyPack({

// 用唯一ID来代表当前HappyPack是用来处理一类特定文件的,与rules中的use对应

id: 'babel',

loaders: ['babel-loader?cacheDirectory'],//默认设置loader处理

threadPool: happyThreadPool,//使用共享池处理

}),

new HappyPack({

// 用唯一ID来代表当前HappyPack是用来处理一类特定文件的,与rules中的use对应

id: 'css',

loaders: [

'css-loader',

'postcss-loader',

'sass-loader'],

threadPool: happyThreadPool

})

],

module: {

rules: [

{

test: /\.(js|jsx)$/,

use: ['happypack/loader?id=babel'],

exclude: path.resolve(__dirname,' ./node_modules'),

},

{

test: /\.(scss|css)$/,

//使用的mini-css-extract-plugin提取css此处,如果放在上面会出错

use: [MiniCssExtractPlugin.loader,'happypack/loader?id=css'],

include:[

path.resolve(__dirname,'src'),

path.join(__dirname, './node_modules/antd')

]

},

}

参数说明:

  1. threads:代表开启几个子进程去处理这一类文件,默认是3个。

  2. verbose:是否运行HappyPack输出日志,默认true。

  3. threadPool:代表共享进程池,即多个HappyPack示例使用一个共享进程池中的子进程去处理任务,以防资源占有过多。

代码压缩

用ParallelUglifyPlugin代替自带的UglifyJsPlugin插件。

自带的JS压缩插件是单线程执行的,而webpack-parallel-uglify-plugin可以并行的执行。

配置参数:

  1. uglifyJS:{}:用于压缩ES5代码时的配置,Object类型。

  2. test:/.js$/g:使用正则去匹配哪些文件需要被ParallelUglifyPlugin压缩,默认是 /.js$/

  3. include:[]:使用正则去包含被压缩的文件,默认为 []

  4. exclude:[]:使用正则去包含不被压缩的文件,默认为 []

  5. cacheDir:'':缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回,默认不会缓存,开启缓存设置一个目录路径。

  6. workerCount:'':开启几个子进程去并发的执行压缩。默认是当前运行电脑的CPU核数减去1。

  7. sourceMap:false:是否为压缩后的代码生成对应的Source Map,默认不生成。

代码:

...

minimizer: [

// webpack:production模式默认有配有js压缩,但是如果这里设置了css压缩,js压缩也要重新设置,因为使用minimizer会自动取消webpack的默认配置

new optimizeCssPlugin({

assetNameRegExp: /\.css$/g,

cssProcessor: require('cssnano'),

cssProcessorOptions: { discardComments: { removeAll: true } },

canPrint: true

}),

new ParallelUglifyPlugin({

cacheDir: '.cache/',

uglifyJS:{

output: {

// 是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,可以设置为false

beautify: false,

//是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false

comments: false

},

compress: {

//是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出

warnings: false,

//是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句

drop_console: true,

//是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 1, 默认为否

collapse_vars: true,

}

}

}),

]

构建结果对比: ["11593ms","10654ms","8334ms","7734ms"],整体构建速度从 12000ms降到现在的 8000ms

“积跬步,行千里”——持续更新中~喜欢的话留下个赞和关注哦!

往期经典好文

  • 你不知道的CORS跨域资源共享

  • Koa日志中间件封装开发(log4js)

  • 团队合作必备的Git操作

  • 使用pm2部署node生产环境


欢迎关注 SegmentFault 微信公众号 :)

webpack打包优化_Webpack 构建速度优化相关推荐

  1. 优酷 Android 构建速度优化实践

    作者:苏彦郊(木磊) Android 项目一般使用 gradle 作为构建打包工具,gradle 简洁.动态的功能特性为人津津乐道,同样,构建执行速度缓慢的缺陷也一直为人诟病. 近年来,随着优酷功能特 ...

  2. Gradle 构建速度优化

    构建速度优化 AS编译太慢是我们经常吐槽的,我们该做些什么来加快编译的速度呢?前面我们简单的了解了gradle构建项目的流程.我们可以从以下几个方面来做: 注意AS配置: 如及时更新Gradle和JD ...

  3. webpack打包测试_webpack入门笔记(一)

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency gr ...

  4. FPGA电子设计系统的资源优化(面积优化)与速度优化

    一.电子设计系统的面积优化与速度优化 1.资源优化: ①资源共享:针对数据通路中耗费逻辑资源较多的模块,通过选择.复用的方式共享使用该模块,达到减少资源使用.优化面积的目的: ②逻辑优化:使用优化后的 ...

  5. webpack打包原理_webpack打包原理入门探究(四)插件探究(上)

    子由风:webpack打包原理入门探究(一)​zhuanlan.zhihu.com 子由风:webpack打包原理入门探究(二)基本配置​zhuanlan.zhihu.com 子由风:webpack打 ...

  6. webpack打包缓存_webpack独立打包与缓存处理

    关于 微信公众号:前端呼啦圈(Love-FED) 我的博客:劳卜的博客 知乎专栏:前端呼啦圈 前言 先前写了一篇webpack入门的文章<webpack入门必知必会>,简单介绍了webpa ...

  7. Webpack构建性能优化指南

    本指南翻译自webpack官方性能指南文档:https://webpack.js.org/guides/build-performance/ 构建性能 本指南涵盖了对增进构建或编译性能的一些有效的提示 ...

  8. vs运行时 文本可视化工具 无法点开_webpack 优化:2 款工具帮你找到构建速度“变慢”的原因...

    前言 随着前端工程化的开发方式日益完善,像 webpack.rollup.gulp 等工具已经融入到我们的日常开发之中.最常见的就是 webpack ,一个模块打包工具. 但随着项目的功能需求迭代,代 ...

  9. webpack最新版本_webpack小结-开发环境构建优化

    刚刚对我们前端项目做了一顿分析优化操作,因为接手时每次构建要花两分钟左右的时间,实在忍受不了,只能动手了.通过这次优化,重新温习了下 webpack 的一些知识.接下来会关于 webpack 展开写几 ...

最新文章

  1. 一个关于debug的说明(摘自thinkingpython)
  2. 如何在Python中附加文件?
  3. 正则表达式(Regular Expressions)
  4. 信息系统项目管理师选择案例论文三方面考试心得分享
  5. python匿名函数lambda_python的匿名函数lambda解释及用法
  6. java中同步组件_Java并发编程(自定义同步组件)
  7. Git之集中式vs分布式
  8. Compass样式重置
  9. linux下数据库时间格式,Java编程时间格式与数据库中时间格式转化
  10. 【20171005】Luogu P1164 小A点菜
  11. 蓝桥杯 ADV-74 算法提高 计算整数因子
  12. linux应用对I2C设备驱动4种读写方法
  13. 3.nginx 的基本配置与优化
  14. 入云!离开张一鸣的字节,做出了第一个重大决定
  15. 台式计算机上的fn键是哪个,电脑键盘上Fn键到底有什么用?
  16. k8s部署tomcat及web应用_k8s介绍 k8s搭建一个应用(mysql+tomcat)
  17. 用旭日图展示数据的三种方法
  18. 【安卓开发系列 -- APP 】APP 性能优化 -- 崩溃分析
  19. Android4.1 如何实现状态栏上信号图标有SIM卡1,2标记,并且当处于2G状态显示“G”,处于3G状态显示“3G”
  20. 特斯拉Model Y被评为2022年最佳电动汽车;亚洲第50家希尔顿花园酒店于锦州开业 | 美通社头条...

热门文章

  1. String特殊值的判断方式
  2. 钩子教程 - 原理(一)
  3. 【原】数据分析/数据挖掘 入门级选手建议
  4. 项目管理与项目组合管理的不同
  5. Python办公自动化(六)|自动更新表格,
  6. Nginx 日志配置实践
  7. bat中冒号的作用(注释 ,跳转, 截取、替换字符串)
  8. 测试~在使用共通处理时,需要注意的问题 ~ 使用前,清空Form中的值。
  9. Ubuntu14.04 搜索不到WIFI或连接不上的解决方法。
  10. hadoop异常: java.io.EOFException: Unexpected end of input stream