最近三个月我们一直在不断调整前端结构,目的在于提升 前端开发的一致性和复用性,先后提出了 前端结构 の 调整建议(v1),前端结构 の 调整新建议(v2)。
最近两周,基于 Jimmy 的实践经验,与目前团队不断的交流融合,在 6月24日,我们有了新共识,到达了一个新的里程碑。
原则
- 可理解性是首要的,通过明确的约定以保持良好的一致性;
- 创建和业务相关的 典型案例,便于团队模仿、学习和理解;
- 鼓励尝试,容忍犯错,凝聚团队共识,渐进改造现有代码;
三个顶级目录
- imodules 模块;
- ipages 页面;
- iscripts 脚本;
目录结构示例
├── imodules/
│ ├── base/
│ ├── embed/
│ ├── hour24/
│ ├── repair/
│ └── xbase/
├── ipages/
│ ├── home/
│ └── repair/
└── iscripts/
├── immy/
├── vendor/
└── xlibs/
imodules(模块)
模块划分目的在于将复杂问题进行分解,提升独立性,降低耦合度,促进复用,并行开发,以提升开发效率。
imodules
├── base
│ └── _baseUModules
├── embed
│ ├── EmbedBottom
│ └── EmbedTop
├── hour24
│ └── Hour24Matte
├── repair
│ ├── RepairMatte
│ └── RepairScreenSelect
└── xbase
└── _Matte
模块分类目录约定
1. 小写字母开头,驼峰风格,不使用中划线和下划线进行区隔,慎用数字;
2. 仅为源码分类使用,不在 dist 发布目录上体现;
3. 支持多级分类目录;模块实体目录约定
同时作为模块 id(元素 id),大写字母开头,驼峰风格,不使用中划线和下划线进行区隔,慎用数字;
特殊:下划线开头是允许的,表示内部基类;模块 id 和 元素 id 约定的说明
规则:大写字母开头,驼峰风格,不使用中划线和下划线进行区隔,慎用数字;
考虑:中划线使得正则复杂化;驼峰了就自然拒绝下划线;除非数字有意义,否则慎用数字;
base 非常特殊,和 xbase | _parts | partial 分离;
叶子节点示例
imodules/repair/RepairModal/
imodules/repair/RepairModal/
├── main.css
├── main.html
├── main.js
└── screen.tpl
模块 css 的加载问题
见 jacques_迹远 的论述 <style>标签放置位置规范;<style> Tag;style Attribute;模块的可测试性
建议建立模块测试机制,实现可单独调试、可单独测试、可单独发布,以支持持续集成、持续测试、持续发布;
ipages(页面)
ipages
├── home/
│ ├── I404/
│ └── Index/
└── repair/
└── RepairIndex/
- 页面分类目录约定;
ipages/home/,ipages/repair/;
命名约定同模块分类目录的命名约定; - 页面实体目录约定;
BODY id,命名约定同模块实体目录的命名约定; - 叶子节点示例
ipages/repair/RepairIndex/
ipages/repair/RepairIndex/
├── images/
│ └── supplier-avatar.png
├── main.css
├── main.js
└── repair@index.html
- repair@index.html,表示发布后 repair/index.html,指定了发布路由;没有 @ 则表示发布在根目录下,有几个 @,则有几层目录;有一定的灵活变换性;
iscripts(脚本)
iscripts/
├── immy/
│ ├── libs/
│ ├── baseWidgets.js
│ ├── data.js
│ ├── project.js
│ └── utils.js
├── vendor/
│ └── mustache.js
└── xlibs/
├── common-structure-expanded/
├── global-structure-expanded/
└── tip.js
- mustache.js 放到 vendor 下;
- xlibs 是业务库,其内容存在相当的不确定性和变动可能;跨业务模块公用,跨站点公用。这里有一个转变,就是放到这里的,默认都是全局公用的;
- tip.js 放到 xlibs 下;
immy(基础框架)
- 基础框架和应用模块适度分离,以便进一步重构框架和模块;
- 新框架命名
使用 immy,简洁、易记忆,和 Jimmy 有深刻渊源; - immy 框架 可作为产品,以适度分离的方式迭代发展;
immy
├── libs/
│ ├── potato.js
│ └── require.js
├── baseWidgets.js
├── data.js
├── project.js
└── utils.js
immy 应当有继续演进的机会,虽然 require.js 可以放到 vendor 下,但考虑到若没有 require.js,这个框架就跑不起来。require.js 属于 immy 这个框架的最小集合。
idom、ievent、imodule
- 设置 自定义属性 idom,将 dom 操作从 class 分离;
- 设置 自定义属性 ievent,明确区分 event 和 action;
- 设置 自定义属性 imodule,明确引用依赖的模块 js;
- 基于 els elements 去绑定;
模块 の 类、函数、变量
- 类名:大写字母开头,驼峰风格;
- 变量:小写字母开头,驼峰风格;
- 函数:小写字母开头,驼峰风格;
- 私有:下划线开头表示内部使用;
HTML 元素 の id 和 class
- 元素 id:命名约定同模块实体目录的命名约定;
- css class:全小写,中划线分隔;
URL、目录、文件 の 一般命名约定
- URL 设计要尽量简单、直观和有意义;
- 除了模块实体目录和页面实体目录作为 id 使用要加以特殊约定外,目录文件名统一使用英文小写(除 README.md 外),慎重使用数字后缀;如果要多个单词区隔,请使用 中划线“-”进行区隔;
- CSS 类名也是中划线区隔,全小写;
- 网页链接通常使用绝对路径;
缘起
两个不同的角色要共享后台注册登录认证服务,但在页面弹出层有所不同,如何合理复用?
imodules/user/
imodules/user/
├── CustomerLoginForm
├── _LoginForm
└── SupplierLoginForm
约定
后记
- 我们的前两版结构调整,应该说主要是文件夹的合理组织,工程耦合不是通过文件夹拆分组合(不论多么自洽和复杂)就能简单解耦的;
- 第三版结构调整,应该说在工程解耦上走出了坚实的一步;