剑客
关注科技互联网

commentbox用到了那些前端技术

commentbox用到了那些前端技术

这是
写个抓取网易云音乐精彩评论的爬虫 – Python之美 – 知乎专栏 的最后一篇。本节将主要分享
GitHub – dongweiming/commentbox: 网易云音乐精彩评论

中前端部分我的实践。

一直在考虑要不要加这么一篇,因为本章的内容和Python真的没有啥直接关系,所以有点超出专栏的定位。但考虑到Python Web开发者经常也会写前端,希望此篇能够抛砖引玉的给大家带来些帮助。

通过首图大家可以知道我在这个项目中用到了那些前端,我来分别介绍下技术选型的原因,并介绍实践过程中的一些值得分享的地方。

React

React想必大家都所有耳闻了,它是构建大型,快速 Web app的首选方式,已经在 Facebook 和 Instagram 以及国内灰常多的大厂有了广泛的应用,也包括豆瓣(( ̄y▽ ̄)~. 虽然不算大厂)。我们组的产品开发并不是专职的前端开发,但是由于团队成员前端能力都还不错,所以基本上前端的活儿也是我们自己写。从去年下半年开始,在我们组的多个用户可见的新功能、后台都使用到了React,这种组件化的开发模式已经被大家接受。那么它究竟好在哪里?

1. 它的虚拟DOM Diff算法可以将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上。

2. 组件化的思想把UI分成不同的组件,每个组件都独立封装,这样写出来的代码清晰,组件可维护,可重用,可组合。

3. 学习React之后,除了能够写Web、还能帮助你熟悉React Native,相当于减少了学习成本。

随便提一下,React更适合有复杂交互的单页面应用(SPA),并不是什么场景下用React都最好,虽然开发者乐意啥都无所谓。

2. Material-UI

它是根据Google的
Material Design

实现的一个React组件集合项目,这个在我们组使用很广泛,基本上现在新的后台都使用React+Material-UI的模式。

如果5年前和我说:「嗨,我们现在正在用Bootstrap!」,我会觉得「啊,好酷!」,然而现在是2016年,我已经被满大街的Bootstrap风的网站弄得审美疲劳了 ( ´☣///_ゝ///☣`)。 Material-UI自带了很多很酷的组件,比如Badge、Chip、Date Picker、Progress、Snackbar等等,而且现在还在不断加新的特性。

3. Mobx

在复杂的单页面中,JavaScript需要管理很多的 state (状态,比如服务器的响应、激活的路由,被选中的Tab或者标签、分页等等),那么多的状态在什么时候,由于什么原因,发生怎样的变化让项目变得愈加复杂,所以经常一个JavaScript文件几百甚至上千行。React会禁止异步和直接操作 DOM 来解决这个问题,但是我们还要解决处理状态中数据的问题。

之前一直用redux管理状态,用过的人都知道,累… 它那个文档我啃了一周多才弄清楚,每次添加新的状态都特别痛苦。而mobx对自己的描述是「Simple, scalable state management」, 如果你使用React,喜欢面向对象,羡慕vue的简单直观,一定一定要体验下Mobx。连redux的作者 Dan Abramov 都发推说( https:// twitter.com/dan_abramov /status/723979142350417921 ):

Unhappy with Redux? Try MobX

其实我这个项目就是为了学习mobx而写的…. 怎么用呢?由于我这个项目比较简单,为了更新起来方便,我只用一个store( commentbox/commentStore.js at master · dongweiming/commentbox · GitHub ),mobx提供了三个装饰器:

1. observable。可观察对象,这是设计模式中常用的 观察者模式, 一个观察者(Observer)管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。

2. action。可以理解为Python的方法。

3. computed。可以理解为Python的property。

本项目的核心数据源就是观察对象「 comments 」,在一系列事件中,this.comments会改变,这样React就会重绘/添加最新的页面了。

4. Fetch

Fetch并没有Logo,所以没有显示在头图中。传统的获取后端数据的方式是 Ajax ,也就是用 XMLHttpRequest(XHR),XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。Fetch 的出现就是为了解决 XHR 的问题,拿例子说明:

使用 XHR 发送一个 json 请求一般是这样:

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.onerror = function() {
  console.log("Oops, error");
};

xhr.send();

使用 Fetch 后,顿时看起来好一点:

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});

使用 ES6 的 箭头函数 后:

fetch(url).then(response => response.json())
  .then(data => console.log(data))
  .catch(e => console.log("Oops, error", e))

本小节内容大部分来自 传统 Ajax 已死,Fetch 永生 · Issue #2 · camsong/blog · GitHub

5. ES6

ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ES6将彻底改变你编写JS代码的方式!不了解的可以买本阮一峰老师的《 ECMAScript 6入门 》看看。

另外推荐看的是这篇 前端开发者不得不知的ES6十大特性 ,里面提的十大特性真的非常有意义,本项目中都有体现,限于篇幅我就不一一列举了。

ES6一定要学,这个可比要学Python 2还是Python 3答案明确的多!!

6. Babel

旧的浏览器是不支持ES6语法的,而我们无法决定用户使用的浏览器。 Babel 是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。这意味着,你可以用ES6的方式编写程序,又不用担心现有环境是否支持。Babel也是现在前端开发必备的解决方案。

