同构 JavaScript,其实可以更简单

2,300 阅读6分钟
原文链接: github.com

本文为译文,原文地址为:medium.com/@pierceydyl…

isomorphic ,发音类似为(埃搜摸非克)

意为拥有类似的结构或外表,但源头却不同

1-uac5pb_amuak73m73j2htq

自从NodeJS诞生以来,人们就开始爱上了你可以在不同代码栈之间“共享”JavaScript经验的想法。这样的想法(在理论上)拥有诸多好处,包括可以减少不同语言之前的上下文切换,前端和后端开发能更容易的过渡,以及最有希望的好处是获得共享代码的能力。

好吧,我确实诗经在browserifywebpack的帮助下使用了同样的效用函数...确定我可以在浏览器里面使用同样的api进行AJAX操作嘛?没问题!移动表格和文件也可以嘛?没问题!那如果我需要探测环境呢?我并没有使用meteor!也没问题!甚至DOM现在也可以通过ReactDeku和其他很多库实现的“虚拟DOM”实现同构。你也可以不适用虚拟DOM,而采用其他的工具例如morphdomset-domdiffHTML来编写简单的“静态”html代码。

const _ = require("lodash")

_.chain(emails)
    .chunk(100)
    .filter("to")
    .unshift(Promise.resolve())
    .reduce((p, batch)=> {
        p.then(()=> {
            fetch("http://myapi.com/email", {
                method: "POST",
                body: JSON.stringify(batch)
            });
        });
    })
    .value()
    .then(()=> {
        console.log("Emails sent!");
    });

上面的代码看起来确实很酷。现在我可以使用同样的效用函数,ajax和模板在Node和浏览器端编写一个应用。但是这对于一个应用来说还圆圆不够。我们还需要其他很多东西!我需要路由,重定向,session,cookie和其他更多东西来制造一个应用!在Node中我能使用中间件来组织整个应用的代码,我可以将特征相互隔离开,并方便的进行测试!这样的做法可以简单的、自上而下的、插件式的去构建html代码。那为什么我们不能用同样的方式创建DOM呢?React在这个方面更进了一步,但是它做的还不够。

各位女士们乡亲们,我最近的工作一直致力于让编写同构应用更加简单愉快。在客户端和服务器之间编写更少的模板和更少的上下文切换。渐进增强,更快的加载速度,SEO以及用一种更好的方法去思考web应用。现在有一种方法可以让你的浏览器和Node之间共享90%以上的代码。它是一个已经开发了一年以上的框架,在这里我要先感谢我在Tiller Digital工作的同事,以及千千万万和帮助开发同构工具的朋友们。这个框架的名字叫做:Rill

Rill在我们经常使用的Node功能,例如HTTP服务器,上进行了抽象。然他它使用同构的方式暴露出http api,这要感谢 @rill/http。路由,重定向,cookie,session,刷新,错误处理,甚至通用的头信息例如“user-agent”,“referrer”和“local”均使用同构的方式进行了抽象。你最终可以在浏览器端和服务器端使用同样的api获取一个用户的所有数据,最终所有的代码都能以Node的方式编写。

Rill不仅仅是上面说的这些,@rill/http仅仅只是其中一个模块。Rill主要的库更贴近Express或者Koa,三者的api也类似。它能够以同构的方式使用中间件,并为任何应用提供一个最终模块。它提供了一种数据流动的方式。具体信息你可以查看文档

// 用类似的方式创建一个app

const app = require("rill")();

// 使用一些中间件吧!

app.use(require("@rill/logger")()); // 设置日志

app.use(require("@rill/react")()); // 设置react render

// 我们来创建主页

app.get("/", ({ req, res })=> {

  // 让response body设置为一个React组件

  // 这会在浏览器端渲染同步html,并在浏览器端更新dom

  res.body = ;

});

// Listen将开启一个node服务器,或者在浏览器内开启事件监听器.

app.listen({ port: 3000, ip: "0.0.0.0" });

// 非常简单的单页React组件

function MyApp (props) {

  // 使用 JSX

  return (

    

        

            My App - Home

        

        

            Welcome to { props.title } life.

            Take me away!