前端组件的本质到服务端组件渲染

先说结果 为ejs-mate实现了一个组件加载函数 实现了服务端组件化的渲染 按组件加载js与css资源

目前很多前端标准各大浏览器都有部分支持 心想试一下 然后试试看把vue的组件改成原生的前端组件吧 然后看了一下WebComponents 发现Shadow DOM离我上次看的标准又有变化了 没办法 目前这些基本还处于草案的阶段 只有template标签因为属于HMTL5的标准 目前是比较稳定放心可用的状态 具体就不多说了 写了两个组件 弄了个demo thesadabc.github.io/blog-demo/webcomponents 代码在这github.com/thesadabc/blog-demo/tree/master/webcomponents chrome56+

然后我发现并不能把vue的组件完全移植到原生的组件上 后来发现事情并没有这么简单 重新审视一番发觉 vue 的这些所谓的组件实质上是 模板 之所以不能移植到原生组件 很大一部分原因是诸如v-ifv-for等语法 而这些在模版引擎里非常常见 包括router-view这种 原生组件是根本没法搞的

vue ng之类的 本质上是前端的组件化渲染 组件本质就是模板 相比后端组件化渲染还只是停留在非常低级的includehtml模板文件的阶段 对组件的js与css的处理几乎没有

所以我在想 按照各自框架渲染组件的方式 如果移植到服务端渲染 那岂不是很爽吗 然而vue是有服务端渲染的 不过这个服务端组件渲染和前端组件渲染不太一样 服务端渲染只是把html相关的渲染完成 而事件属性之类的传递和前端组件渲染并没有区别 也还是包含了一个完整的Vue对象 所以其实这种渲染并不是完全的服务端渲染 而是分步渲染 反而觉得这种方式非常多余 为了seo的一种妥协

于是开始搞一个吧 完全后端渲染的 组件化的解决方案 各自模板引擎其实都有提供include方法 不过这只是html的模块化 事件以及数据传递相当成问题 弄了一个简单的 包含了这种思想的 demo

前端渲染

基于ejs-mate 自己封装了一个component函数 用来加载组件 以及组件相关的资源(js, css) 这个demo就不上代码了 因为太简单了

大概就是这个意思 后来有一些改进 遇到几个问题

  1. 组件事件的处理
  2. 组件根节点属性传入
  3. 组件对外的一些接口
  4. 嵌套组件

很明显 这几个在前端渲染很容易解决 但是后端渲染就有问题了

所以有这样的想法

1和3可以给每个脚本插入一段代码 这段代码给这个脚本 注入入一个对象 表示根节点 类似hexo给其插件注入了hexo这个变量一样 而且由于组件复用的原因 所以这个需要和第2点配合 插入固定class或者其他方式来标记元素 可以保证每种组件唯一 不是每个

说到这个 css的嵌套Nesting 暂时这个还用不了 如果可以的话 在每个组件css外面注入一层父选择器 这样就更好了

对于问题2 使用cheerio之类的工具来处理

对于问题4 估计目前搞不定

于是基于上面这几个想法 然后花了一天 弄了一个略微高级的 写了一个这样的代码github.com/thesadabc/blog-demo/tree/master/server-render-components 功能和上面那个原生控件的差不多 也是多个图片预览的功能 把嵌套的部分去掉了 这个因为是服务端渲染 需要下载下来自己运行才能看到效果 下面有个截图

服务端渲染

  1. 文件列表
  2. 浏览器打开渲染的结果
  3. 服务端express接入模板引擎并设置路由
  4. home模版
  5. thumb组件js代码 注入了一个root变量作为根节点元素

具体的内容可以直接看代码 还是比较简单的 本来想吧 资源混淆压缩加进去 结果uglifyjs不支持新的语法 明明浏览器都已经可以用了啊 然后干脆就放弃了

基本上来说 目前这个还是比较满足我心里的想法的 非常爽