
目标:Gitlab博客的新设计新利18官方网站
2021年3月数字体验团队为GitLab博客部署了新的改进设计。新利18官方网站这一设计变化影响了超过1300篇博客文章。新利18官方网站这是迄今为止规模最大的运动我们的设计系统,拖鞋。由于Gitlab博客的年龄和大小,它提出了挑战。新利18官方网站我们想辜负Gitlab的迭代值:“做尽可能小的事情,并尽快完成。”
主要挑战:渐进地采用具有冲突CSS的新设计系统
拖鞋使用顺风CSS,它随附自己的基础样式,称为起飞前的。飞行前的行为就像正常化的风格(它是建立在上面modern-normalize),这对新项目或进行全面过渡的项目很有用。在我们的情况下,Preflight是一个障碍,因为它必须与我们现有的CSS一起工作。
我们探索了一些开箱即用的解决方案,比如启用Tailwind!重要的配置,或使用a非常具体的选择策略。
在这两种情况下,我们非常接近我们所需的结果,但仍然存在问题:
关键的遗留组件需要旧的CSS。那些旧款式已经过时了重要的!
以及选择器策略,因为它们应用于我们在Tailwind实用程序中没有指定的属性。解决这些冲突将花费太多的时间和体力。我们想要更多高效的解决方案,因此我们专注于两件事:识别我们的CSS的理想状态,并找到更好的CSS封装。目标是防止现有的样式影响新组件,以及影响旧组件的新样式。
解决方案:CSS封装与web组件
Web组件技术为我们使用旧CSS的需求提供了一个引人注目的解决方案。我们使用了阴影DOM封装CSS。模板和插槽允许我们使用现有的HTML,ERB和HAML模板。自定义元素把它整合在一起。
在里面顶级博客模板新利18官方网站,我们放置了博客文章标记的模板标记新利18官方网站。这模板
标签是有效的HTML - 这意味着我们的模板引擎可以在其内部处理所有内容。我们可以用部分的
标签和屈服
正如预期的那样,它们成为模板的一部分。下面的输出显示了哪些看起来(简洁的某些类):
<模板id =“slp-新利18官方网站blog”><主要类=“slp新利18官方网站Blog”><头类=“slp新利18官方网站blog__header”><%=部分的“包括/ cms / blo新利18官方网站g_post / slp-blog-avatar”,当地人:{作者:作者}% ><%=部分的“包括/ cms / blo新利18官方网站g_post / slp-tags”% >
header><文章类=“slp新利18官方网站blog__article”><如果current_page。数据。image_title% >< imgalt =”“src =”<%=current_page。数据。image_title% >”宽度=“100%”/><结束% ><%=屈服% >< / >条<旁边类=“slp新利18官方网站Blog__aside”><%=部分的“包括/ cms / blo新利18官方网站g_post / slp-social-power”% ><插槽名称=“non-slippers-aside-items”> slot>除了< / ><页脚类=“slp新利18官方网站blog__footer”>
<%=部分的“包括/ CMS / Blo新利18官方网站g_Post / SLP相关内容”% ><插槽名称=“non-slippers-footer-items”> slot>
< /页脚>< /主要>模板>Data-cookieConeent =“忽略”src =“/ javascript / slipper新利18官方网站s-blog.js”类型=“text / javascript”> script>
顶层模板加载源/ javascripts / slippers-bl新利18官方网站og.js
在身体
的文档,它阻塞呈现,直到脚本完成加载。源/ javascripts / slippers-bl新利18官方网站og.js
将拖车CSS作为变量导入使用webpack加载器语法。CSS作为一个变量存储,我们可以将它注入自定义元素定义。
接下来,我们注册SLP-新利18官方网站Blog.
作为自定义元素。当DOM解析标记时,它将渲染博客帖子模板,也将在罕见的情况下,我们的JavaScript没有加载,它将失败。新利18官方网站如果失败,我们返回到屈服
输出在轻DOM确保关键内容永远不会丢失。在这些情况下,我们的静态站点生成器已经呈现了模板,所以访问者仍然可以访问博客文章的图像和文本。新利18官方网站
下面是JavaScript的样子:
进口vue.从'vue / dist / vue.min.js'进口拖鞋从'拖鞋 - ui / dist / slipperscomponents.common.js'/ / eslint-disable-next-line进口/ no-webpack-loader-syntax常量css=需要(“!原始装载机!Sass-Loader!../ stylesheets / slippers.css.scss”)。默认的;//为了简洁起见,省略了一些事件处理程序和其他要求出口功能initializeSlippersWebComponent(){如果(窗口。customElements){customElements。定义(“slp-新利18官方网站blog”,类扩展htmlelement.{构造函数(){极好的();常量模板=文档。getElementById(“slp-新利18官方网站blog”)。内容;常量shadowRoot=这。attachshadow.({模式:'打开'});shadowRoot。innerhtml.=' <时尚>$ {css}> < /风格的;shadowRoot。列表末尾(模板。版本(真的));}});}}
如果脚本成功加载,我们的回退生成的轻DOM内容屈服
语句在呈现自定义组件时被丢弃。这就是我们预先使用内联脚本标记的原因-以避免无样式内容的Flash。
最后,我们可以使用槽渲染非拖鞋项目。槽元素从轻DOM获得CSS,所以我们的预先存在部分和其他包括模板将按预期工作。
我们的自定义元素和它的插槽看起来像这样:
< slp新利18官方网站-blog ><%=屈服% >< divslot =.“non-slippers-aside-items”><%=部分的“包括/ newsletter-signup.html”% >< / div >< divslot =.“non-slippers-footer-items”><除非current_page。数据。install_cta==.假% ><%=部分的”包括/博客/试一试新利18官方网站”% ><结束% ><如果ci_environment吗?% ><%=部分的“包括/博客/评论”新利18官方网站% ><结束% >< / div > SLP新利18官方网站-BLOG>
结果:快速迭代,最小的权衡
我们的解决方案有一些权衡:
- 我们为我们的博客文章增加了构建过程的复杂性。新利18官方网站
- Web组件有广泛的浏览器支持,但这只是最近的发展。围绕这些工具的最佳实践仍然存在争议。
- 从技术上讲,我们在静态生成的站点中添加了客户端渲染,这意味着我们要放弃一些静态站点的优点来实现CSS封装。
这些权衡最终是值得的。我们实现了近乎完美的CSS封装,这使得我们能够迭代拖鞋并有效地发布博客模板。新利18官方网站对于那些不能或不愿加载JavaScript来阅读我们的帖子的人,我们有合理的后备方案来保存关键内容。Web组件是未来的趋势,我们很高兴能够负责任地使用它们。