目前的symfony.com网站创建于Symfony 2.0发布之前的2011年7月。尽管代码持续更新到了最新的稳定版本 (写本篇博文时是Symfony 3.3),在某些部分,程序显示出老化迹象。这也是为什么我们决定翻新网站的前端以简化模板并以不同方式来管理网站资源。
我们的前端需要简化,因此我们基于Bootstrap 3使用了一个极为传统的配置,以及一堆SCSS和JavaScript文件。在开始阶段它们工作的不错,但维护起来却愈发困难。
重构过程花了我们差不多两周时间,涉及了50个commits,改动了219个文件 (多数是 .html.twig
和 .scss
)。我们添加或改变了6,209行代码,删除了10,291行代码。在本文中,我们解释了一些最为相关的改进。
全新的Asset组织方式
之前,根据其自身用意,我们拥有海量的小SCSS文件: code.scss
, typography.scss
, forms.scss
, 等等。除了在样式复用过程中徒增难度之外,这些玩意还把维护过程变得复杂,因为在给定页面元素的设计过程中,它难以找到所有的样式。
这是开发者很容易犯的一个错误: 把某样东西分割成大量小片,并深信这是“模块化”设计而沾沾自喜,但结果却是难于维护。
现在我们在一个大号的 app.scss
文件中定义了全部基础样式,我们还拥有为每个页面的特殊用途而准备的专用文件: home.scss
, download.scss
, 等等。这便在设计上大幅简化了维护,还帮助我们创建了一个更加一致化的设计。因为对于不同元素而言,相同的样式很容易复用。
全新的设计理念
以前的设计是 "桌面优先" 而新设计则是 "移动优先",这也是我们长久以来想要改变的。现在的一切功能设计以及测试,都是手机优先,然后再根据需求来为更大尺寸的设备进行调整。
结果就是现在的symfony.com在内容上良好地适配了任何设备。例如, Symfony Roadmap页面,你可以找到当前版本和后续版本的信息,现在能在手机上以垂直路线图显示,而在大设备上以水平路线图展示。看一下这一页面的前后对比:
为了避免让新设计过于复杂化,我们决定只适配两个响应式的节点:平板和小桌面级别的 768px
,以及其他设备的 992px
。
全新的CSS样式
之前,我们没有使用任何特别的CSS标记法,多数selectors靠的就是嵌套的HTML id
属性 (如 #p-7-2.post #comments #add-comment
)。新设计中使用了专有的HTML class
属性,乃是基于 BEM methodology。我们并未严格执行BEM因为它能极速胀大,但BEM却帮我们创建了一个更加模块化和更易维护的设计。
另一项改进,则是以一种更加细粒化的方式引入了三方依赖。并非使用整个的Bootstrap 3框架,现在我们按需选取了真正用到的Bootstrap文件:
1 2 3 4 5 6 | // app.scss
@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/mixins";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/normalize";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/grid";
// ... |
令样式大幅简化的最后一项改进,是通过CSS classe工具,设置了margin属性 (如 .m-t-0
可以代表 margin-top: 0
, .m-b-15
代表 margin-bottom: 15px
, 等等。)
尽管它们可能存在争议,人们会认为它们膨胀了你的CSS,但在我们这里,仅通过10个工具class我们就转换了全部所需,进而省去了大量无用的自定义的CSS class,它们仅设置了margin或padding。这些工具类也将在Bootstrap 4中登场。
全新的工作流
一开始,我们使用的是Assetic来管理symfony.com的资源。然而,几个月之后,我们删掉了它,开始过渡到基于JavaScript的资源管理。作为多数情况下的非JavaScript开发者,我们困惑于可用工具的数量,但最终我们置身于 Webpack 大军之中。
Webpack是个很好的工具来管理你的样式,脚本和图片,把它们处理并生成为最终的CSS和JavaScript文件。但是,Webpack初上手还是较难掌握的。幸运的是,我们有一个队友: Ryan Weaver。在过去的几个月,Ryan已经秘密工作于一个全新的用于管理web资源的JavaScript工具。
这个新工具,叫做 Webpack Encore,是一个把Webpack整合到你程序的一个简易工具。它封装 了Webpack,给了你一个清爽而强力的API来构建JavaScript modules, 预处理CSS和JS,并且编译和最小化这些assets。
在过去几个月,我们已经在symfony.com生产环境上使用了这个工具,我必须说,它的使用令人愉悦。更甚者,这个新工具将成为 官方推荐的Symfony程序资源管理工具。你是否想在自己的项目中使用它了?不必等待太久,因为 本周之内它就发布了。
全新的Twig模板
之前的Twig模板相当好,但是我们做了一些改变以便让它们能使用最新的Twig功能来简化一些事情。我们使用了很多技巧,也是你可以在自己的项目中使用的:
Null coalesce operator(null联合操作符): 从Twig 1.28引入,它提供的是和在PHP 7中定义的 ??
操作符相同的功能。它可以又好又简洁地替换 default
调节器:
不要把模板切分为许多碎片: 把模板切成小片并使用 include()
来将其包容到主模板会伤害性能。也会使维护复杂化,因为很难找到内容到底是在哪里被定义的。
创建子模板仅发生在模板的某些部分可以在其他若干模板中真正复用时。当包容子模板时,优先使用 include()
模板函数,而不是include
标签,并且应始终使用 Twig 命名空间的语法,会比传统的 bundle 语法要快:
检查block是否存在: Twig 1.28中新增的另一项功能是,支持了 is defined
块儿操作符,这在高度动态的模板中检查区块的存在性时十分有用:
自定义Twig命名空间: 在重新设计期间,对于每一个icon,我们用合适的SVG文件替换掉了一种自定义的icon字体。在模板中引用这些文件是极为烦人的 (如 images/icons/arrow.svg
, bundles/blog/images/icons/arrow.svg
),因此我们使用 custom Twig namespaces 来存储 icon
命名空间下的所有这些图标,并通过 source() Twig函数来在模板中嵌入它们:
1 2 3 | {# Twig namespaces create concise and beautiful templates #}
{# Twig命名空间创建了简洁优雅的模板 #}
<i class="icon">{{ source('@icons/arrow.svg') }}</i> |
不必担心HTML代码中的空格: 作为开发者我们的工作是创建可维护的Twig模板,而不是生成美观的HTML代码。HTML吃的是浏览器而不是去吃用户,因此它在发送到浏览器之前被乱砍、最小化和压缩了,因此不要太介意它:
1 2 3 | {# this is beautiful and easy to maintain #}
{# 美观而易于维护 #}
<li class="{{ current == item.slug ? 'selected' }}" ...> |
最终结果
上面所解释的所有变化和使用的技巧,组合起来就 带令得本次重构是如此精彩。symfony.com网页看上去和感觉起来是相同的,但所有设计上的问题消失了,网站是完全响应式的,而且是“手机优先”,性能也被巨幅提升了: 之前,每个symfony.com的页面要下载约 194KB 的 app.css 文件 (gzipping压缩之前); 现在,这个 app.css 文件的容量仅为 59KB,真乃巨量的减少!
尽管重构的目的并非是要改变页上在视觉上的设计,我们利用这次机会做出了一些微小改变,特别是文档环节。例如,注解,技巧和警告的区块,现在更加简洁而易于识别: