cdn
- qiniu
CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速资源的获取速度。
HTML文件不缓存,放在自己的服务器上,关闭自己服务器的缓存,静态资源的URL变成指向CDN服务器的地址
- 静态的JavaScript、CSS、图片等文件开启CDN和缓存,并且文件名带上HASH值
为了并行加载不阻塞,把不同的静态资源分配到不同的CDN服务器上
哪些需要缓存
由于 CDN 服务一般都会给资源开启很长时间的缓存,例如用户从 CDN 上获取到了 index.html 这个文件后, 即使之后的发布操作把 index.html 文件给重新覆盖了,但是用户在很长一段时间内还是运行的之前的版本,这会导致新的发布不能立即生效 解决办法
- 针对 HTML 文件:不开启缓存,把 HTML 放到自己的服务器上(怎么配置自己的html到服务器上?),而不是 CDN 服务上,同时关闭自己服务器上的缓存。自己的服务器只提供 HTML 文件和数据接口。
- 针对静态的 JavaScript、CSS、图片等文件:开启 CDN 和缓存,上传到 CDN 服务上去,同时给每个文件名带上由文件内容算出的 Hash 值
- 带上 Hash 值的原因是文件名会随着文件内容而变化,只要文件发生变化其对应的 URL 就会变化,它就会被重新下载,无论缓存时间有多长。
启用CDN之后 相对路径,都变成了绝对的指向 CDN 服务的 URL 地址
域名限制
同一时刻针对同一个域名的资源并行请求是有限制
- 可以把这些静态资源分散到不同的 CDN 服务上去
- 多个域名后会增加域名解析时间
- 可以通过在 HTML HEAD 标签中 加入去预解析域名,以降低域名解析带来的延迟
接入CDN
要给网站接入 CDN,需要把网页的静态资源上传到 CDN 服务上去,在服务这些静态资源的时候需要通过 CDN 服务提供的 URL 地址去访问 ```javascript {output: {path: path.resolve(__dirname, 'dist'),
- filename: ‘[name]_[hash:8].js’,
- publicPath: ‘http://img.zhufengpeixun.cn‘
},
}
```
文件指纹
- 打包后输出的文件名和后缀
- hash一般是结合CDN缓存来使用,通过webpack构建之后,生成对应文件名自动带上对应的MD5值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的HTML引用的URL地址也会改变,触发CDN服务器从源服务器上拉取对应数据,进而更新本地缓存。
指纹占位符
| 占位符名称 | 含义 |
|---|---|
| ext | 资源后缀名 |
| name | 文件名称 |
| path | 文件的相对路径 |
| folder | 文件所在的文件夹 |
| hash | 每次webpack构建时生成一个唯一的hash值 |
| chunkhash | 根据chunk生成hash值,来源于同一个chunk,则hash值就一样 |
| contenthash | 根据内容生成hash值,文件内容相同hash值就相同 |
用 Webpack 实现 CDN 的接入
总结上面所说的,构建需要实现以下几点:
- 静态资源的导入 URL 需要变成指向 CDN 服务的绝对路径的 URL 而不是相对于 HTML 文件的 URL。
- 静态资源的文件名称需要带上有文件内容算出来的 Hash 值,以防止被缓存。
- 不同类型的资源放到不同域名的 CDN 服务上去,以防止资源的并行加载被阻塞。
先来看下要实现以上要求的最终 Webpack 配置:
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const {WebPlugin} = require('web-webpack-plugin');
module.exports = {
// 省略 entry 配置...
output: {
// 给输出的 JavaScript 文件名称加上 Hash 值
filename: '[name]_[chunkhash:8].js',
path: path.resolve(__dirname, './dist'),
// 指定存放 JavaScript 文件的 CDN 目录 URL
publicPath: '//js.cdn.com/id/',
},
module: {
rules: [
{
// 增加对 CSS 文件的支持
test: /\.css$/,
// 提取出 Chunk 中的 CSS 代码到单独的文件中
use: ExtractTextPlugin.extract({
// 压缩 CSS 代码
use: ['css-loader?minimize'],
// 指定存放 CSS 中导入的资源(例如图片)的 CDN 目录 URL
publicPath: '//img.cdn.com/id/'
}),
},
{
// 增加对 PNG 文件的支持
test: /\.png$/,
// 给输出的 PNG 文件名称加上 Hash 值
use: ['file-loader?name=[name]_[hash:8].[ext]'],
},
// 省略其它 Loader 配置...
]
},
plugins: [
// 使用 WebPlugin 自动生成 HTML
new WebPlugin({
// HTML 模版文件所在的文件路径
template: './template.html',
// 输出的 HTML 的文件名称
filename: 'index.html',
// 指定存放 CSS 文件的 CDN 目录 URL
stylePublicPath: '//css.cdn.com/id/',
}),
new ExtractTextPlugin({
// 给输出的 CSS 文件名称加上 Hash 值
filename: `[name]_[contenthash:8].css`,
}),
// 省略代码压缩插件配置...
],
};
以上代码中最核心的部分是通过 publicPath 参数设置存放静态资源的 CDN 目录 URL, 为了让不同类型的资源输出到不同的 CDN,需要分别在:
- output.publicPath 中设置 JavaScript 的地址。
- css-loader.publicPath 中设置被 CSS 导入的资源的的地址。
- WebPlugin.stylePublicPath 中设置 CSS 文件的地址。
设置好 publicPath 后,WebPlugin 在生成 HTML 文件和 css-loader 转换 CSS 代码时,会考虑到配置中的 publicPath,用对应的线上地址替换原来的相对地址。
