背景
一直想做个项目,以react为前端,node做后端,实现前后端都可以使用javascript开发。所以在github上找手脚架时候,找到了react-starter-kit,8k多的star,于是就拍板使用它了。这就是这系列笔记的来源之所以。
然而最终发现,react-starter-kit实在不是一个平易近人的项目,匮乏的文档,匮乏的demo,匮乏的说明,尤其是,匮乏的starter-guide,实在有些匹配不上react-starter-kit这个名字。
——然而已经入坑了,那就只好慢慢填坑爬出来——一把辛酸泪。。。
内容
在展开所有内容之前,还是有必要讲讲React Starter Kit涵盖了哪些。以下是github项目上介绍:
React Starter Kit — isomorphic web app boilerplate (Node.js, Express, GraphQL, React.js, Babel 6, PostCSS, Webpack, Browsersync)
这是React Starter Kit项目的介绍。
总体上呢,我认为可以分为两个部分:
- 工具部分:webpack,babel,browserSync等
- 框架部分:Express,GraphQL,redux,React等
除此以外是个人规划部分:
- 数据库:Mongodb,使用mongoose做连接池
- 模板引擎:干掉Jade,使用artTemplate(不要问我为嘛用这个,只因为习惯了,另外憎恨Jade语法)
加起来,react-starter-kit大概涉及到了:webpack,babel,browserSync,Express,GraphQL,redux,React,mongoose,artTemplate,名副其实的全家桶,需要的储备知识着实不少。
模板引擎
第一步是src/views目录下的两个jade模板。这是首页和报错页面的基础模板。其中首页模板会在各个页面被重用。
下面是关键上下文代码之一
1 | //file:src/server.js |
其中,可以看到两个地方引用(require)了jade模板,并且代码最终会被webpack打包,所以这里webapck使用了jade-loader,为了可以将index.jade改成index.html,我们需要安装 tmodjs-loader
,确保html后缀的artTemplate模板可以被正确识别和编译。
下面是操作步骤
- 安装tmodjs-loader:
npm i tmodjs-loader --save-dev
- 转换jade2html: html2jade,将jade贴到右边左边会有编译的HTML,补充好变量位置即可。
- 设置webpack的loader
在tools/webpack.config.js
line127左右的位置插入以下代码,为模板设置正确的loader1
2
3
4{
test: /\.html$/,
loader: "tmodjs"
}
关键上下文代码之一:
除此以外,在src/content目录下有若干的jade文件,这个是Content Component的jade文件,为了去除jade,我们将它转换为markdown文件即可。Content Component逻辑中已经配置好markdown文章的逻辑。不需要操作更多。
至此,jade模板更换artTemplate工序完成。
mongoose
为了链接mongodb,这里使用了mongoose来连接和操作。
安装
安装很容易,在终端下运行:
1 | npm i mongoose --save |
配置
安装完成之后我们呢需要配置一下才能够使用,在src下新建mongoose目录,用来存放Schema等相关的东西。结构如下:
1 | mongoose |
这里仅仅展示一下News.js和index.js,已经足够展示整体结构了。
1 | //file:News.js |
可以看到,虽然目录名字虽然叫做Schema,但是导出的是model,这是为了方便进行数据操作。至于index.js,只是为了方便导入各个Model而做的归集。
另外,这里有个变量mongoDbUrl,从外部引入了,这里也贴一下相关的配置:
1 | let mongodbInfo = { |
实际上就是一个带了认证信息的mongodb链接。
这部分内容只是很简单的讲解了如何进行安装,配置,使用上还是需要对mongoose有基础的认识,需要一些知识储备。之前写过的mongoDB笔记(二)可以做一些浅显的参考,更具体的概念性东西,大概需要读者另外爬文了。
API
有了数据库连接池,那么现在往下走,基于monogoose来做一些API。API主要考虑到两个方面,一个数据读写,一个是路由设置。
路由
我们先从路由开始开工。
在src下新建api文件夹,建立api/index.js文件。
下面弄个简单的index.js例子
1 | import { Router } from 'express'; |
完毕之后在src/server.js中添加路由相应的路由代码:
1 | import api from './api'; |
数据读写
数据读写的代码其实在上面已经贴出来了。
1 | News.find().exec(function(){ |
不过这里仅仅是非常简单的全部查询,并没有限制性的条件,这在大多数时候是不存在的,不过这里还算合用(马上讲到GraphQL)。如果需要了解更多的相关mongoose的查询语句,可以参考我之前写的笔记mongoDB笔记(三),这篇笔记对响应的查询都有比较详细的记录。
小总结
到这里,就可以使用浏览器访问 /api/news
来获取json数据了。
GraphQL
GraphQL是个很赞的东西。怎么形容它呢?当前前端有个词,叫做响应式,页面会根据屏幕宽度来展现不同的外观。而GraphQL的最大优势和这个词汇有点像。它可以从前端接受查询语句,然后按照要求返回指定的字段。
优势
也许指定的字段这个不太能突出GraphQL的优势,这里举些例子吧。
例一:
当前如果有个接口 /api/list
,返回的数据结构是这样的:
1 | { |
而实际上,页面逻辑需要这样的就够了:
1 | { |
如果前端队这个接口高度复用,不同页面只是过去了name,title,brand等数据进行了单独的调用,可以复用的时候实现最优json结构保持简洁和节省流量带宽吗?
例二:
数据结构和例一相同,但是当初接口设计时候只需要做查询就够了,又或者设计时候只接受name进行过滤,到那时现在我们需要队brand进行过滤,此时应该怎么办?
例三:
有两个接口 /api/list1
和/api/list2
,结构和例一一致,但是两种不同品类商品
假如我们有这样一个需求:
- 从list1中过滤出brand==”que01”
- 从list2中过滤出color== “yellow”
- 将结果分别赋值给{data1:[],data2:[])
此时常规的办法的是怎样的?先请求一次list1,过滤,然后请求list2,过滤。拼接。两次请求,3次数据处理,如果服务端承担了这个过滤,也必须请求两次,然后进行合并操作。我们可以更简单一些嘛?
是的。在GraphQL中,这些可以毫不费力的实现。这实在是一个超级令人激动的东西。
React-starter-kit本身已经集成了GraphQL。但是要使用起来,还是有一些注意事项。不过本文主要立足于怎么将GraphQL在react-starter-kit中用来了,所以就不做太多的理论说明了,有时间单独总结一下它的使用,上面的例子,只是为了让大家明白他的优势。
使用
在react-starter-kit中使用GraphQL不是一件太困难的事情。
在server.js中有以下代码:
1 | app.use('/graphql', expressGraphQL(req => ({ |
GraphQL已经作为中间件载入了。这里仅对初步使用作出讲解。下面是src/data目录的结构
1 | ├── models |
下面是我个人初步的schema.js
1 | import { |
这里是最外层的接口了。其中tags,news,content都是最外层的api,也是我们需要自行定制的地方。
做好这些以后我们查询时候发送请求到/graphql
接口。
下面这是发送过去的类似json的字符串:
1 | { |
然后返回的数据:
1 | { |
这里值得一提的是,title,link,author,publishedDate,contentSnippet这些字段可以任意顺序组合,删减。
简单的用法的我们暂时就这样简单的一笔跳过,详细的如果有时间另外写一篇讲解这个。我们现在来看看如何处理数据源。我们配合之前做好的api作为数据源来支挽GraphQL。
为了方便,这里使用tags来讲解。下面是tags.js的详细代码。
1 | import { GraphQLList as List,GraphQLString } from 'graphql'; |
这里args里面定义了接口接受的参数,resolve则定义了处理数据的方式并返回数据(第二个参数是传递的请求参数组成的数组),type则定义了数据类型。做好相应的逻辑配置之后,我们不仅可以想news那样直接返回所有数据,还可以传递参数id和name之一过去过滤数据.like this:
1 | //request: |
到这里,最简单的使用就可以跑起来了。这已经可以满足最基础的场景应用。这部分我们到此为止。下一步我们讲讲自定义组件和页面。
自定义组件和页面
react-starter-kit定义了一些页面,但是很显然,我们不能满足修改已有进行改造使用,更多时候我们需要更多的页面…以及…更多的组件构成的页面…
这里仍旧以/tags
页面为说明,这是一个新建的页面,使用了自定义的组件和数据源来构建的新的页面。
我们第一步要做的是在/src/routes
下新建一个页面,然后在内部建立 Tags.css、Tags.js、index.js
三个文件,保持同其他route组件的一致性。
下面是具体code:
1 | //file:Tags.js |
css代码就不贴了,虽然它是组件的重要组成部分,但是就逻辑来说,它无关紧要,不是吗?这里简单说下这两个文件,如果说Tags.js是组件的结构逻辑,那么index.js就是数据获取并渲染Tags.js组件的文件。
做好以上步骤以后,我们需要做最后一步,将其添加到路由内部,是我们访问 /tags
时候可以访问到。
一下是关键代码,文件位置是 /src/routes/index.js
1 | import tags from './tags'; |
关键点在于import和children中的tags。这里有个非常重要的事情是,自定义组件,请放在content上面(重要的事情说三遍:请放在content上面!请放在content上面!请放在content上面!),如果你不这样做,就无法保证自己路由优先基本,实质上代码逻辑中,经个人调试,会有一个『*』的路由,如果你不放到上面,它就被『*』匹配了,这样就没你的页面什么事情了,因为根本不会往下走了!
总结
本文虽然不是深度性的文章,但是确实是一个大纲性质和入门的文章。不管是mongoose、API、GraphQL还是React,他们几乎每个都能写本书。
所以说,文章虽然浅显,但是真想用好react-starter-kit,还是需要相对巨量的知识储备。
react-starter-kit,个人认为,虽然是for starter,但是是相对于react-starter-kit的受众starter来说,它实在不是相对于前端初学者。
虽然是个starter-kit,但是:
—— 如果你没有学过express,请不必细看下去;
—— 如果你没有学过mongoose,请不必细看下去;
—— 如果你没有学过React,请不必细看下去;
—— 如果你没有打算学GraphQL,请不必细看下去;
就这样吧,感叹下,前端实在太快,如果没有足够的知识储备,真的无法走在前沿。
——向小伙伴们祝好!