我的编程空间,编程开发者的网络收藏夹
学习永远不晚

webpack实现静态资源缓存的方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

webpack实现静态资源缓存的方法

引言

静态资源缓存是前端性能优化的一个点,所以在前端开发过程中,一般会最大限度的利用缓存(这里主要是强缓存)。回到本文主题,在使用webpack构建的项目中,稍有不慎的话,即使服务器设置了缓存策略,可能构建的项目无法实现静态资源缓存。那么webpack怎样才能达到使用缓存的效果呢,下面就来谈谈这个问题。

区分一下几种不同的hash

我们都知道,webpack有各种hash值,包括每次项目构建hash,不同入口的chunkhash、文件的内容contenthash,这么多hash,它们有什么区别呢?

hash

hash是跟整个webpack构建项目相关的,每次项目构建hash对应的值都是不同的,即使项目文件没有做“任何修改”。

其实是有修改的,因为每次webpack打包编译都会注入webpack的运行时代码,导致整个项目有变化,所以每次hash值都会变化的。

以本人项目代码为例,代码两次构建前后没有做任何修改的对比图

可以看出,前后两次对应项目构建hash改变了。由此推断使用该方式是无法达到缓存的,因为每次hash都会变化。

chunkhash

chunkhash,从字面上就能猜出它是跟webpack打包的chunk相关的。具体来说webpack是根据入口entry配置文件来分析其依赖项并由此来构建该entry的chunk,并生成对应的hash值。不同的chunk会有不同的hash值。一般在项目中把公共的依赖库和程序入口文件隔离并进行单独打包构建,用chunkhash来生成hash值,只要依赖公共库不变,那么其对应的chunkhash就不会变,从而达到缓存的目的。

一般在项目中对webpack的entry使用chunkhash,具体表现在output配置项上:


moudule.exports = {
  entry: {
   app: './class="lazy" data-src/main.js',
   vendor: ['react', 'redux', 'react-dom', 'react-redux', 'react-router-redux']
  },
  output: {
    path:path.join(__dirname, '/dist/js'),
    filename: '[name].[chunkhash].js'
  }
 ...
}

最后app和vendor的chunkhash编译结果如下图

contenthash

contenthash表示由文件内容产生的hash值,内容不同产生的contenthash值也不一样。在项目中,通常做法是把项目中css都抽离出对应的css文件来加以引用。比方在webpack配置这样来用:


