全栈开发实例:如何独立开发/发布一个 WebAPP - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
elevenBeans
V2EX    前端开发

全栈开发实例:如何独立开发/发布一个 WebAPP

  •  
  •   elevenBeans 2017 年 5 月 21 日 2053 次点击
    这是一个创建于 3156 天前的主题,其中的信息可能已经有所发展或是发生改变。

    talkIsCheap( )? goto(lastParagraph):continue( )

    背景

    全栈工程师,也叫全端工程师(同时具备前端和后台能力),英文 Full Stack developer。是指掌握多种技能,并能利用多种技能独立完成产品的人. ( From 百度)

    敲黑板:利用多种技能独立完成产品

    So, 至少需要一个人 cover 掉 前端+ 后端 + 数据库吧 ~

    搞一个活生生的投票应用送给各位 : )

    具体功能为:

    • 对于已经授权用户可以:

      • 新建一个 poll,可自定义其中的选项
      • 存储发起的 polls,下次登陆仍旧可以看到自己发起的 polls 集合
      • 看到应用中所有用户创建的 polls 的实时投票结果 (用图表展示)
      • 向所有 polls 投票(每个 poll 每个用户号只能投一票).
      • 可分享 poll (poll 详情页支持外部 landing)
    • 非授权用户只能:

      • 看到应用中所有用户创建的 polls 的实时投票结果 (用图表展示)

    开发过程

    整体技术目标:React + Express + Mongodb 完成一个投票 SPA

    前端

    • 概述

      • 使用 JS 语言标准 ES6
      • 模块化:ES6 module
      • 使用 React + ReactDOM 进行框架前端组件化开发
      • React-Router:SPA 的核心,与后端路由配合完成应用路由
      • React-router-transition:转场过渡效果就是要做到如丝般顺滑~
    • 前端入口 (View source)

      利用 React router 将首页指向 Home 组件,定义三个新路由 list、detail、new,分别指向对应页面组件。

      <Router key={Math.random()} history={browserHistory} > <Route path="/" compOnent={App}> <IndexRoute compOnent={Home}/> <Route path="/list(/:name)" compOnent={List}> </Route> <Route path="/detail(/:id)" compOnent={Detail}> </Route> <Route path="/new" compOnent={New}></Route> </Route> </Router> 
    • 页面级组件 每一个页面级组件对应一个应用页面,均继承自 React.Component

      • home (View source)
        • 作为应用的首页, 列出应用主要功能和信息
        • 对应 router: /
      • list (View source)
        • 列表页展示所有 polls 及对应 title、owner 等概要信息
        • 对应 router: /list(/:name)
      • detail (View source)
        • 详情页展示指定 poll 的详细信息
        • 对应 router: /detail(/:id)
      • new (View source)
        • 新建页收集新建 poll 的必要信息
        • 对应 router: /new
    • 公共组件

      • header (View source): 所有页面的共同头部,包含个性化 menu、用户头像姓名,登入登出按钮等等

      • footer (View source): 可复用的页面底部,包含 copyright 信息

      • loading: 加载动效 (推荐一个工具 loading.io

      • spning: 按钮等待动效

    • 异步请求

      • zepto ajax (均采用 POST, 整站开发, 不跨域)

    后端

    • 概述

      • 使用 Express 框架搭建后端服务,作为 SPA 的入口和容器。
      • 使用单一职责的 express.Router(),配合前端 React-router。处理外部直接 Landing、原地重刷新以及区分 404 页面:
      • 使用 ejs 模版引擎作为主应用的后端 View:
    • Views

      • index (View source): 后端入口模版,提供 React.reader() 的目标 DOM 节点
      • header (View source): 模版公共头部:HTML 的 <head> 信息,以及在其中需要同步加载的 js、css 资源
      • footer (View source): 模版公共尾部: 主要用于加载 HTML 尾部 js 资源
      • error (View source): 错误页模版
    • Views Router (View source)

      所有 Landing 或者页面刷新的链接都由后端同一收口到 views 中的 index,再由前端统一处理。

      router.get('/detail/:id', throwToHome); router.get('/detail', throwToHome); router.get('/list/:name', throwToHome); router.get('/list', throwToHome); router.get('/new', throwToHome); router.get('/', throwToHome); router.get('*', throwToError); function throwToHome(request, response){ response.render('index', { cdnUrl: config.CDN_URL } ); } function throwToError(request, response){ response.render('error', { cdnUrl: config.CDN_URL } ); } 
    • 第三方用户登陆

    • API (View source)

      • /getPollList: 获取 polls 列表
        • 入参: userName (用户名),可获取该用户创建的所有 polls; 缺省 userName 则获取所有存在的 polls
        • 返回: 符合条件的 polls 列表
      • /getPollByID: 获取指定的 poll 的详细信息
        • 入参: pollID (poll 唯一标识)
        • 返回: 一个包含指定 poll 的单元素列表
      • /upDatePollByID: 更新一个 poll (投票)
        • 入参 pollID (poll 唯一标识); index(用户具体投给的选项编号); voter(传递投票的用户名,避免用户对同一个 poll 多次投票)
        • 返回 result: bool 类型值,告诉你是否更新成功
      • /insertPoll: 新建一个 poll
        • 入参title(poll 题目),description(poll 描述),options: (poll 中的选项),ownerName(创建用户), voterList(投票用户,初始为空数组)
        • 返回 result: bool 类型值,告诉你是否创建成功

    数据库

    • Mongodb MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

    • 环境安装和配置

      • 下载:Download
      • 安装:解压压缩文件至你任何想要存放的地方
      • 配置:二进制文件可以直接执行, 配置你的 .bashrc文件:export PATH=<mongodb-install-directory>/bin:$PATH, 例如我的是 export PATH=$HOME/mongodb/bin:$PATH
      • 运行 mongodb 服务, 默认 27017 端口
       mongod 
      • 运行 Cli, 用命令行对于数据库的常用操作

        mongo // 进入 Cli 
        show dbs // 显示所有数据库 
        use <dbName> // 进入指定数据库 
        show collections // 显示所有 collections (table) 
        db.<collectionName>.find({}) // 查询 
        db.<collectionName>.deleteOne({}) // 删除 
      • Express 连接 Mongodb (View source)

        var dbUrl = 'mongodb://localhost:27017/voting' var mOngo= require("mongodb").MongoClient; mongo.connect(dbUrl, function(err, db){

        var pullList = db.collection('pollList'); pullList.find({ownerName: ownerName},{}).sort({timestamp: -1}).toArray(function(err, docs){ if(err){ db.close(); errCal(err); } else { db.close(); sucCal(docs); } }); });

    • 数据库 collection (table) 设计 userList schema:

       { "type": "array", "items": { "type": "object", "properties": { "_id": { "type": "integer" }, "email": { "type": "string" }, "name": { "type": "string" }, "timestamp": { "type": "integer" } } } } 

    pollList schema:

     { "type": "array", "items": { "type": "object", "properties": { "_id": { "type": "integer" }, "description": { "type": "string" }, "options": { "type": "array", "items": { "type": "object", "properties": { "count": { "type": "integer" }, "index": { "type": "integer" }, "option": { "type": "string" } } } }, "ownerName": { "type": "string" }, "pollID": { "type": "string" }, "title": { "type": "string" }, "voterList": { "type": "array", "items": { "type": "string" } } } } } 

    发布过程

    heroku 发布代码至云服务

    官网 (可能需要梯子)

    • 下载 Heroku Cli Download
    • 进入项目根目录
    cd WeVoting 
    • 执行 heroku login 进行登录,无账号则去官网申请
    • 执行 heroku create <yourAppName> 创建 App,这里的appName 也是你在herokuapp.com 下的三级域名
    heroku create we-voting-ele 
    最终域名为: https://we-voting-ele.herokuapp.com 
    • 推送代码到 heroku 进行发布
    git push heroku master 
    • 打开应用
    heroku open 
    • 新建一个 Procfile 设置服务开启命令
    web: node index.js 
    • Scale the app
    heroku ps:scale web=1 

    heroku addons 部署 mongodb 云服务 mLab MongoDB

    • 一行命令部署 mLab MongoDB 免费版

      heroku addons:create mongolab:sandbox 
    • 获取云数据库服务链接 Mongodb_uri, 用于后台代码连接 Mongodb 服务

      heroku config 

    详情请见:Getting Started on Heroku with Node.js

    Done ~

    img1

    LISENCE

    代码开源,一张图告诉你开源协议怎么选 by ryfeng

    最后送上源码和 Demo

    Demo 在此

    看完了就去 Git repository 加个星星吧 : ) 能互相 follow 就更好了 ~

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2659 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 04:13 PVG 12:13 LAX 20:13 JFK 23:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86