本项目源码都可在 这里 找到。css
以前公司的官网项目静态文件都是放在静态服务器中,这其中的弊端就不赘述了。简单说一下 CDN 的好处:html
CDN 能够解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。使用户可就近取得所需内容,解决 Internet 网络拥挤的情况,提升用户访问网站的响应速度和成功率。控制时延无疑是现代信息科技的重要指标,CDN 的意图就是尽量的减小资源在转发、传输、链路抖动等状况下顺利保障信息的连贯性。CDN 就是扮演者护航者和加速者的角色,更快准狠的触发信息和触达每个用户,带来更为极致的使用体验。
这里为了最小化演示路径,咱们只上传项目所用的 js 文件。且 CDN 基于七牛云。webpack
// webpack.config.js module.exports = { // 入口文件 entry: './src/app.js', // 打包出口 output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js', publicPath: 'http://example.clouddn.com/example/' // CDN 地址 } }
在 output.publicPath
中能够配置咱们的 CDN 地址(这里你要有一个七牛云的 帐户 )。以后咱们引入 qn-webpack。git
plugin 配置见该 plugin 源码便可。这里有一份示例配置:github
// webpack.config.js const qiniuWebpackPlugin = new QiniuWebpackPlugin({ accessKey: '七牛云我的面板 > 密钥管理 > AK', secretKey: '七牛云我的面板 > 密钥管理 > SK', bucket: '对象存储空间名', path: '空间内保存路径', exclude: /index\.html$/ // 须要排除上传的文件 }); module.exports = { // 加载插件 plugins: [ qiniuWebpackPlugin ] };
如今运行:web
npm run build # webpack --mode=production
在终端中咱们已经能够看到咱们的 js 文件被上传至本身的 CDN 服务中。经过 html-webpack-plugin 咱们引入 js 的路径也相应的替换成了 CDN 地址。npm
不少时候,在咱们的项目中,须要去:gulp
import url from './your/img/path'; <img src={url}>
图片挂上 CDN 也是颇有必要的,图片视频文件之类的东西自己就比较大并且能够算是静态的内容,从动态服务器上分离出去,能够极大的减少服务的负载。特别像是七牛云这样拥有图片处理引擎的服务商,咱们还能够经过 imageView2 来处理上传至 CDN 的图片。canvas
说回图片上传,首先咱们引入 file-loader ,Webpack 配置以下:api
// webpack.config.js module.exports = { module: { rules: [ { test: /\.(gif|png|jpe?g|svg|webp)$/i, use: [ { loader: 'file-loader', options: { // publicPath: 默认 `__webpack_public_path__` 为 `output.publicPath` } } ] } ] } }
file-loader 会指示 Webpack 将所需的对象做为文件引入并返回其公共 URL 。
再次运行:
npm run build # webpack --mode=production
两个文件已经被上传至 CDN ,且路径被替换。可是, 2.74 MiB
与后面的 [big]
非常鲜艳,下一步咱们须要压缩图片以减小文件体积。
以前咱们能够看看 Chrome 控制台:
2.7 MiB
的图片就算放在 CDN ,请求时间也超过了 100ms
,那么咱们开始处理图片。
引入 image-webpack-loader 并开始配置 Webpack :
//webpack.config.js module.exports = { module: { rules: [{ test: /\.(gif|png|jpe?g|svg|webp)$/i, use: [ { loader: 'file-loader', options: { // publicPath: 默认 `__webpack_public_path__` 为 `output.publicPath` } }, { loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false, }, pngquant: { quality: '65-90', speed: 4 }, gifsicle: { interlaced: false, }, WebP: { quality: 75 } } }, ], }] } }
详细配置参见 文档 。
再次打包:
发现图片大小从 2.74 MiB -> 1.16 MiB
虽然仍是有点大,可是已经有很明显的大小变化。再来看看 Chrome 控制台:
效果很明显 140 ms -> 43 ms
。
在进行这一步以前,须要简单了解一下什么是 WebP 格式图片。
目前移动端 Android 4.0 以上、PC 端 Chorme 10+(14 ~ 16 有渲染bug)、Opera 11+ 、Safri 均支持 WebP 格式图片。 WebP 与 jpg 相比较,编码速度慢 10 倍,解码速度慢 1.5 倍,而绝大部分的网络应用中,图片都是静态文件,因此对于用户使用只须要关心解码速度便可。但实际上,webp 虽然会增长额外的解码时间,可是因为减小了文件体积,缩短了加载的时间,实际上文件的渲染速度反而变快了。
搬运知乎上的一张图片:
因此咱们能够得出结论:WebP 体积大幅减小,图片质量也有保障,除了兼容性不太好。
对于兼容性,咱们能够看这张图:
考虑到兼容性的问题,咱们以后会进行专门处理。如今第一步则是转化 png & jpg -> Webp
。
这里选用 gulp 做为转化图片为 WebP 的自动化构建工具。Webpack 社区插件看 这里,我这里选用 gulp 做为构建工具也是但愿本身可以控制 WebP 图片的制做,在本地生成而不是 CI 打包时(时间有点长... 。
//gulpfile.js const gulp = require('gulp'); const webp = require('gulp-webp'); // 基于 cwebp 的 gulp 插件 // 基于 cwebp 转化图片 gulp.task('webp', () => gulp.src('src/img/*.{png,jpg,jpeg}') .pipe(webp({ quality: 75 })) // 详情配置见:https://github.com/imagemin/imagemin-webp#api .pipe(gulp.dest('src/img')) ); // 监听文件夹变化 gulp.task('watch', () => gulp.watch('src/img/*.{png,jpg,jpeg}', ['webp']) ); gulp.task('default', () => gulp.start('watch') );
配置以后咱们运行打包能够比较一下:
最后咱们在项目中使用 WebP 时候,须要判断一下浏览器是否支持 WebP 格式图片:
const canUseWebp = (() => { return document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') > -1; })() // 若是可使用 WebP ,则给顶部元素加上一个 class if (canUseWebp) { document.getElementsByTagName('body')[0].className += ' webp'; }
将这段 js 内联在 head 标签中后,咱们能够利用 CSS 预处理器来判断是否须要使用 WebP 格式图片。
// stylus bg($url, $type) background-image url($url + $type) .webp & // 若是拥有 .webp 类名,则使用 WebP 格式图片 background-image url($url + '.webp')
// less .mixin(@url, @type) { background-image: url(@{url}.@{type}); .webps & { background-image: url('@{url}.webp'); } }
// scss @mixin bg($url, $type) { background-image: url($url + $type); @at-root(with: all) .webps & { background-image: url($url + '.webp'); } }