ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 文件合并 ## 代码压缩 ### HTML压缩 ~~~ new HtmlWebpackPlugin({ template: __dirname + '/views/index.html', // new 一个这个插件的实例,并传入相关的参数 filename: '../index.html', minify: { removeComments: true, collapseWhitespace: true, removeRedundantAttributes: true, useShortDoctype: true, removeEmptyAttributes: true, removeStyleLinkTypeAttributes: true, keepClosingSlash: true, minifyJS: true, minifyCSS: true, minifyURLs: true, }, chunksSortMode: 'dependency' }) ~~~ 我们在使用html-webpack-plugin 自动化注入JS、CSS打包HTML文件时,很少会为其添加配置项,这里我给出样例,大家直接复制就行。 > 在我们书写HTML元素的src 或 href 属性时,可以省略协议部分,这样也能简单起到节省资源的目的。 > <br> ### 提取css并压缩 在使用webpack的过程中,我们通常会以模块的形式引入css文件(webpack的思想不就是万物皆模块嘛),但是在上线的时候,我们还需要将这些css提取出来,并且压缩,这些看似复杂的过程只需要简单的几行配置就行: > 们需要用到extract-text-webpack-plugin ,所以还得大家自行npm install > ~~~ const ExtractTextPlugin = require('extract-text-webpack-plugin') module: { rules: [..., { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: { loader: 'css-loader', options: { minimize: true } } }) }] } ~~~ <br> ### JS压缩 ~~~ new webpack.optimize.UglifyJsPlugin() ~~~ <br> ## 代码分割 ### 提取公共资源 ~~~ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'scripts/common/vendor-[hash:5].js' }) ~~~ > 这里是webpack3的语法,在webpack4中已作更改,希望大家注意 > 使用webpack3的新特性:ModuleConcatenationPlugin ~~~ new webpack.optimize.ModuleConcatenationPlugin() ~~~ <br> ### Tree-shaking Tree-shaking 是一种清理构建过程的方法通过只加载生产中实际使用的代码并清除 在 Webpack 中 未使用的 import。使用 Webpack 3 和 Rollup,我们还可以使用 scope hoisting(作用域提升),scope hoisting 允许工具检测哪些 import 可以被提升或者可以转换成一个内联函数。有了 Webpack 4,你现在可以使用 JSON Tree Shaking。UnCSS 或者 Helium 可以帮助你去删除未使用 CSS 样式。 <br> ### Code-splitting Code-splitting 是 Webpack 的另一个特性,可将你的代码分解为按需加载的“块”。并不是所有的 JavaScript 都是必须下载、解析和编译的。一旦你在代码中确定了分割点,Webpack 会处理这些依赖关系和输出文件。在应用发送请求的时候,这样基本上确保初始的下载足够小并且实现按需加载。 <br> ## 图片处理 ### css sprites雪碧图 <br> ### font-icon字体图标 iconfont字体文件是用字体编码的形式来实现图标效果,既然是文字,那就可以随意设置颜色设置大小,相对来说比sprite方案更好。但是它只适用于纯色图标。推荐使用 [阿里巴巴矢量图标库](https://link.jianshu.com/?t=http://iconfont.cn/) <br> ### 图片base64编码传输 webpack url-loader对未设置或者小于limit设置的图片进行转换,以base64的格式被 img 的 src 所使用;而对于大于limit byte的图片用file-loader进行解析 ~~~ { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, ~~~ 注意:cssnano压缩css的时候,对于部分规则的base64 uri不能识别,会出现误伤,如下图,cssnano压缩的时候会将//压缩为/: ![](https://box.kancloud.cn/fa8d1ae97a7105067d24cc29ebc46bb4_341x89.png) cssnano压缩base64 原因是:cssnano会跳过 data:image/data:application 后面的字符串,但是不会跳过 data:img ,所以如果你使用的工具生成的是 data:img ,建议换工具或者直接将其修改为 data:image 。 <br> ### SVG图片 <br> ### 图片压缩 <br> ### 使用WebP WebP格式,是谷歌公司开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook、Ebay等知名网站已经开始测试并使用WebP格式。 ![](https://box.kancloud.cn/eab718fe02428f71677481f523cde32c_1272x537.png) webp优化能在jpg的基础上再降低近50%的大小。其优化效果明显。此外,如果浏览器支持webpanimation,还能对gif做压缩。 ![](https://box.kancloud.cn/26352542c7af69d2bececdce729ca0c3_1000x84.png) ![](https://box.kancloud.cn/52c7ff235a70ec14740e51cbee4e11d5_1000x120.png) 实现方案: * 判断浏览器对webp及webpanimation的兼容性。 * 如果浏览器支持webp及webpanimation,将其替换成webp格式的图片。 鉴于浏览器对webp的支持比较局限,我们采用渐进升级的方式来优化:对于不支持webp的浏览器,不做处理;对于支持webp的浏览器,将图片src替换成webp格式。 ~~~ // 检测浏览器是否支持webp // 之所以没写成回调,是因为即使isSupportWebp=false也无大碍,但却可以让代码更容易维护 (function() { function webpTest(src, name) { var img = new Image(), isSupport = false, className, cls; img.onload = function() { isSupport = !!(img.height > 0 && img.width > 0); cls = isSupport ? (' ' + name) : (' no-' + name); className = document.querySelector('html').className className += cls; document.querySelector('html').className = className.trim(); }; img.onerror = function() { cls = (' no-' + name); className = document.querySelector('html').className className += cls; document.querySelector('html').className = className.trim(); }; img.src = src; } var webpSrc = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoB\ AAEAAwA0JaQAA3AA/vuUAAA=', webpanimationSrc = 'data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAA\ SAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAA\ AAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA'; webpTest(webpSrc, 'webp'); webpTest(webpanimationSrc, 'webpanimation'); })(); ~~~ 借鉴modernizr,实现了检测webp/webpanimation兼容性的函数,从代码中可以看出,检测原理就是模拟下载对应格式的图片,在异步函数中可以得到兼容性结果。 接下来就是替换url为webp格式 ~~~ // 获取webp格式的src function _getWebpSrc(src) { var dpr = Math.round(window.devicePixelRatio || 1), ratio = [1, 1, 1.5, 2, 2, 2], elHtml = document.querySelector('html'), isSupportWebp = (/(^|\s)webp(\s|$)/i).test(elHtml.className), isSupportWebpAnimation = (/(^|\s)webpanimation(\s|$)/i).test(elHtml.className), deviceWidth = elHtml.clientWidth, isQiniuSrc = /img\.qdaily\.com\//.test(src), format = _getFormat(src), isGifWebp, isNotGifWebp, regDetailImg; if (!src || !isQiniuSrc || !format || format == 'webp') { return src; } isNotGifWebp = (format != 'gif' && isSupportWebp); isGifWebp = (format == 'gif' && isSupportWebpAnimation); // 根据屏幕分辨率计算大小 src = src.replace(/\/(thumbnail|crop)\/.*?(\d+)x(\d+)[^\/]*\//ig, function(match, p0, p1, p2) { if(dpr > 1){ p1 = Math.round(p1 * ratio[dpr]); p2 = Math.round(p2 * ratio[dpr]); match = match.replace(/\d+x\d+/, p1 + 'x' + p2) } return match; }); if(isNotGifWebp || isGifWebp) { // 替换webp格式,首页/列表页 src = src.replace(/\/format\/([^\/]*)/ig, function(match, p1) { return '/format/webp'; }); } } ~~~ 注意事项 * window的屏幕像素密度不一定是整数,mac浏览器缩放之后,屏幕像素密度也不是整数。所以获取dpr一定要取整:dpr = Math.round(window.devicePixelRatio || 1);。 * ratio = [1, 1, 1.5, 2, 2, 2]表示:1倍屏使用1倍图,2倍屏使用1.5倍图,3倍屏以上都用2倍图。这儿的规则可以按实际情况来设置。 * webp优化更适合托管到第三方的图片,简单修改参数就可以获取不同的图片。 ![](https://box.kancloud.cn/0794a7af7691bdfd4b4a0ee90deef4c5_989x673.png) ![](https://box.kancloud.cn/6d771be0a95ec57f143c4154562a442c_989x1016.png) 如上所述,在对webp优化的时候,我们顺道模拟实现了srcset:根据屏幕像素密度来设置最适合的图片宽高。 <br> ### 响应式图片 尽可能通过 srcset,sizes 和 picture 元素使用 响应式图片。也可以通过 picture 元素使用 WebP 格式的图像(Chrome,Opera,Firefox soon支持),或者一个 JPEG 的回调(见 Andreas Bovens 的 code snippet)或者通过使用内容协商(使用 Accept 头信息)。 <br> ## 字体 首先需要问一个问题,你是否能不使用 UI 系统字体。 如果不可以,那么你有很大可能使用 Web 网络字体,会包含字形和额外的功能以及用不到的加粗。你可以向字体设计公司获取网络字体子集或子集,如果您使用的是开源字体(例如,通过仅包含带有某些特殊的重音字形的拉丁语),则可以只选择部分 Web 字体来减少其文件大小。 WOFF2 的支持非常好,对于不支持WOFF2的浏览器,你可以使用 WOFF 和 OTF 作为不支持它的浏览器的备选。另外,从 Zach Leatherman 的《字体加载策略综合指南》(代码片段也可以作为 Web字体加载片段)中选择一种策略,并使用服务器缓存持久地缓存字体。是不是感觉小有成就?Pixel Ambacht 有一个 快速教程和案例研究,让你的字体按顺序排列。 如果你无法从你的服务器拿到字体并依赖于第三方主机,请确保使用 字体加载事件(或对不支持它的浏览器使用 Web字体加载器)FOUT 要优于 FOIT; 立即开始渲染文本,并异步加载字体 —— 也可以使用 loadCSS。 你也可以 摆脱本地安装的操作系统字体,也可以使用 可变的 字体。 怎么才能是一个无漏洞的字体加载策略? 从 font-display 开始,然后到 Font Loading API,然后到 Bram Stein 的 Font Face Observer。如果你有兴趣从用户的角度来衡量字体加载的性能, Andreas Marschke 探索了 使用 Font API 和 UserTiming API 进行性能跟踪。 此外,不要忘记包含 font-display:optional 描述符来提供弹性和快速的字体回退,unicode-range 将大字体分解成更小的语言特定的字体,以及Monica Dinculescu 的字体样式匹配器 用来解决由于两种字体之间的大小差异,最大限度地减少了布局上的震动的问题。 参考资料 [网站性能优化实战——从12.67s到1.06s的故事](https://zhuanlan.zhihu.com/p/35224473) [2018 前端性能优化清单 - 掘金](https://juejin.im/post/5a966bd16fb9a0635172a50a#heading-1) [完整攻略!让你的网页加载时间降低到 1s 内! - 简书](https://www.jianshu.com/p/d857c3ff78d6)