React + Node + Mongo +Webpack写一个简单的Blog网站

用到的技术:React Node Webpack material-ui mongo

github地址:https://github.com/shenjiajun53/HiBlog
喜欢请给个star!!!
推荐两个工具:https://app.astralapp.com/dashboard 这个网站可以用来管理github上的star

另一个叫 Octotree 是Chrome应用,可以看到github上的项目结构,跟IDE一样

我是一名Android开发,虽然在互联网公司,但是感觉自己的工作根本就是软件行业的工作。
想想对服务端,前端都不了解真是挺无知的。
之前看同事有自己的博客站,百度了下,发现要做那种个人网站真是很简单,只不过那根本就是个静态网站,太辣鸡,所以我决定自己撸个博客网站。

主页

home_page.png

注册页

register_page.png

下面就是技术选型啦:

前端:

要用就用潮的,三个著名框架Angular,React,Vue
Angular听说1和2完全不兼容,最讨厌这种对开发人员不负责的框架了,不考虑
Vue的语法更像常规的前端开发,React默认支持es6,风格跟Android更像,尤其跟Android的DataBinding很像。
另一方面es6很像Java,我肯定使用es6开发的,我更喜欢面向对象。Vue当然也可以用es6,但我懒得鼓捣了,更重要的ReactNative可比Weex火多了。哈哈,所以前端我就选择React了。
真正的前端开发应该更喜欢Vue吧,文档都有中文的。

后端:

虽然我是做Android的,但是遥想两年前第一次接触JavaEE的时候真是被恶心到了,不考虑
python没有花括号,知乎上都嘲笑写python要用游标卡尺,不考虑
PHP开发比Java更快,而且现在快跟Java平分秋色了吧,可以考虑。
Node技术还是挺新的,各种文章资料会比较少,坑也可能比较多。但我真是不高兴再学一门语言了,所以哈哈,就选Node了。

运行

1.git clone
2.安装mongo,然后在安装目录下新建文件夹,比如“D:\data\db”,然后打开“D:\MongoDB\Server\3.4\bin\mongod.exe”开启服务,会有个命令行窗口保持运行
3.建议安装一个mongo可视化工具,Robomongo,默认连接localhost:27017,能连接上就说明好了
4.进入项目目录下,执行命令

npm install

安装相关依赖库
5.执行

node server.js

开启服务。
或者,比如我用的Webstorm,可以点击左下角npm按钮,点击start-dev-serpervisor或者点击start-dev-nodemon,都可以

webstorm.png

6.打开浏览器,输入 localhost:5006

下面开始:

我对前后端几乎零基础,之前有看过ReactNative,顺便看了下React。
所以写的代码在内行眼里可能很丢人,哈哈

第一步:

安装node,新建个文件夹,HiBlog
命令行:

cd HiBlog

初始化:

npm init

生成package.json文件
然后安装各种需要的包,比如express--node框架,webpack--打包工具

npm i express  --save;npm i webpack --save

然后这两个就下载好了,在node_module文件夹下,引用也自动添加到package.json文件里了
或者package.json文件直接复制的别人的,里面有内容了,

npm i

把package里所有引用都下载到node_module下。
跟Android的依赖很像啊

我的module引用

{
  "name": "HiBlog",
  "version": "0.1.0",
  "private": true,
  "engines": {
    "node": "^7.4.0",
    "npm": ">= 3.x.x"
  },
  "devDependencies": {
    "concurrently": "^3.1.0",
    "nodemon": "^1.11.0",                                     //node监听工具,改动代码自动重启服务
    "supervisor": "^0.12.0",                                   //跟上面一样的,用一个就行,反正我都加了
  },
  "dependencies": {
    "antd": "^2.6.4",                                         //蚂蚁金服的UI框架,项目里没用,哈哈
    "babel-core": "^6.22.1",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "body-parser": "^1.16.0",
    "config-lite": "^1.5.0",
    "connect-flash": "^0.1.1",
    "connect-mongo": "^1.3.2",
    "cookie-parser": "^1.4.3",
    "css-loader": "^0.26.1",
    "ejs": "^2.5.5",
    "express": "^4.14.1",
    "express-formidable": "^1.0.0",
    "express-session": "^1.15.0",
    "express-winston": "^2.1.3",
    "jsx-loader": "^0.13.2",
    "marked": "^0.3.6",
    "material-ui": "^0.16.7",                                      //UI框架,项目里主要用的就是这个
    "moment": "^2.17.1",
    "mongoose": "^4.8.1",                                     //数据库框架
    "multer": "^1.3.0",
    "objectid-to-timestamp": "^1.3.0",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-router": "^3.0.2",
    "react-tap-event-plugin": "^2.0.1",
    "roboto": "^0.8.2",
    "sha1": "^1.1.1",
    "style-loader": "^0.13.1",
    "webpack": "^1.14.0",
    "winston": "^2.3.1"
  },
  "scripts": {
    "start": "node server.js",                                          //启动服务
    "start-supervisor": "supervisor --harmony server",        //启动服务    代码有变动就重启
    "start-nodemon": "nodemon server.js",                    //启动服务       代码有变动就重启
    "build": "webpack --watch",                                   //打包React代码, --watch代表代码有变动就重新打包
    "start-dev": "concurrently \"npm run start\" \"npm run build\"",
    "start-dev-supervisor": "concurrently \"npm run start-supervisor\" \"npm run build\"",
    "start-dev-nodemon": "concurrently \"npm run start-nodemon\" \"npm run build\""
  }
}

看下我的目录结构

2017-02-18.png

