-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
webpack4 中如何实现资源内联? #5
Labels
Comments
点个赞 |
厉害了 |
1 similar comment
厉害了 |
ejs 语法是 <%= %> 不是 ${},这里要修改一下 |
我这边发现一个问题,产生的css产物中, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
首先,我们一起了解下什么是资源内联。
什么是资源内联?
资源内联(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 图标内联的写法修改成:
最后
下面是本篇文章的代码演示资料,如果有需求,可以自行获取。
The text was updated successfully, but these errors were encountered: