美文网首页移动全栈技术之路千米移动React Native开发
F8App-ReactNative项目源码分析2-服务器端

F8App-ReactNative项目源码分析2-服务器端

作者: offbye西涛 | 来源:发表于2016-05-19 12:23 被阅读1023次

    近期开始研究Facebook f8app项目,目标是理解Facebook官方React Native f8app的整体技术架构,给公司目前几个的React Native项目开发提供官方经验借鉴,并对原生开发和React Native开发进行框架层面的融合。
    研究了f8app的项目结构后,发现f8app服务器端的代码比较少,并且弄清楚数据模型和接口协议,对于后面理解客户端的实现有帮助,所以先分析服务器端。第二篇文章会详细分析f8app服务端的技术实现,并进行一些修改实验。f8app服务器端是基于Node.js,Express,Parse和GraphQL实现的,数据存储是MongoDB NoSql数据库。

    安装推荐开发工具nuclide

    我们一般使用Atom进行js开发,首先安装facebook推荐的开发工具nuclide。Mac和Linux下的安装命令如下,暂不支持windows。

    apm install nuclide
    

    F8app工程结构

    下面先用tree -L 2 命令看下目录结构,只显示二级目录

    ├── LICENSE
    ├── README.md
    ├── android  安卓项目目录
    │   ├── app
    │   ├── build.gradle
    │   ├── gradle
    │   ├── gradle.properties
    │   ├── gradlew
    │   ├── gradlew.bat
    │   └── settings.gradle
    ├── index.android.js
    ├── index.ios.js
    ├── ios   iOS项目目录
    │   ├── Default-568h@2x.png
    │   ├── F8Scrolling.h
    │   ├── F8Scrolling.m
    │   ├── F8v2
    │   ├── F8v2.xcodeproj
    │   ├── F8v2.xcworkspace
    │   ├── F8v2Tests
    │   ├── PodFile
    │   ├── Podfile.lock
    │   ├── Pods
    │   ├── Settings.bundle
    │   ├── Splash@2x.png
    │   └── build
    ├── js    React native js源代码目录
    │   ├── F8App.js
    │   ├── F8Navigator.js
    │   ├── FacebookSDK.js
    │   ├── Playground.js
    │   ├── PushNotificationsController.js
    │   ├── actions
    │   ├── common
    │   ├── env.js
    │   ├── filter
    │   ├── flow-lib.js
    │   ├── login
    │   ├── rating
    │   ├── reducers
    │   ├── setup.js
    │   ├── store
    │   └── tabs
    ├── logs
    ├── node_modules
    │       下面有900多个js模块
    ├── npm-shrinkwrap.json
    ├── package.json
    ├── scripts   一些脚本
    │   ├── import-data-from-parse.js
    │   ├── optimize-images.sh
    │   └── store-ip.sh
    └── server  服务器端目录,基于Parse和GraphiQL
        ├── cloud
        ├── cloud.js
        ├── schema
        └── server.js
    

    服务器端技术介绍

    f8app的服务器代码都在server目录下,由于使用了Node.js,Express,Parse,GraphQL等先进框架,代码量比较小,一共只有10个js文件,996行js代码。下面先介绍下f8app服务器端使用的技术,Node.js和Express这类常见技术就不介绍了。
    服务器端是基于Facebook的Parse云平台,Parse服务将于January 28, 2017停止服务,现在官方提供了迁移指南。
    现在Parse Server已经开源了,git地址是parse-server,开源Parse Server是基于node.js和Express框架的,支持的数据库是MongoDB和MongoRocks。
    script/import-data-from-parse.js实现了从https://api.parse.com/1/classes/ 导入数据到本地MongoDB数据库的功能,通过npm run import-data 可以导入数据。

    MongoRocks: What and Why?

    MongoRocks是Facebook在2015年开发的基于RocksDB的MongoDB存储引擎实现,一般情况下Parse应用都应该用MongoRocks。
    MongoDB3.0允许用户替换默认的default memory mapped (MMAP) 存储引擎。MongoRocks比MMAP存储引擎在性能方面有很多好处,
    MongoRocks更多介绍可以参考MongoRocks链接

    Parse Server简单介绍

    Parse 的愿景是让开发者摆脱服务器,随心所欲地开发各种移动应用程序。对于比较复杂的应用程序,开发者有时需要不在移动设备上运行的逻辑。Cloud Code 正好可以实现这一目标。
    由于f8app已经带了Parse Server,所以我就不需要用npm安装了,直接在f8app目录下运行npm start,测试下添加数据

        curl -X POST \
        -H "X-Parse-Application-Id: oss-f8-app-2016" \
        -H "Content-Type: application/json" \
        -d '{"score":1337,"playerName":"Sean Plott","cheatMode":false}' \
        http://localhost:8080/parse/classes/GameScore
    

    在终端运行上面的命令后,服务端返回 {"objectId":"S8mgRPVgwU","createdAt":"2016-05-17T08:31:10.802Z"} 表示添加成功
    在浏览器,可以看到刚才添加了一条Game score数据。

    在终端运行下面命令可以查询新添加的那条数据

        curl -X GET \
         -H "X-Parse-Application-Id: oss-f8-app-2016" \
         http://localhost:8080/parse/classes/GameScore/S8mgRPVgwU
    

    返回结果 {"objectId":"S8mgRPVgwU","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-05-17T08:31:10.802Z"
    Parse提供各种语言的SDK,包括Android,iOS,js等,可以很方便的在移动端使用。

    Relay和GraphQL

    Relay 是 app 中的一个数据框架,GraphQL 是 Relay 用来做数据表示的查询语言。GraphQL 同时还有一个 npm 包,可在服务器上运行,提供可以和 Relay 交互的数据源.

    Relay 不是从 Flux 架构分化来的,它只和 GraphQL 有关。这也就是说,这和 Redux 的模型有着巨大的区别。

    在 Relay + GraphQL 的模型中,每个组件指定自己需要的数据。Relay 调用数据,数据更新时,提供给组件最新的数据,并在客户端做缓存。app 需要更新数据时,在 Action 中创建一个 GraphQL 变更,这和 Redux 类似。

    GraphQL是Facebook开发的一个针对描述复杂数据模型需求的一个数据查询语言标准,目前是工作草案。可以使用多种语言实现,目前Facebook提供了node.js版本的参考实现GraphQL.js..

    服务器端代码分析

    server.js是服务器的入口类,基于Express框架默认在8080端口提供了/parse,/dashboard,/graphql三个url入口,根目录默认跳转到/graphql。
    下面是/parse url入口的代码,很简单,直接new ParseServer,把相关的参数传进去,mongodb数据库地址DATABASE_URI可以取环境变量的值const DATABASE_URI = process.env.DATABASE_URI || 'mongodb://localhost:27017/dev'; ,其它的参数也都可以直接在环境变量里面设置,通过export XXX="xxx"即可修改。

        server.use(
          '/parse',
          new ParseServer({
            databaseURI: DATABASE_URI,
            cloud: path.resolve(__dirname, 'cloud.js'),
            appId: APP_ID,
            masterKey: MASTER_KEY,
            fileKey: 'f33fc1a9-9ba9-4589-95ca-9976c0d52cd5',
            serverURL: `http://${SERVER_HOST}:${SERVER_PORT}/parse`,
          })
        );
    

    cloud.js很简单,只是引用了cloud目录下文件,代码如下:

        require('./cloud/friends');
        require('./cloud/surveys');
        require('./cloud/tests');
    

    cloud/friends.js 提供通过OAuth在Facebook登录后,获取好友和日程的功能。

    /dashboard是ParseDashboard的入口,很简单不说了,就是Parse的Web管理控制台,通过http://localhost:8080/dashboard 可以访问,对Mongodb中数据进行管理,操作很方便。

    /graphql是通过express-graphql插件实现的一个graphql入口,前端UI是通过graphiql.js插件实现的。graphql这块占代码量比较大,schema目录下的文件都是和graphql相关的。
    GraphQL.js. 提供2个主要能力:构建type schema; 根据type schema类型提供查询能力。
    schema.js是graphql查询的入口,只支持查询schedule,node(接口类型,只有id),viewer,这点可以从下面的代码看出来,只指定了F8QueryType。我们在浏览器graphql控制台http://localhost:8080/graphql 里面也只能做schedule的查询,否则会提示错误,这个控制台还是很智能的,支持查询代码提示。

        export var Schema = new GraphQLSchema({
          query: F8QueryType,
          mutation: F8MutationType,
        });
    

    F8QueryType 定义如下:

        var F8QueryType = new GraphQLObjectType({
          name: 'Query',
          fields: () => ({
            node: nodeField,
            viewer: {
              type: F8UserType,
              resolve: (rootValue) => rootValue, // TODO: Authenticate user
            },
            schedule: {
              type: new GraphQLList(F8SessionType),
              description: 'F8 agenda',
              resolve: (user, args) => new Parse.Query(Session)
                .ascending('startTime')
                .find(),
            },
          }),
        });
    
    修改下试试,让它能支持查询演讲者,在schedule:{这行上面加入下面代码:
    
        speaker: {
          type: new GraphQLList(F8SpeakerType),
          resolve: (speaker, args) => new Parse.Query(Speaker)
            .find(),
        },
    
    在graphql控制台输入查询条件
    
        {
           speaker{
          id
          name
          title
          }
        }
    

    可以查到所有演讲者的列表。
    schema.graphql直观的展示了全部的type scheme查询类型,可以看到有interface和type 2种定义方法,interface其实就是类似Java里面的接口,type可以实现interface。Node是interface,包含一个主键id,其它很多类型都实现了Node,例如type Speaker implements Node。通过这个文件我们可以轻松地理解整个服务器的数据结构,还是很清晰的。graphiql.js控制台第一次访问会请求schema.json,用于查询框智能语法提示。
    updateSchema.js可以重新生成schema.graphql和schema.json。在f8app目录下运行npm run update-schema 命令可以重新生成这2个文件。
    按照上面的做法修改文件后运行命令,可以发现 schema.graphql多了一行 speaker: [Speaker]

    babelRelayPlugin.js代码很少,是提供scheme数据给Relay的。
    具体可以参考babel-relay-plugin

    本文介绍了f8app的项目架构,分析了f8app服务器端的技术实现,整个数据流是Parse Cloud 通过脚本导入-> MongoDB -> ParseServer -> GraphQL -> Redux -> ReactNative,用到了Express,Parse Server,Parse dashboard,GraphQL.js,GraphiQL.js, Ralay等js模块,代码量比较小,但技术栈挺复杂的。

    下篇文章分析React Native Android端的技术实现。

    相关文章

      网友评论

      • 76fde5bc9533:api.parse.com关闭了,parse cloud数据如何导入f8app?主要用来演示学习
        608924568ff8:https://raw.githubusercontent.com/ReactWindows/f8app/data/mongodb/db.zip 这个地址可以下载离线的db 然后需要配置一下 运行这个库

      本文标题:F8App-ReactNative项目源码分析2-服务器端

      本文链接:https://www.haomeiwen.com/subject/mshgrttx.html