本文介绍如何利用Webpack的contenthash生成唯一文件名,结合Express的no-cache与maxAge配置,实现index.html与静态资源的精确缓存。通过splitChunks提取第三方库,确保内容变更时仅更新受影响文件,其余资源长期缓存,从而显著提升网站加载性能。
精确缓存策略概述
针对近期开发的个人博客项目(采用Vue前端与Node后端),为了解决网络加载缓慢的问题,计划实施性能优化。本次优化的核心目标包括以下几个方面:
- 将 index.html 设置为 no-cache 策略。这样每次请求时,浏览器会检查 index.html 是否发生变化:若未变化则使用本地缓存,若已变化则获取最新的 index.html 文件。
- 对于其他所有静态资源文件,统一采用长周期缓存策略,例如设置缓存有效期为一年(maxAge: 1000 * 60 * 60 * 24 * 365)。
- 前端代码通过 webpack 进行打包,根据文件内容生成对应的文件名。每次重新打包时,只有内容发生变化的文件,其文件名才会随之改变。
综合上述三点配置,即可实现文件的精确缓存机制。
具体而言,在一年内若个人博客未进行任何更新,同一台电脑访问该网站时不会发起任何网络请求;若某个文件发生更新,浏览器仅请求新文件,旧文件仍从缓存中读取。
HTTP缓存头基础知识
相关缓存知识补充:
- max-age:用于设置缓存存储的最大周期,单位为秒。超过此时间后缓存被视为过期。在此时间之前,浏览器读取文件时不会发出新请求,而是直接使用缓存内容。
- no-cache:表示客户端可以缓存资源,但在每次使用缓存资源前,必须向服务器重新验证其有效性。
Webpack打包与文件名生成
Webpack 打包配置
根据文件内容生成唯一文件名
通过配置 output 对象的 filename 属性可实现此需求。在 filename 的值选项中,存在 [contenthash] 占位符,它将根据文件内容生成唯一的 hash 值。当文件内容发生变化时,[contenthash] 也会相应更新。
Webpack Output配置示例
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].js',
path: path.resolve(__dirname, '../dist'),
},
第三方库提取与SplitChunks配置
提取第三方库
由于引入的第三方库通常较为稳定,不常发生更改,因此将其单独提取出来作为长期缓存对象是更优的选择。此处需使用 webpack4 的 splitChunks 插件,并配置 cacheGroups 选项。
SplitChunks CacheGroups配置示例
optimization: {
runtimeChunk: {
name: 'manifest' // 将 webpack 的 runtime 代码拆分为一个单独的 chunk。
},
splitChunks: {
cacheGroups: {
vendor: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
},
}
},
- test:用于控制哪些模块被该缓存组匹配。若原封不动传递,默认选择所有模块。可传递的值类型包括 RegExp、String 和 Function。
- priority:表示抽取权重,数值越大优先级越高。由于一个 module 可能满足多个 cacheGroups 的条件,最终抽取到哪个组由权重最高的规则决定。
- reuseExistingChunk:表示是否使用已有的 chunk。若设为 true,则表示如果当前 chunk 包含的模块已被抽取出去,则不会重新生成新的 chunk。
- minChunks(默认值为1):在分割之前,该代码块最小应被引用的次数(旨在保证代码块复用性,默认配置策略下无需多次引用也可被分割)。
- chunks(默认值为async):可选值包括 initial、async 和 all。
- name(打包的chunks的名字):可以是字符串或者函数,函数可根据条件自定义名称。
除了提取第三方库外,结合 Vue 使用 import 动态引入组件,还能实现按需加载功能。
Express静态资源缓存设置
Express 服务器配置
Express中间件配置示例
app.use((req, res, next) => { // 将 index.html 设为 no-cache
if(req.url == '/') {
res.setHeader('Cache-control', 'no-cache')
}
next()
})
app.use(express.static('dist', {
etag: false,
maxAge: 1000 * 60 * 60 * 24 * 365, // 缓存一年
})) // 将dist设为根目录
详细实现代码可参考我的个人博客项目仓库。
参考资料
Webpack 缓存相关文档 逐步了解 webpack4 的 splitChunks 插件
至此,关于 webpack 与 express 实现文件精确缓存的示例代码介绍完毕。如需了解更多相关内容,请搜索本站历史文章或继续浏览后续文章,感谢大家的支持!