一个 Node.js+mongoDB+Vue.js 的博客内容管理器

8,168 阅读4分钟
原文链接: www.jianshu.com

在用过臃肿的WordPress后,一直想自己写一个轻便简约的博客内容管理器(CMS)
一拖再拖,在暑假开学前,终是完成了这么个玩意儿。

嗯,其实我想完成的功能:
  • 一个基本的博客内容管理器功能,如后台登陆,发布并管理文章等
  • 可以管理博客页面的链接
  • 支持markdown语法在线编辑
  • 博客页面对移动端进行适配优化
  • 用户自定义主题和账户修改(未完成)
  • 页面足够大气、酷炫嘿

于是,为了彰显一贯的酷炫,我给后台写了一套星空主题。。。

登陆页面

login.gif

后台管理页面

console.png

但博客页面最后没用后台的星空主题,主要是觉得黑色不太好搭配。
于是我想,既然前端都是用Vue.js写的,那就参chao考xi一下Vue.js尤雨溪的博客样式吧!
为了保持不是和尤大大的博客一个样(恰逢近日尤大大把博客改了一番),在这基础上又加了自己写的canvas动画,应该是足够优雅啦
于是,我的博客页面:


blog.gif

Demo 在这里,登陆后台按钮在页面最下方“站长登陆”,可以以游客身份登入后台系统。

源码在这里

用到的技术和实现思路:

前端:Vue全家桶
  • Vue.js
  • Vue-Cli
  • Vue-Resource
  • Vue-Validator
  • Vue-Router
  • Vuex
  • Vue-loader
后端
  • Node.js
  • mongoDB (mongoose)
  • Express
工具和语言
整体思路:
  • Node服务端除了主页外,不做模板渲染,渲染交给浏览器完成
  • Node服务端不做任何路由切换的内容,这部分交给Vue-Router完成
  • Node服务端只用来接收请求,查询数据库并用来返回值

所以这样做前后端几乎完全解耦,只要约定好restful风格的数据接口,和数据存取格式就OK啦
后端我用了mongoDB做数据库,并在Express中通过mongoose操作mongoDB,省去了复杂的命令行,通过Javascript操作无疑方便了很多。

上文件目录

Paste_Image.png

我将前端的部分统一放到了src目录下,所有页面分割成一个单一的vue组件,放在component中,通过入口文件mian.js,由webpack打包生成,生成的文件放在public文件夹下。
后端文件放在server文件夹内,其实这就是基于Express的服务器,在server文件夹内执行

node www

就可以启动Node服务器,默认侦听3000端口

Webpack.config.js

关于webpack的配置文件,则是由Vue-Cli的基础上生成的,我只做了一点小改动。
话说React.js里就没用像Vue-Cli这样好用的脚手架,还是Vue.js简单优雅。。

var path = require('path')
var webpack = require('webpack')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './public'),
        publicPath: '/public/',
        filename: 'build.js',
    },
    resolveLoader: {
        root: path.join(__dirname, 'node_modules'),
    },
    module: {
        loaders: [
            {
                test: /\.vue$/,
                loader: 'vue'
            },
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/
            },
            {
                test: /\.json$/,
                loader: 'json'
            },
            {
                test: /\.html$/,
                loader: 'vue-html'
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'url',
                query: {
                    limit: 10000,
                    name: '[name].[ext]?[hash]'
                }
            }
            , {
                test: /\.(woff|svg|eot|ttf)\??.*$/,
                loader: 'url-loader?limit=50000&name=[path][name].[ext]'
            }
        ]
    },
    babel: {
        presets: ['es2015'],
    },
    devServer: {
        historyApiFallback: true,
        noInfo: true
    },
    devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map'
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            output: {
                comments: false,
            },
            compress: {
                warnings: false
            }
        }),
        new webpack.optimize.OccurenceOrderPlugin()
    ])
}

可以看出尤大大帮我们把浏览器自动刷新,热加载和生产环境的代码压缩都写好了,简直超贴心。
然而实际项目中,我还是碰到一个麻烦的问题,下面是package.json中的script脚本

"scripts": {
    "dev": "webpack-dev-server --inline --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "watch": "webpack --progress --color --watch",
    "server": "supervisor ./server/www"
  },
npm run dev

后,浏览器在8080端口开了一个服务器,然而这个服务器是用来服务前端页面的,也就是说,从这里启动服务器而不是开启Node服务器会造成数据无法交互,毕竟这个服务器不能连接数据库。但这个端口是可以在文件修改之后自动刷新浏览器的。

然后,通过分别执行

npm run watch
npm run server

来侦听文件改动,并重启Node服务器,此时浏览器是不能自动刷新的。找了一些方法但终归没解决。习惯了自动浏览器刷新,碰到这种情况蛮蛋疼的。虽然至少通过supervisor不用自己重启Node服务器了。。

于是只能妥协:
在修改样式的时候使用8080端口的服务器,在修改数据交互的时候手动刷新在3000端口服务器的浏览器。
就这样忍着慢悠悠的编译速度完成了开发。

写完这个博客管理器,感受还是蛮多的,对Vue.js中的数据绑定,组件化和数据流了解的更深入了一层,同时也对Node.js的后端有了一次优雅的实践。

马上开学了,如果有时间,在这篇文章里,我会把几个重要的Vue组件写一下分析,同时斗胆地分享对Vue.js全家桶之间配合的使用心得。。。

好不想去学校T_T