本項目源碼都可在 這裏 找到。css
以前公司的官網項目靜態文件都是放在公司本身的靜態服務器中,這其中的弊端就不贅述了。簡單說一下 CDN 的好處:html
CDN 能夠解決因分佈、帶寬、服務器性能帶來的訪問延遲問題,適用於站點加速、點播、直播等場景。使用戶可就近取得所需內容,解決 Internet 網絡擁擠的情況,提升用戶訪問網站的響應速度和成功率。控制時延無疑是現代信息科技的重要指標,CDN 的意圖就是儘量的減小資源在轉發、傳輸、鏈路抖動等狀況下順利保障信息的連貫性。CDN 就是扮演者護航者和加速者的角色,更快準狠的觸發信息和觸達每個用戶,帶來更爲極致的使用體驗。webpack
這裏爲了最小化演示路徑,咱們只上傳項目所用的 js 文件。且 CDN 基於七牛雲。git
// 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。github
plugin 配置見該 plugin 源碼便可。這裏有一份示例配置:web
// webpack.config.js
const qiniuWebpackPlugin = new QiniuWebpackPlugin({
accessKey: '七牛雲我的面板 > 密鑰管理 > AK',
secretKey: '七牛雲我的面板 > 密鑰管理 > SK',
bucket: '對象存儲空間名',
path: '空間內保存路徑',
exclude: /index\.html$/ // 須要排除上傳的文件
});
module.exports = {
// 加載插件
plugins: [ qiniuWebpackPlugin ]
};
複製代碼
如今運行:npm
npm run build # webpack --mode=production
複製代碼
在終端中咱們已經能夠看到咱們的 js 文件被上傳至本身的 CDN 服務中。經過 html-webpack-plugin 咱們引入 js 的路徑也相應的替換成了 CDN 地址。gulp
不少時候,在咱們的項目中,須要去:canvas
import url from './your/img/path';
<img src={url}> 複製代碼
圖片掛上 CDN 也是頗有必要的,圖片視頻文件之類的東西自己就比較大並且能夠算是靜態的內容,從動態服務器上分離出去,能夠極大的減少服務的負載。特別像是七牛雲這樣擁有圖片處理引擎的服務商,咱們還能夠經過 imageView2 來處理上傳至 CDN 的圖片。api
說回圖片上傳,首先咱們引入 file-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`
}
}
]
}
]
}
}
複製代碼
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 格式後
最後咱們在項目中使用 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');
}
}
複製代碼
Amigooo 博客 地址