7. Webpack

Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 ES6 模块、CSS、图片等。

本项目用的 webpack.config.js 中有个细节,在 commentbox/webpack.config.js at master · dongweiming/commentbox · GitHub 我定义了:

new webpack.ProvidePlugin({
        'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
    })

这样就可以全局的使用fetch而不需要import了,比如在 commentStore.js 中fetch可以直接使用。

我使用比较古老的方式Makefile而不是package.json管理项目:

 cat Makefile 
webpack=./node_modules/.bin/webpack

install:
	@npm install

dev:
	@node server.js

build:
	@NODE_ENV=production ${webpack} -p -c --progress

这算是个人习惯了:

执行「make dev」启动开发模式,执行「make build」生成dist,也就是打包好的js文件,通过再上线前进行。

可以看到,为了调试方便我添加一个 server.js ,并在assets也放了一个index.html文件。我列出来server.js全部内容,然后添加一些注释:

// https://www.npmjs.com/package/colors,给终端加一些颜色,提神
var colors = require('colors');
var webpack = require('webpack');
// 一个轻量的NodeJS express服务器
var WebpackDevServer = require('webpack-dev-server');
// 模块如其名,HTTP代理,后面会说到用法
var httpProxyMiddleware = require('http-proxy-middleware');
// 首先加载webpack.config.js的配置
var config = require('./webpack.config.js');

config.debug = true; // 启用debug模式,替代webpack.config.js的设置
config.devtool = 'eval'; // 修改开发工具模式
// 下面这段相当于对entry里面的每项的值的左面都插入下面三个元素,虽然本例中只有index一项
Object.keys(config.entry).forEach(key => {
    var item = config.entry[key];
    item.unshift(
        'react-hot-loader/patch',
        'webpack-hot-middleware/client?path=/__webpack_hmr',
        'webpack/hot/only-dev-server'
    );
});

// 给plugins添加如下2个插件
config.plugins = config.plugins.concat(
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin()
);

var compiler = webpack(config);
var app = new WebpackDevServer(compiler, {
    hot: true,
    filename: config.output.filename,
    publicPath: config.output.publicPath,
    stats: {
        assets: false,
        colors: true,
        chunks: false,
        children: false
    }
}).app; // 使用WebpackDevServer创建一个应用

// webpack-hot-middleware模块用来实现浏览器的无刷新更新(hot reload),这也是webpack文档里常说的HMR(Hot Module Replacement)
app.use(require('webpack-hot-middleware')(compiler, {
    log: console.log,
    path: '/__webpack_hmr',
    heartbeat: 10 * 1000
})); // 添加路由 /__webpack_hmr, 

app.use(httpProxyMiddleware('/', {
    target: 'http://localhost:8100/'
})); // 添加代理,全部路径的请求都转发到本地8100端口的后端服务(也就是通过「python app.py」启动的Flask的应用)

// 最后让这个express启动,监听3000端口
app.listen(3000, '0.0.0.0', function(err) {
    if (err) {
        console.log(err);
        return;
    }
    console.log('[webpack-dev-server]'.magenta); // 终端打印一些带颜色的输出
    console.log('* You can visit:'.green);
    console.log('   > ' + 'http://0.0.0.0:3000/'.underline.cyan);
});

启动「make dev」之后,当你修改完源码,就会自动重新编译了,很方便。

8. ESLint

Python有Pylint,CSS有CSSLint,ESLint 支持 ECMAScript 5 语法,还可以通过使用解析器选项让它支持 ECMAScript 6 和 7 以及 JSX 的验证。它被设计为是完全可配置的,这意味着你可以关闭每一个规则,只运行基本语法验证,或混合和匹配绑定的规则和自定义规则,以让 ESLint 更适合于你的项目。我把ESLint配置放在了 .eslintrc 中,它在webpack.config.js的 preLoaders 中被调用,每次hot reload或者build的时候都会触发先验证是不是符合要求。

9. react-router

React Router 是一个基于React之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与URL间的同步。路由功能是一个纯前端的解决方案,与我们熟悉的Python后台路由不太一样。后台路由,通过不同的URL会路由到不同的控制器上,再渲染到页面。而React Router是在组件中定义路由规则,然后通过不同的URL,告诉组件加载哪个组件。

更详细的介绍可以看 简介 | React Router 中文文档

最后说一下我的前端项目的目录结构(有些目录限于篇幅并没有展开):

❯ tree -L 3
.
├── README.md
├── app.py
├── assets  # 前端源码,配置,模板等都放在这里
│   ├── Makefile
│   ├── index.html
│   ├── node_modules
│   ├── package.json
│   ├── server.js
│   ├── src  # 全部前端源码都在这个目录下
│   └── webpack.config.js
├── config.py
├── ext.py
├── libs
├── models.py
├── requirements.txt
├── run.py
├── spider
├── static
│   ├── images
│   └── js
│       └── dist  # webpack生成的js文件都在这个目录下,也是templates/index.html中指定的js文件的路径
├── templates
│   └── index.html
├── venv
├── views

无耻的广告: 《Python Web开发实战》上市了!

commentbox用到了那些前端技术

———————————————————————————————————-

欢迎加入QQ群522012167,或者WEB上扫码进QQ群:

commentbox用到了那些前端技术

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址