V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
bramblex
V2EX  ›  JavaScript

手撸了一个简单 web 框架,拿来做博客

  •  
  •   bramblex · 2016-02-24 11:14:19 +08:00 · 7300 次点击
    这是一个创建于 3202 天前的主题,其中的信息可能已经有所发展或是发生改变。

    手撸了一个简单 web 框架,拿来做博客

    这两个半个月自己简单手撸了个 web 框架。用得是 PureScript 撸的, PureScript 跟 CoffeeScript 一样是一门 target 到 JavaScript 的语言,虽然 PureScript 从语言本身的设计角度来说比 CoffeeScript 不知道高到哪里去了……但那也架不住 CoffeeScript 简单方便易学大众有生态。

    其实拿 PureScript 手撸这个 web 框架是用来炫技的, PureScript 的强类型纯函数式的特性我觉得真的不太适合应用场景,把本身很简单的事情变复杂了。用 JavaScript / Ruby / Python / PHP 我实现这些东西顶多就两三天。

    》》Github 传送门
    》》LoveAria.Me 博客主站

    下面讲讲我主要做的事情:

    1.SQLite3 的 PureScript Binding ,以及一个简单的 ORM (还是半残状态,连 JOIN 我都没实现好,强类型面对这种场景只能日狗)。

    虽然是自己手撸的……但是放心,注入不了的,本宝宝做了防注入的。

    可以用下面哪种好看的方式做查询了,例如:

    insert "article" [ "title" .= title
                    , "category_id" .= category_id
                    , "raw_content" .= content
                    , "content" .= Markdown content ]
    
    update "article" [ "title" .= title
                    , "category_id" .= category_id
                    , "raw_content" .= content
                    , "content" .= Markdown content] ("id" .== id)
    
    first "article" ("id" .== id .&& "user_id" .== user_id) (Asc "id")
    
    findall "article" ("category_id" .<- [cid1, cid2, cid3]) (Desc "id")
    

    2.一门 HTML 模板 DSL 。因为是 PureScript 的 DSL ,所以其实还是 PureScript 本身。只是语法看上去像一门单独的语言而已, 并且还是有些丑的。

    list :: Array Category.RichArticle -> Template
    list articles = do
      base
      title "Article"
      extend "body" $ do
    
        ifLogined $ \_ ->
          t_a [a_href := "/article/create"] $ text "Create"
    
        article_list articles
    
    article_list :: Array Category.RichArticle -> Template
    article_list articles = do
      t_table [] do
        t_tr [] do
          t_th [] $ text "Id"
          t_th [] $ text "Title"
          t_th [] $ text "Category"
          t_th [] $ text "Create At"
          t_th [] $ text "Update At"
    
          forT articles $ \article -> do
            t_tr [] do
              t_td [] $ text $ show article.id
              t_td [] do
                t_a [a_href := "/article/show/" ++ show article.id]
                  $ text article.title
              t_td []  do
                t_a [a_href := "/article/category/" ++ show article.category.id]
                  $ text article.category.name
              t_td [] $ text article.create_at
              t_td [] $ text article.update_at
    

    3.基础的框架是在 PureScript-Express 上面建立的。所以基本的 handler 处理还是沿用 Express 。

    main :: forall e. ModelApp (console :: CONSOLE | e)
    main = do
      liftEff $ log "Setting up"
      setProp "json spaces" 4.0
    
      useExternal $ MW.bodyParser {extended: false}
      static_path <- liftEff $ Config.static_path
      useExternalAt "/static" $ MW.static static_path
    
      useExternal $ cookieSession {secret: Config.security_key}
      useExternal $ MW.setCookiesMaxAge (3600 * 24 * 30)
    
      use CacheHandler.logger
      use CacheHandler.cacheMiddleware
    
      mount "/" HomeHandler.main
    
      mount "/user" UserHandler.main
      mount "/article" ArticleHandler.main
      mount "/category" CategoryHandler.main
      mount "/cache" CacheHandler.main
    

    4.现在博客的功能基本完善。讲一下框架之上博客的功能:

    1. 文章的增删改,搜索功能还没做,感觉没什么必要做。在下一条讲
    2. 不限制层次的分类。对的,分类就是树状递归结构,不限制层数。你爱几层就几层,跟文件系统的目录类似。用这样的分类来整理文章,我觉得根本没必要搜索了吧。而且我这一辈子能写一千篇高质量的博客不?
    3. 页面缓存。因为 ORM 设计的问题和分类目录递归查询量很大,所以我干脆就直接给他们做了一个 10 分钟的页面缓存。登录成功的用户忽略缓存。成功发布或者修改 文章和分类 会简单全部刷新缓存。

    5.关于前端

    前端方面我准备使用 PureCSS 来做基本的 CSS 框架,然后做一个简洁好看的 UI 。 /w\ 没错,本宝宝就是那么纯( Pure ) 。 JavaScript 部分依旧还是用 PureScript 来做。当然 PureScript 写前端也有些蛋疼,不过我能折腾 /w\。

    啊~ 终于能够好好写东西并且实验奇怪小东西的地方啊啦~

    》》Github 传送门
    》》LoveAria.Me 博客主站

    55 条回复    2016-03-01 12:22:42 +08:00
    bramblex
        1
    bramblex  
    OP
       2016-02-24 11:19:33 +08:00
    估计也没几个人能看懂,太小众的东西哎。 ╮(╯▽╰)╭
    brucefeng
        2
    brucefeng  
       2016-02-24 11:52:22 +08:00
    说句心里话,不喜欢框架,要造轮子就造个工具吧,框架这种东西限制太多,用起来束手束脚。
    bramblex
        3
    bramblex  
    OP
       2016-02-24 11:56:43 +08:00
    @brucefeng

    要看您喜欢什么工具咯~
    jarlyyn
        4
    jarlyyn  
       2016-02-24 12:01:37 +08:00
    说实话,不是看不懂,是不敢回,呵呵呵。
    vagarlee
        5
    vagarlee  
       2016-02-24 12:05:03 +08:00
    表示小白完全不懂。。。
    flowerains
        6
    flowerains  
       2016-02-24 12:09:24 +08:00
    看不懂,好厉害的样子( ⊙o⊙?)不懂
    bramblex
        7
    bramblex  
    OP
       2016-02-24 12:10:03 +08:00
    @jarlyyn

    语言太小众了……
    几乎都没人听过……
    只在 Haskell 圈里面小范围有人知道
    jarlyyn
        8
    jarlyyn  
       2016-02-24 12:15:32 +08:00
    @bramblex

    语言这东西又不重要。一般的代码要说写可能写不出,看不懂的还是比较少的。

    更何况还是博客这种烂大街的系统。

    首先作为一个框架来说,没有 test 基本属于不可饶恕的。

    其次缓存明显不该强制……

    然后 role 字段放在 user Model 里我个人不是很认同。

    大概看了一圈代码,大概是这些问题吧。
    jarlyyn
        9
    jarlyyn  
       2016-02-24 12:17:47 +08:00
    @bramblex

    还有

    getHomePage = findArticleById 0

    这个也太脏了吧?

    至少放在 config 里吧……

    或者是我理解错了?
    bramblex
        10
    bramblex  
    OP
       2016-02-24 12:22:20 +08:00
    @jarlyyn

    您说这些问题确实存在:

    1. 因为自用,所以根本没写 test 。不过 test 可以用 purescript 项目的 test ……虽然麻烦点。
    2. 缓存问题吗……我自己强制的,还是因为自用,没考虑给别人用。
    3. role 字段放在 userModel 里面是不应该的,然而……我这里 role 字段根本没起过作用,只是放在里面看的。
    4. home page 和 一般文章有什么区别吗? /w\ 既然没有,那我就直接扔给 aritcle 处理了,一切以方便出发~
    ChiChou
        11
    ChiChou  
       2016-02-24 12:37:32 +08:00
    写了框架居然不发红包?
    bramblex
        12
    bramblex  
    OP
       2016-02-24 12:38:23 +08:00
    @ChiChou 玛德智障
    jsyangwenjie
        13
    jsyangwenjie  
       2016-02-24 12:47:52 +08:00
    你用纯函数式语言撸这种框架真是蛋疼。。。刚在群里看到。。
    bramblex
        14
    bramblex  
    OP
       2016-02-24 12:57:47 +08:00
    @jsyangwenjie 对啊……真是蛋疼……不过终于能用了
    learnshare
        15
    learnshare  
       2016-02-24 13:23:26 +08:00
    特地去搜了一下 PureScript ,看来是 Python style 。
    tabris17
        16
    tabris17  
       2016-02-24 13:30:10 +08:00
    @learnshare 是函数式吧,老实说,真是继承了函数式语言的最大特性——完全没有阅读性
    bramblex
        17
    bramblex  
    OP
       2016-02-24 13:32:39 +08:00
    @tabris17

    不能因为看不懂就说没有阅读性啊……
    bramblex
        18
    bramblex  
    OP
       2016-02-24 13:34:34 +08:00
    @learnshare

    Python sytle 是什么鬼…

    应该说 Haskell sytle , python 是抄 haskell 的,而且还抄得很烂。
    bramblex
        19
    bramblex  
    OP
       2016-02-24 13:35:04 +08:00
    @tabris17

    我写得不好看只是单纯因为我写得烂而已……
    yuriko
        20
    yuriko  
       2016-02-24 14:04:46 +08:00
    曾经写过一阵子 haskell ,语言写起来实在麻烦
    bramblex
        21
    bramblex  
    OP
       2016-02-24 14:23:39 +08:00
    @yuriko

    写起来很爽啊,就是处理这种不知道具体类型的东西要蛋疼一些。不过其实也是可以很简单解决的。比如 Template Haskell ,或者自己造一个语言来生成 Haskell 代码。这些都是很简单的解决方案
    minsheng
        22
    minsheng  
       2016-02-24 14:25:42 +08:00
    楼主你是 C 写多了还是 C 写多了还是 C 写多了下划线是什么鬼?????
    edsgerlin
        23
    edsgerlin  
       2016-02-24 14:30:49 +08:00
    好像在知乎看到过 OP 安利 PureScript ……过几年 WebAssembly 普及,只要 GHC 有 LLVM 后端就能直接拿 Haskell 写啦。
    minsheng
        24
    minsheng  
       2016-02-24 14:30:51 +08:00
    Lib.Utils 是什么鬼东西啊,我虽然不用 PureScript 但是这些东西拿出来专门实现一遍也太鬼畜了吧?

    还有为什么 .js 和 .purs 放在同一个目录下,不是有 pulp 吗?
    minsheng
        25
    minsheng  
       2016-02-24 14:31:44 +08:00
    @edsgerlin GHC 本来就有 LLVM 后端, GHCJS 也早就理论上可以用了,但是生成文件的体积惨不忍睹
    bramblex
        26
    bramblex  
    OP
       2016-02-24 14:34:03 +08:00
    @minsheng

    是这样的,我自己曾经的语言风格是:
    类——首字母大写驼峰,
    函数 /方法——首字母小写驼峰
    变量——首字母小写下划线

    放在这里面好像不对劲……
    minsheng
        27
    minsheng  
       2016-02-24 14:35:11 +08:00
    然后楼主打算 type Sql = String 吗?你这是写 Python/NodeJS 呢……
    bramblex
        28
    bramblex  
    OP
       2016-02-24 14:35:37 +08:00
    @edsgerlin

    那就等普及吧~
    不过即便普及,我觉得 JavaScript 还能作为 target 语言活着。毕竟,你见过范式那么全的大杂烩吗? /w\
    minsheng
        29
    minsheng  
       2016-02-24 14:36:07 +08:00
    哦,楼上我好像看错了,无视我对 Sql 的吐槽,我来研究一下 Model
    bramblex
        30
    bramblex  
    OP
       2016-02-24 14:37:14 +08:00
    @minsheng

    purescript pures/ js 放在同一目录有问题?我不知道, purescript 的作者就是这样写的。我跟着他做的
    minsheng
        31
    minsheng  
       2016-02-24 14:37:32 +08:00
    @bramblex 入乡随俗,变量名请统一使用希腊字母,

    cata phi = In . fmap (cata phi) . out

    其它的统一驼峰法咯(逃
    bramblex
        32
    bramblex  
    OP
       2016-02-24 14:38:25 +08:00
    @minsheng

    炫技 / 练手 。至于有没有?

    当然是没什么卵用啊 !
    minsheng
        33
    minsheng  
       2016-02-24 14:38:35 +08:00
    @bramblex 我又傻逼了,我看成了你生成的 JS ……我就想怎么会犯这么低级的错误。 PureScript 的包我一点都不熟悉还是不看了,我们聊聊为什么不用 Haskell 吧?
    bramblex
        34
    bramblex  
    OP
       2016-02-24 14:42:26 +08:00
    @minsheng

    /w\ 还真可以……

    ```Haskell
    搞 = id
    比利 = id
    (♂) = id

    搞 ♂ 比利
    ```
    minsheng
        35
    minsheng  
       2016-02-24 14:44:03 +08:00
    @bramblex 来点严肃的吐槽,既然是炫技,你 SQL 还要手工定义 Schema 是不是太麻烦了?我记得最近 PureScript 似乎是支持 Generics 了——虽然 Template PureScript 还是坑,希望今年 GSoC 能加进去——搞个什么根据数据类型自动生成 SQL 操作代码岂不美哉?
    bramblex
        36
    bramblex  
    OP
       2016-02-24 14:44:08 +08:00
    @minsheng 因为我的 vps 装不进 ghc 。并且我不想折腾交叉编译
    bramblex
        37
    bramblex  
    OP
       2016-02-24 14:44:42 +08:00
    @minsheng 今年的 GSoc 还真有 Template PureScript 项目……
    learnshare
        38
    learnshare  
       2016-02-24 14:45:54 +08:00
    @bramblex 因为只见过 Python
    bramblex
        39
    bramblex  
    OP
       2016-02-24 14:46:38 +08:00
    @minsheng

    我想想怎么实现
    minsheng
        40
    minsheng  
       2016-02-24 14:49:48 +08:00
    @bramblex 好像用不上, PureScript 的 record syntax 比较神奇我不是很熟悉,但看你用得好开心啊。

    GHC 装不进 VPS 是嘛,这个确实是比较严肃的问题,我前段时间真是日了狗了 pandoc 编译 VPS 上死活不成功,结果查了一下 aeson 出了问题,那个版本需要 7GB RAM 才能编译,但是我所有的 Mac 都有这么多内存一点问题都没有……

    对啊对啊,你要不要试试, 5500 刀呢。
    reverland
        41
    reverland  
       2016-02-24 14:51:59 +08:00
    膜,楼主不是 haskell 大法好嘛
    4679kun
        42
    4679kun  
       2016-02-24 14:54:14 +08:00
    大神(´゚Д゚`)
    bramblex
        43
    bramblex  
    OP
       2016-02-24 15:00:53 +08:00
    @minsheng

    我那个 vps 一年 99 RMB ,你指望我能装上 ghc 吗?连硬盘都只有 3G ,装个系统就差不多了,哪里有地方给我装 ghc 嘛 TnT
    bramblex
        44
    bramblex  
    OP
       2016-02-24 15:01:12 +08:00
    @reverland 这个跟 Haskell 长得差不多
    bramblex
        45
    bramblex  
    OP
       2016-02-24 15:01:22 +08:00
    @4679kun 活捉~
    scarlex
        46
    scarlex  
       2016-02-24 15:47:25 +08:00
    下一步就是整合 elm 来写前端了么?
    bramblex
        47
    bramblex  
    OP
       2016-02-24 16:10:06 +08:00
    @scarlex 正在用 purescript 写前端中 虽然麻烦
    edsgerlin
        48
    edsgerlin  
       2016-02-24 18:04:07 +08:00
    另外,写后端直接用 Haskell 不好吗……
    bramblex
        49
    bramblex  
    OP
       2016-02-24 18:30:27 +08:00
    @edsgerlin 我的 vps 只有 3G 硬盘…… ghc 装都装不上。而且我不想折腾交叉编译
    reverland
        50
    reverland  
       2016-02-24 22:56:05 +08:00 via Android
    @bramblex 我还觉得 js 和 scheme 差不多,真的
    reverland
        51
    reverland  
       2016-02-24 22:56:37 +08:00 via Android
    @bramblex 你们不去贴吧了么。。
    scarlex
        52
    scarlex  
       2016-02-25 09:48:18 +08:00
    @bramblex
    我也学过 haskell ,也看过类似 yesod 之类的 web 框架,但在 vps 上面 build 的时候直接报内存不足了。
    不知道在服务器上跑 haskell 的东东最起码要多少内存?
    bramblex
        53
    bramblex  
    OP
       2016-02-25 12:49:57 +08:00
    @scarlex

    我没有具体了解要多少。据说 8G 够用……
    qqjt
        54
    qqjt  
       2016-02-25 21:28:57 +08:00
    打不开呀
    bramblex
        55
    bramblex  
    OP
       2016-03-01 12:22:42 +08:00
    @qqjt 哎,一直都好好的啊?可能是你打开的时候刚好遇到我在升级
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1052 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 19:01 · PVG 03:01 · LAX 11:01 · JFK 14:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.