module.exports = {
  ...
  plugins: [
     new ExtractTextPlugin({
	filename: 'static/[name]_[chunkhash:7].css',
	disable: false,
	allChunks: true
     })
  ...
  ]

上面配置有一个问题,因为使用了chunkhash,它与依赖它的chunk共用chunkhash。

比方在上面app chunk例子中依赖一个index.css文件,index.css的hash是跟着app的chunkhash走的,只要app文件变更的话,那么即使index.css文件没有变化,它的hash值也是会跟着变化的,导致缓存失效。

那么这时我们可以使用extra-text-webpack-plugin里的contenthash值,保证即使css文件所处的模块里就算其他文件内容改变,只要css文件内容不变,它的hash值就不会变。

实现js缓存

webpack插件CommonsChunkPlugin的主要作用是抽取webpack项目入口chunk的公共部分,具体的用法就不做过多介绍,不太了解可以参考webpack官网介绍;

该插件是webpack项目常用的一个优化功能,几乎在每个webpack项目中都会用到。使用该插件带来的好处:

  • 提升webpack打包速度和项目体积:将webpack入口的chunk文件中所有公共的代码提取出来,减少代码体积;同时提升webpack打包速度。
  • 利用缓存机制:依赖的公共模块文件一般很少更改或者不会更改,这样独立模块文件提取出可以长期缓存。

但是在项目中,若插件打开方式不正确的话,上面的第二点其实是无法实现,因为这种情况下:

没有被修改过的公有代码或库代码打包出的Entry Chunk,会随着其他业务代码的变化而变化,导致页面上的长缓存机制失效。

那么,下面就来开启CommonsChunkPlugin正确的打开方式。

CommonsChunkPlugin不正确用法

假如将我们项目的公共库如react、react-dom、react-router与业务代码隔离,将其提取为vendor chunk,webpack配置如下:


const webpack = require("webpack");
const path = require('path');
module.exports = {
  entry: {
    app: "./class="lazy" data-src/main.js",
    vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
  },
  output: {
    path: path.resolve(__dirname, 'output'),
    filename: "[name].[chunkhash].js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]})
  ]
};

上面将项目一些基础库打包成一个名为vendor的chunk中,并将业务相关的代码打包到一个名为app的chunk中;

webpack打包编译后的结果如下:

我们对其中的业务代码app.js进行修改后,重新编译结果如下:

可以发现,在CommonsChunkPlugin这种配置下,当业务代码app发生变化,而库代码也跟着变化,vender的chunkhash也跟着变化,这样vendor的引用的名称跟着变化,导致浏览器端的长缓存机制失效。

引起问题的原因

引起webpack每次打包编译时vendor跟着变化的原因:

webpack每次build的时候都会生成一些运行时代码。当只有一个文件时,运行时代码直接塞到这个文件中。当有多个文件时,运行时代码会被提取到公共文件中,也就是上面CommonsChunkPlugin配置的vendor chunk中。

webpack每次编译时产生的运行时代码,包括全局webpackJsonp方法的定义和维护模块依赖关系,具体可以参考这里>>。

所以,上面webpack的CommonsChunkPlugin配置中,每次编译时这些代码都会打包到vendor中,导致每次vendor的chunkhash每次都会变化。

那么,我们可以在对vendor chunk进行配置,抽取其中的公共代码,即webpack运行时代码,这样就可以将项目依赖的基础库模块与业务模块隔离开来,因为不会对这些文件进行修改,所以这些文件可达到长缓存的作用。具体配置如下:


module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
  },
  ....
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]}),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'manifest',
        chunks: ['vendor']
    })
  ]
};

这样,即使修改业务app代码,项目依赖的基础库vendor chunk也不会发生变化;只是抽取的manifest chunk每次还会变化,但是这个文件体积非常小,相比vendor来说这种方式的收益更大。如下图:

修改app代码后的打包编译结果如下,可以看到vendor的chunkhash没有变化

在webpack中配置CommonsChunkPlugin时需要注意几点:

1、 配置webpack的output项时,其filenamechunkFilename必须使用chunkhash。不要使用hash,否则即使按照上面的配置也不能达到预期的效果。至于hash与chunkhash的区别,可参考github的回答

2、对于图片、字体等静态资源抽离使用的file-loader,其配置的hash表示的是静态文件的内容hash值,不是webpack每次打包编译生成的hash值, 切记!!!

3、对于抽取的css样式文件,需要使用contenthash, 与file-loader中的hash意义相同。此处不能为chunkhash,否则其与抽取该样式文件的entry chunk的chunkhash保持一致,打不到缓存的目的。

实现css的缓存

webpack实现css的缓存,就是使用上面介绍过的contenthash,该hash属性值其实是extra-text-webpack-plugin计算的。具体实现css的缓存,其实就像下面一样使用contenthash即可


