webpack性能优化

webpack输出质量优化

  • 开启gzip优化。gizp是一种HTTP请求优化的方式,通过减少文件体积下载来提高加载的速度。
传送门二:https://www.jb51.net/article/148254.htm
传送门二:https://www.cnblogs.com/zs-note/p/9556390.html
  • 使用CDN加速静态资源加载
    用法:CDN通过将资源部署到世界各地,使得用户可以就近访问资源,加快访问速度。要接入CDN,需要把网页的静态资源上传到CDN服务上,在访问这些资源时,使用CDN服务提供的URL。
    由于CDN会为资源开启长时间的缓存,例如用户从CDN上获取了index.html,即使之后替换了CDN上的index.html,用户那边仍会在使用之前的版本直到缓存时间过期。业界做法:
    HTML文件:放在自己的服务器上且关闭缓存,不接入CDN
    静态的JS、CSS、图片等资源:开启CDN和缓存,同时文件名带上由内容计算出的Hash值,这样只要内容变化hash就会变化,文件名就会变化,就会被重新下载而不论缓存时间多长。
    另外,HTTP1.x版本的协议下,浏览器会对于向同一域名并行发起的请求数限制在4~8个。那么把所有静态资源放在同一域名下的CDN服务上就会遇到这种限制,所以可以把他们分散放在不同的CDN服务上,例如JS文件放在js.cdn.com下,将CSS文件放在css.cdn.com下等。这样又会带来一个新的问题:增加了域名解析时间,这个可以通过dns-prefetch来解决 来缩减域名解析的时间。形如**//xx.com 这样的URL省略了协议**,这样做的好处是,浏览器在访问资源时会自动根据当前URL采用的模式来决定使用HTTP还是HTTPS协议。
    总之,构建需要满足以下几点:
    静态资源导入的URL要变成指向CDN服务的绝对路径的URL
    静态资源的文件名需要带上根据内容计算出的Hash值
    不同类型资源放在不同域名的CDN上

    配置如下:

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const {WebPlugin} = require('web-webpack-plugin');
//...
output:{
 filename: '[name]_[chunkhash:8].js',
 path: path.resolve(__dirname, 'dist'),
 publicPatch: '//js.cdn.com/id/', //指定存放JS文件的CDN地址
},
module:{
 rules:[{
     test: /\.css/,
     use: ExtractTextPlugin.extract({
         use: ['css-loader?minimize'],
         publicPatch: '//img.cdn.com/id/', //指定css文件中导入的图片等资源存放的cdn地址
     }),
 },{
    test: /\.png/,
    use: ['file-loader?name=[name]_[hash:8].[ext]'], //为输出的PNG文件名加上Hash值 
 }]
},
plugins:[
  new WebPlugin({
     template: './template.html',
     filename: 'index.html',
     stylePublicPath: '//css.cdn.com/id/', //指定存放CSS文件的CDN地址
  }),
 new ExtractTextPlugin({
     filename:`[name]_[contenthash:8].css`, //为输出的CSS文件加上Hash
 })

  • 为第三方文件单独打包,增加文件的并发下载量(对于单个域名,http)
一:使用script引入第三方文件资源
二:使用splitChunks来对第三方文件进行分割
  • :暴漏第三放文件(第三方库的使用)
方法一:直接引用
方法二:使用imports-loader
方法三:直接在html模板文件中引入
方法四:使用providePlugin
传送门:https://www.codercto.com/a/60936.html
  • 打包文件分析详述
https://javascript.ctolib.com/webpack-bundle-analyzer.html
stat size:文件初始状态大小
parsed size :文件解析的大小
gzip size:文件经过压缩后的大小
  • 优化打包文件的体积
 对文件进行按需加载。
 比如lodash我们可能只是需要用到其中的几个方法,那么我们就可以使用import _defaults from 'lodash'
 这样文件就会显著减小
  • 使用Scope Hoisting
    用法:译作“作用域提升”,是在Webpack3中推出的功能,它分析模块间的依赖关系,尽可能将被打散的模块合并到一个函数中,但不能造成代码冗余,所以只有被引用一次的模块才能被合并。由于需要分析模块间的依赖关系,所以源码必须是采用了ES6模块化的,否则Webpack会降级处理不采用Scope Hoisting。
    传送门:https://blog.csdn.net/u014399368/article/details/100095919
    代码:
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
//...
plugins:[
    new ModuleConcatenationPlugin();
],
resolve:{
	mainFields:['jsnext:main','browser','main']
}

开发过程优化体验

  • DevServer刷新浏览器有两种方式:
    向网页中注入代理客户端代码,通过客户端发起刷新
    向网页装入一个iframe,通过刷新iframe实现刷新效果
    默认情况下,以及 devserver: {inline:true} 都是采用第一种方式刷新页面。第一种方式DevServer因为不知道网页依赖哪些Chunk,所以会向每个chunk中都注入客户端代码,当要输出很多chunk时,会导致构建变慢。而一个页面只需要一个客户端,所以关闭inline模式可以减少构建时间,chunk越多提升月明显。关闭方式:
    启动时使用webpack-dev-server --inline false
    配置 devserver:{inline:false}

另外devServer.compress 参数可配置是否采用Gzip压缩,默认为false

构建过程优化

使用loader优化
  • 一:cache-loader
    用法:在一些性能开销较大的 loader 之前添加此 loader,以将结果缓存到磁盘里。】
    传送门:https://cloud.tencent.com/developer/section/1477510

  • 二:Happypack
    用法:由于有大量文件需要解析和处理,构建是文件读写和计算密集型的操作,特别是当文件数量变多后,Webpack 构建慢的问题会显得严重。
    传送门:https://juejin.im/post/5ca224f751882543d65285ed

  • 三:thread-loader
    用法:把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker 池(worker pool)中运行,请仅在耗时的 loader 上使用
    传送门:https://blog.csdn.net/a5534789/article/details/88778024,https://cloud.tencent.com/developer/section/1477543

  • 四:DLLplugin
    用法:【不重复打包第三方库,较少打包第三方库的时间,将第三方模块抽离出来】
    原理:DllPlugin动态链接库插件,其原理是把网页依赖的基础模块抽离出来打包到dll文件中,当需要导入的模块存在于某个dll中时,这个模块不再被打包,而是去dll中获取。为什么会提升构建速度呢:原因在于dll中大多包含的是常用的第三方模块,如react、react-dom,所以只要这些模块版本不升级,就只需被编译一次。我认为这样做和配置resolve.alias和module.noParse的效果有异曲同工的效果。
    传送门:https://www.jb51.net/article/142761.htm,https://segmentfault.com/a/1190000018820505

使用plugin优化

  • webpack-parallel-uglify-plugin
    用法:使用UglifyJS插件压缩JS代码时,需要先将代码解析成Object表示的AST(抽象语法树),再去应用各种规则去分析和处理AST,所以这个过程计算量大耗时较多。ParallelUglifyPlugin可以开启多个子进程,每个子进程使用UglifyJS压缩代码,可以并行执行,能显著缩短压缩时间。JS中的whappyPack
    传送门
webpack内部语法优化
  • 一:module.noParse
    用法:告诉webpack某些库中并没有引入其他的文件,不需要再去解析
    传送门

搜索过程优化

  • 一:resolve.modules:[path.resolve(__dirname, ‘node_modules’)]
    用法:避免webpack层层去查找webpack模块,resolve.modules告诉webpack去哪些目录下寻找第三方模块,默认值为[‘node_modules’],会依次查找./node_modules、…/node_modules、…/…/node_modules。
    传送门一
    传送门二

  • 二:resolve.mainFields:[‘main’]
    用法:设置尽量少的值可以减少入口文件的搜索步骤,第三方模块为了适应不同的使用环境,会定义多个入口文件,mainFields定义使用第三方模块的哪个入口文件,由于大多数第三方模块都使用main字段描述入口文件的位置,所以可以设置单独一个main值,减少搜索。
    传送门一
    传送门二

  • 三:resolve.alias
    用法:使webpack直接使用库的min文件,避免库内解析,这样会影响Tree-Shaking,适合对整体性比较强的库使用,如果是像lodash这类工具类的比较分散的库,比较适合Tree-Shaking,避免使用这种方式。
    传送门一
    传送门二

  • 四:resolve.extensions
    用法:默认值:extensions:[’.js’, ‘.json’],当导入语句没带文件后缀时,Webpack会根据extensions定义的后缀列表进行文件查找,所以:

列表值尽量少
频率高的文件类型的后缀写在前面
源码中的导入语句尽可能的写上文件后缀,如require(./data)要写成require(./data.json)

otherTip

配置babel-loader时,use: [‘babel-loader?cacheDirectory’] cacheDirectory用于缓存babel的编译结果,加快重新编译的速度。另外注意排除node_modules文件夹,因为文件都使用了ES5的语法,没必要再使用Babel转换。

配置externals,排除因为已使用

配置performance参数可以输出文件的性能检查配置。

配置profile:true,是否捕捉Webpack构建的性能信息,用于分析是什么原因导致构建性能不佳。

配置cache:true,是否启用缓存来提升构建速度。

可以使用url-loader把小图片转换成base64嵌入到JS或CSS中,减少加载次数。

通过imagemin-webpack-plugin压缩图片,通过webpack-spritesmith制作雪碧图。

开发环境下将devtool设置为cheap-module-eval-source-map,因为生成这种source map的速度最快,能加速构建。在生产环境下将devtool设置为hidden-source-map

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值