Open cpselvis opened 4 years ago
点个赞
厉害了
厉害了
ejs 语法是 <%= %> 不是 ${},这里要修改一下
我这边发现一个问题,产生的css产物中,backgroud:url(../img/bg.png)
原封不动的内联到了html中,而html和img文件夹是并列关系,所以会出现找不到图片的情况; 请问如何解决?
我试着将产物css改成和html并列,里面依旧还是backgroud:url(../img/bg.png)
;使用url-loader
和file-loader
无论如何设置,产物中所有的背景图均转换为了base64图片; 关闭又无法解决路径问题;
项目是vue-cli项目;css使用的是stylus语法
首先,我们一起了解下什么是资源内联。
什么是资源内联?
资源内联(inline resource),就是将一个资源以内联的方式嵌入进另一个资源里面,我们通过几个小例子来直观感受一下。
HTML 内联 CSS,这个其实就是我们通常说的 内联 CSS 或者 行内 CSS。我们可以写几行 reset CSS,然后通过
style
标签的方式嵌入进了 HTML 里面:CSS 内联图片,就是我们通常将小图片通过 base64 的方式内嵌进 CSS 里面。我们可以将搜索小 icon 内联进 CSS:
了解了资源内联的基本概念后,可能你会问资源内联有什么意义?接下来我们从几个维度去看看为什么我们需要资源内联。
资源内联的意义
资源内联的意义这里我从三个方面去说明一下,分别是:工程维护、页面加载性能、页面加载体验。
工程维护
我们看看资源内联对于工程维护的意义,这个是一个基本的 HTML 结构。在如今流行的 Hybrid 混合开发架构里,会有一个个的 H5 页面,对应前端工程里的多页面应用(MPA)。
我们去打包多页面应用的时候会借助 html-webpack-plugin,每个页面会有一个 HTML 模板与之对应。每个 HTML 模板都会包含很多相似的内容,比如 meta 信息,或 SSR 时需要用到的一些占位符等等。试想一下,如果将下面这段 meta 代码分别复制一份放到每个 HTML 模板里面将会对代码维护造成的影响。
这个时候推荐的做法是维护一份 meta.html,将上面的这个代码内容放置进去。每个 HTML 模板将 meta.html 片段内联进去。
工程维护的另一个比较常见的场景就是图片、字体等文件的内联了,比如很多同学通常会去网上找一个在线的 base64 编码工具(如:https://www.base64code.com/ )去将各种图片(png、jpg、gif) 或者 字体 (ttf、otf) 编码,然后将编码后的那一长串字符串放置到代码里面去。比如前面的这个搜索 icon 图标,这段长串的字符串放置在源代码里面根本毫无语义,而且对维护者而言也是场灾难。
我们可以通过更优雅的资源内联语法来避免这个问题,文章后面会介绍到。
页面加载性能
资源内联的第2点意义在于可以减少 HTTP 的请求数,当然如果你的网站有使用 HTTP2 这点的意义可能不会那么大。将各种小图片、小字体(比如:小于5k) 在生产环境 base64 到代码里面可以极大的减少页面的请求数量,从而提升页面的加载时间。
页面加载体验
资源内联另外一个重要的意义在于提升页面加载体验。我们都知道浏览器解析 HTML源码是从上到下解析,因此我们会把 CSS 放到头部,JS 放置到底部。以 SSR 场景为例,如果不将打包出来的 CSS 内联进 HTML 里面,HTML 出来的时候页面的结构已经有了,但是还需要发送一次请求去请求 css,这个时候就会出现页面闪烁,网络情况差的时候更加明显。
资源内联的类型
资源内联的类型主要包含:
如果你曾经使用过 FIS 或者看过 FIS 的文档,你会发现 FIS 对于资源内联的支持非常棒,详细的文档:嵌入资源
FIS HTML 内联 HTML 片段:
FIS HTML 内联 JS 脚本:
接下来,我们分别看看每种内联在 webpack4 中的实现。
HTML 内联
基础版
HTML 内联 HTML 片段、CSS 或者 JS(babel 编译后的,比如内联某个 npm 组件) 的思路很简单,就是直接读取某个文件的内容,然后插入到对应的位置。我们可以借助 raw-loader@0.5.1版本,最新的 raw-loader 会有问题(因为它导出模块时是使用 export default),不过你完全可以自己实现这样的一个 raw-loader。
0.5.1 版本的 raw-loader 的代码:
借助 raw-loader 实现的内联语法如下:
增强版
我们可以实现一个对开发者更友好的语法糖,比如实现一个 loader 去解析 HTML 里面的?__inline 语法。这里我实现了一个 html-inline-loader,它的代码如下:
然后,你可以这样使用:
查看的效果:
CSS 内联
通常情况下,为了更好的加载体验,我们会将打包好的 CSS 内联到 HTML 头部,这样 HTML 加载完成 CSS 就可以直接渲染出来,避免页面闪动的情况。那么 CSS 内联如何实现呢?
CSS 内联的核心思路是:将页面打包过程的产生的所有 CSS 提取成一个独立的文件,然后将这个 CSS 文件内联进 HTML head 里面。这里需要借助 mini-css-extract-plugin 和 html-inline-css-webpack-plugin 来实现 CSS 的内联功能。
注:html-inline-css-webpack-plugin 需要放在 html-webpack-plugin 后面。
图片、字体内联
基础版
图片和字体的内联可以借助 url-loader,比如你可以通过修改 webpack 配置让小于 10k 的图片或者字体文件在构建阶段自动 base64。
增强版
不过 url-loader 做资源内联最大的缺陷就是 不能个性化的去设置某张图片自动编码,针对这个问题,我们可以借鉴下 FIS 的语法糖,实现 ?__inline 的语法糖,引用某个图片的时候看到这个后缀则自动的将这张图片进行 base64 编码。这个功能实现起来也很简单,可以参考我实现的 inline-file-loader,核心代码:
有了图片的内联功能,我们可以将前面的搜索 icon 图标内联的写法修改成:
最后
下面是本篇文章的代码演示资料,如果有需求,可以自行获取。