看下我的github页面,右边就是我在最上面介绍的github插件,工欲善其事必先利其器。

新建文件webpack.config.js,webpack工具会识别到这个文件里的脚本,然后把React代码打包,很重要,不然不管是React的JSX或者ES6,浏览器都读不懂。

新建文件夹views,里面是前端代码
新建文件夹routes,里面放路由代码,因为我们用的React,所以这个网站就是所谓的单页网站,One Page Website。看views下面只有一个index.html。
这个HTML就是个空壳,真正的网页都是有js代码生成的,不管是哪个页面,都依托这个HTML。所以这里和常规网页不通,网页不是由服务器渲染的一个个HTML。网站的工作方式更像APP,通过api实现网页内容变动。前后端分离才是人性化的开发方式,不是吗?

文件夹config,里面放一些设置

最重要的server.js

/**
 * Created by shenjj on 2017/1/23.
 */
let express = require('express');
let app = express();
let path = require('path');
let ejs = require('ejs');
let bodyParser = require("body-parser");
let MongoUtil = require("./server/lib/MongoUtil");
let session = require('express-session');
let MongoStore = require('connect-mongo')(session);
let cookieParser=require("cookie-parser");
let config = require('config-lite');
let flash = require('connect-flash');

let homeRouter = require('./routes/HomePageRouter');
let userRouter = require('./routes/userInfo');
// let signRouter = require("./server/signUp").signUp;
// let DealSignUp = require("./server/DealSignUp");
let RouterManager = require("./routes/RouterManager");

// 设置模板目录
app.set('views', './views');

// 设置模板引擎为 ejs
app.set('view engine', 'html');
app.engine('html', ejs.renderFile);

// app.use配置
app.use('/output', express.static(path.join(__dirname, '/output')));
//app.use('/views', express.static(path.join(__dirname, '/views')));
app.use('/uploadFiles', express.static(path.join(__dirname, '/uploadFiles')));

...
...

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

// app.use('/', homeRouter);
app.use('/users', userRouter);

let routerManager = new RouterManager(app);
routerManager.startRouters();


app.get('*', function (request, response) {
    response.sendFile(path.resolve(__dirname, 'views', 'index.html'))
});

app.listen(process.env.PORT || 5006);

console.log("url=" + process.env.PORT);

这里开始就是真的node代码里
设置模版目录在views下面,其实就是那个index.html
这是模版引擎ejs,用来渲染成html,(有两个主流引擎ejs和jade,ejs和html一毛一样,所以我推荐这个,jade虽然省代码,但是跟python一样,太随便了)
另外我不需要用ejs的功能,所以我直接设置成HTML了。

app.use('/output', express.static(path.join(__dirname, '/output')));
app.use('/uploadFiles', express.static(path.join(__dirname, '/uploadFiles')));
用来指定打包后的js代码,在output目录下,这个是在wenpack.config里设置的
uploadFiles是js代码里引用的图片,空目录,里面的图片是用户上传的。

RouterManager是我写的Router管理类,从风格也能看出我就是比较习惯Java,还是面向对象舒服,虽然代码量大一点。
routerManater把app传进去

最后是端口号,默认5006

RouterManager里:

...
        this.app.use("/", new HomePageRouter().getRouter());
        this.app.use("/api", new UserRouter().getRouter());
        this.app.use("/api", new BlogRouter().getRouter());
...

HomePageRouter里:

        router.get('/', function (req, res) {
            console.log("homepage on render");
            res.render('index');
            // res.render('');
            // res.redirect("/SignUp");
        });

所以就是,直接在浏览器输入localhost:5006,会跳转到主页
如果输入localhost:5006/api/xxx,会调起userRouter或者blogRouter里的接口,看那个匹配了

下面是部分前端代码

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            hasLogin: false,
            user: null
        }
    }

    componentWillMount() {
        let url = "/api/getUserInfo";
        fetch(url, {
            method: "post",
            credentials: 'include'     //很重要,设置session,cookie可用
        }).then(
            (response) => {
                return response.json();
            }
        ).then(
            (json) => {
                console.log(JSON.stringify(json));
                if (json.result) {
                    this.setState({
                        hasLogin: json.result.hasLogin,
                        user: json.result.user
                    });
                }
                // console.log("state=" + this.state.hasLogin);
            }
        ).catch(
            (ex) => {
                console.error('parsing failed', ex);
            });
    }

    render() {
        console.log('app render');
        // console.log('chileren=' + this.props.children.name);
        return (
            <MuiThemeProvider>
                <div>

                    <TopBar hasLogin={this.state.hasLogin} user={this.state.user}/>
                    {React.cloneElement(this.props.children, {user: this.state.user})}
                </div>
            </MuiThemeProvider>
        );
    }
}

render(
    <Router history={browserHistory}>
        <Route path="/" component={App}>
            <IndexRoute component={Home}/>
            <Route path="SignUp" component={SignUp}/>
            <Route path="SignIn" component={SignIn}/>
            <Route path="UserCenter" component={UserCenter}/>
            <Route path="MyFollow" component={MyFollow}/>
            <Route path="WriteBlog" component={WriteBlog}/>
            <Route path="BlogDetail/:blogId" component={BlogDetail}/>
            <Route path="Settings" component={Settings}/>
            <Route path="Favorites" component={Favorites}/>
            <Route path="MyBlogs" component={MyBlogs}/>
        </Route>
    </Router>
    ,
    document.getElementById('root')
)

页面跳转完全由前端控制,用Rooter类,APP是整个网页的父布局。在APP渲染完成后获取user信息,this.props.children是当前页面,可以clone一个ReactComponent,并设置props。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容