module.exports = {
  ...
  plugins: [
     new ExtractTextPlugin({
	filename: 'static/[name]_[contenthash:7].css',
	disable: false,
	allChunks: true
     })
  ...
  ]

实现图片/字体的缓存

对于图片、字体等静态资源,在使用webpack构建提取时,其实是使用了file-loader来完成的,生成对应的文件hash值也就是由对应的file-loader来计算的。那么这些静态文件的hash值使用的是什么hash值呢,其实就是hash属性值。如下面代码所示:


module.exports = {
 ...
 rules: [
   ...
    {
      test: /\.(gif|png|jpe?g)(\?\S*)?$/,
      loader: require.resolve('url-loader'),
      options: {
        limit: 10000,
        name: path.posix.join('static',  '[name]_[hash:7].[ext]')
      }
    },
    font: {
      test: /\.otf|ttf|woff2?|eot(\?\S*)?$/,
      loader: require.resolve('url-loader'),
      options: {
        limit: 10000,
        name: path.posix.join('static', '[name]_[hash:7].[ext]')
      }
    }
 ]
}

可以看到上面使用的是hash属性值,此hash非webpack每次项目构建的hash,它是由file-loader根据文件内容计算出来的,不要误认为是webpack构建的hash。

参考

1、webpack之CommonsChunkPlugin正确打开方式
2、webpack 填坑之路--提取独立文件(模块)
3、webpack代码分割技巧
4、听说你用webpack处理文件名的hash?那么建议你看看你生成的hash对不对
5、chunkhash
6、multiple-commons-chunks
7、用 webpack 实现持久化缓存
8、Webpack中hash与chunkhash的区别,以及js与css的hash指纹解耦方案

到此这篇关于webpack实现静态资源缓存的方法的文章就介绍到这了,更多相关webpack 静态资源缓存内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

webpack实现静态资源缓存的方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Nginx实现静态资源压缩的方法详解

Nginx可通过Gzip和Brotli算法压缩静态资源,以减少网络大小和提高页面加载速度。配置Nginx进行压缩需启用Gzip和Brotli,指定压缩类型和级别。现代浏览器普遍支持这些算法,并会在请求中发送支持的压缩类型,由Nginx根据头信息决定是否压缩响应内容。静态资源压缩可加快页面加载速度、节省带宽、提高服务器性能和改善用户体验。但要注意可能会消耗CPU资源,某些文件类型无法压缩,过度的压缩可能导致文件损坏。
Nginx实现静态资源压缩的方法详解
2024-04-02

CentOS搭建web服务器的动态缓存与静态资源优化

在CentOS上搭建Web服务器时,可以采取以下措施来进行动态缓存和静态资源优化:1. 使用缓存插件:安装和配置缓存插件,如Varnish或Nginx的反向代理缓存,可以将动态内容缓存起来,减少对后端服务器的请求压力。这些插件可以将频繁请求
2023-10-10

Spring Boot 读取静态资源文件的方法

一、需求场景有时候我们需要在项目中使用一些静态资源文件,比如城市信息文件 countries.xml,在项目启动后读取其中的数据并初始化写进数据库中。二、实现静态资源文件 countries.xml 放在 src/main/resource
2023-05-31

SpringBootsecurity默认拦截静态资源的解决方法

这篇文章主要介绍了SpringBootsecurity默认拦截静态资源,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-19

Nginx 禁用静态文件缓存的配置方法

Nginx禁用静态文件缓存方法:了解配置选项:expires、cache-control和proxy_cache_bypass。配置Nginx:在配置中添加代码,比如expires0或cache-control:no-cache。配置特定文件类型:使用proxy_cache_bypass指令针对特定文件类型禁用缓存。重新加载Nginx:sudoservicenginxreload。验证配置:使用curl-Ihttp://example.com/image.jpg检查响应头。
Nginx 禁用静态文件缓存的配置方法
2024-04-02

无需插件wordpress生成静态缓存文件的方法

说起wordpress生成静态缓存的话首先想到的就是WP Super Cache插件,确实如此,大多数的wordpress站长们都在使用. 但是永远都有那些纠结完美派的人,不喜欢用插件的人也十分的多,而今天介绍的非插件搞定wordpress
2022-06-12

linux服务器上使用nginx访问本地静态资源的方法

1.查看80端口是否被占用,一般80端口多被apache服务占用。 netstat -anp|grep 80 2.修改apache服务的端口号 vim /etc/apache2/ports.conf3.将
2022-06-04

防止SpringMVC拦截器拦截js等静态资源文件的解决方法

SpringMVC提供来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决:方案一、拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)<
2023-05-31

Android实现离线缓存的方法

离线缓存就是在网络畅通的情况下将从服务器收到的数据保存到本地,当网络断开之后直接读取本地文件中的数据。如Json 数据缓存到本地,在断网的状态下启动APP时读取本地缓存数据显示在界面上,常用的APP(网易新闻、知乎等等)都是支持离线缓存的
2022-06-06

编程热搜

目录