描述
去年各大平台纷纷开始占领微信上的又一流量入口——小程序。因为小程序的门槛低,这里指,技术上和前端大同小异,审核刚开始也比较松。除了大厂,很多个人开发这都投入进去。想在小程序上打响自己的个人品牌。在筹备了三个月之久,我的第一款小程序,终于快要完成了。在这里我会总结一下整体的过程,从idea到一个完整的小程序、期间遇到的坑、和觉得挺有意思的地方。
流程
1. 购买服务器
本人购买的服务器是阿里云服务器,因为经历的几家公司都是用的它,感觉还是比较靠谱的(我一同事也用过腾讯的服务,一直在吐槽不稳定,后来也换到阿里云了)
2. 购买域名 小程序的是无法直接通过IP访问,必须申请一个域名,同样的阿里云上买就行了。这里要提醒大家的是,因为国家政策原因域名需要备案,整个过程大概需要一个月时间。阿里云还是比较良心的,备案成功之后会再赠送你一个月的服务器时间。因为整个备案时间大概是一个月。所有绑定域名一定要提前。
3. 申请CA证书绑定到域名。在小程序里的API都需要Htps服务,如果你有CA证书可以直接使用,我也是通过阿里云申请的免费CA证书,时间是一年,到期看可以续的。
4. 根据idea设计产品
5. 开发小程序和server
6.发布
小程序
因为是我的第一个小程序,先试试手,所以选了一个比较简单的东西,音乐欣赏。数据是从其他网站爬过来插到数据库的。 本人是移动端出生,对前端和后端的东西都不是很熟,不过刚好去年写了不少RN的东西,前端的东西也算是半只脚入门了。在小程序里面文件分为下面几种
- js文件,和前端的一样,
- wxml文件,类似于html文件
- wxss文件,类似于css文件
- wxs文件,这是小程序的一套脚本语言,语法看似和JavaScript语法一样,其实他们是不同的语言,有自己的语法,并不和 javascript 一致 。我们可以把它当做方法类在wxml中来使用。在wxml中是无法调用js中的非事件方法的,如果从js文件里拿到的数据你希望再做一步处理然后展示,这样的处理需要放到wxs文件里。
开发前花半天浏览下微信小程序的API差不多就可以了,套路都差不多MVC。
数据库
服务器是用Node.js+MongoDB+Express搭建的,全套搭建起来还是很快的。Node.js是一个基于事件驱动I/O的服务端JavaScript环境,它在高并发的服务上有很好的体验。同样是js所以语法基本没门槛了。
MongoDB数据库和一般的关系型数据库不同,它是非关系型数据库。关系型数据库对数据操作都是:SELECT
、FROM
、WHERE
、BY
等。来感受一下MongoDB怎么操作数据:
//插入一个数据
var user = {
"name":"小芳",
"age":18,
"gender":1,
"country":"中国"
};
db.user.insert(user)
//查询姓名是:张三、李四、王五的信息
db.user.find({"name": {"\$in" : ["张三","李四","王五"] }})
给我最大的感觉,它是一个面向对象面向集合的存储过程,对于经常做面向对象开发人来说是比较容易入手的。
Express
基于Node.js的极其简洁灵活的web应用开发框架,它有丰富的HTTP快捷方法,非常快捷的创建node服务.
首页模块入口设置
...
...
...
var home = require('./routes/home');//首页接口
...
...
...
app.use('/home', home);//将home绑定到首页接口path
详细的首页模块
var express = require('express');
var router = express.Router();
var URL = require('url');
var MusicModel = require('./model.js');
const mongoose = require('mongoose');
//连接数据库并打开
mongoose.connect('mongodb://localhost:27017/funmusic')
var db = mongoose.connection;
db.on('open',function(){
console.log('MongoDB Connect Successed');
});
db.on('error',function(){
console.log('MongoDB Connect Error');
});
//定义card模型
const cardSchema = new mongoose.Schema({
vol_id:String,
vol_number:String,
number:Number,
title:String,
summary:String,
covers:[{
origin:String,
large:String,
large_low:String,
small:String,
}],
create_time:Number,
is_free:Number,
is_trial:Number,
tags:[{
tag_id:String,
name:String,
alias:String,
cover:String,
}],
comments_count:String,
favs_count:Number,
url:String,
detail_desc:String
}, { collection: 'card' });
const cardModel = mongoose.model('card',cardSchema);
//list接口
router.get('/list',function(req,res,next){
var params = URL.parse(req.url,true).query;
var response = res;
cardModel.find({},(err,result,res) => {
if(err) return console.log(err);
console.log(result);
var content = {status:1,data:result};
response.send(JSON.stringify(content));
});
})
//定义cardDetail模型
const cardDetailSchema = new mongoose.Schema({
covers:[{
origin:String,
large:String,
large_low:String,
small:String,
}],
detail_desc:String,
title:String,
number:Number,
tags:[{
tag_id:String,
name:String,
alias:String,
cover:String,
}],
},{collection:'card'});
//detail接口
router.get('/detail',function(req,res,next){
var params = URL.parse(req.url,true).query;
var response = res;
var _vol_id = params.vol_id;
console.log(_vol_id);
cardModel.aggregate([{ $match : { vol_id : _vol_id}},{ $project : {title : 1,covers : 1,detail_desc : 1,number : 1,tags : 1,"_id" : 0}}],(err,result,res) => {
if(err) return console.log(err);
console.log(result);
var restruct = {
image_large:result[0].covers[0].large,
detail_desc:result[0].detail_desc,
title:result[0].title,
number:result[0].number,
tags:result[0].tags,
}
var content = {status:1,data:restruct};
response.send(JSON.stringify(content));
});
});
module.exports = router;
端口管理 - Nginx
Nginx是一个反向代理服务器,平时我们抓包数据从server到client是正向代理,从client到server就是反向代理。服务器的http服务只会向外暴露80端口(默认),https服务暴露443(默认)端口。我们的服务则是3000端口,Nginx会将请求反向代理到3000端口,无论你是http还是hppts请求。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:3000;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
server {
listen 443;
server_name www.lify.online;
ssl on;
root html;
index index.html index.htm;
ssl_certificate cert/214534222920959.pem;
ssl_certificate_key cert/214534222920959.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
#root html;
#index index.html index.htm;
proxy_pass http://127.0.0.1:3000;
}
}
}
进程管理 - PM2
使用它可以很方便的启动、停止和监控进程。刚开始重新发布接口的时候,都需要停止服务,kill进程,再次启动服务,有了pm2只要pm2 restart 进程名
以上是我最近一段时间小程序之旅的总结,希望对你有所帮助。