各位云原生搬砖师 and PPT 架构师,你们有没有想过像写文章一样方便地写代码呢?
怎样才能像写文章一样写代码? 理想的需求应该是可以在线编写、调试函数,不用重启服务,随时随地在 Web 上查看函数的运行日志,无需连接服务器,无需折腾数据库、对象存储、Nginx 等,可以随时随地上线应用,招之即来,挥之即去,随手发布!
这时候懂王上线了,好家伙,这不就是 Serverless 嘛,Serverless 的愿景是用户只需专注开发意图,编写函数代码,并上传到代码仓库,其他的东西不需要关心,Serverless 平台会自动分配计算资源,并按需运行函数。
你懂的真多,可惜啊,仅有 Serverless 还满足不了上述需求。
要想像写文章一样写代码,除了需要 Serverless 来提供函数计算服务之外,还需要以下几个必备条件:
懂王又上线了,这个我也懂,腾讯云开发、Google Firebase 以及 UniCloud 就提供这样的功能。
如果我告诉你现在有一个平台已经俱备了上述的所有条件,而且完全开源,每个开发团队都可以随时拥有一个自己的云开发平台,你会不会内心狂喜?
是的,这个平台就是 Laf。

人生苦短,前端用 Laf,后端用 Laf,云开发用户用 Laf,独立开发者用 Laf,初创团队用 Laf,我也用 Laf。上链接?:
值得一提的是,Laf 在上周五一天内 Star 数量增长了近 300 个,并且后续连续几天的 Star 数量呈垂直上升,简直就是简直了。

Laf 本质上是一个集「函数计算」、「数据库」、「对象存储」等于一身的一站式开发平台,可以快速的开发并发布应用。它包含了以下几个功能:
云函数是运行在云端的 JavaScript 代码,熟悉 Node.js 的开发者可以直接上手。
云函数也可以使用 Typescript 编写,无需管理服务器,在开发控制台在线编写、在线调试、一键保存即可运行后端代码。
在你的应用中,大多数数据的获取都可在客户端直接操作数据库,但是通常业务中会使用到「非数据库操作」,如注册、登录、文件操作、事务、第三方接口等,可直接使用云函数实现。
详情请查看云函数的文档。

前端可使用 laf-client-sdk “直连”云数据库,无需与服务端对接口。
通过在开发控制台,配置相应的访问策略,也可以实现客户端安全操作数据库。
详情请查看云数据库的文档。

laf 云存储是基础 MinIO 提供的对象存储服务,laf 提供了完全兼容 MinIO (aws s3-api) 的对象存储服务, 在 laf oss 文档上线之前,开发者完全可参考 MinIO 的文档来使用 laf oss。

laf 支持静态网站的托管,可以快速的上线静态网站,无需折腾 Nginx。
前端开发者 + laf = 全栈开发者,前端秒变全栈,成为真正的大前端。
laf 为前端提供了 laf-client-sdk,适用于任何 js 运行环境;laf 云函数使用 js/ts 开发,前后端代码无隔裂,无门槛快速上手;laf 提供了静态网站托管,可将前端构建的网页直接同步部署上来,无需再配置服务器、Nginx、域名等;laf 后续会提供多种客户端的 SDK(Flutter/Android/iOS 等),为所有客户端开发者提供后端开发服务和一致的开发体验。后端开发者,可以从琐事中解放出来,专注于业务本身,提升开发效率。
laf 可以节约服务器运维、多环境部署和管理精力;laf 可以让你告别配置、调试 Nginx;laf 可以让你告别「为每个项目手动部署数据库、安全顾虑等重复性工作」;laf 可以让你告别「修改一次、发布半天」的重复繁琐的迭代体验;laf 可以让你随时随地在 Web 上查看函数的运行日志,不必再连接服务器,费神费眼翻找;laf 可以让你「像写博客一样写一个函数」,招之即来,挥之即去,随手发布!云开发用户,若你是微信云开发用户,你不仅可以获得更强大、快速的开发体验,还不被微信云开发平台锁定。
laf + 你的云开发应用,而使用闭源的云开发服务,无法交付可独立运行的源码;laf 是开源免费的;laf 是开源的、高度可扩展的。Node.js 开发者,laf 是使用 Node.js 开发的,你可以把 laf 当成一个更方便的 Node.js 开发平台 or 框架。
独立开发者、初创创业团队, 节约成本,快速开始,专注业务。
laf = 团队。
laf是应用的后端开发平台,理论上可以做任何应用!
使用 laf 快速开发微信小程序 / 公众号: 电商、社交、工具、教育、金融、游戏、短视频、社区、企业等应用!
laf 静态托管;laf 上,将分配的专用域名配置到公众号即可在线访问;开发 Android or iOS 应用。
laf 静态托管;部署个人博客、企业官网。
laf 静态托管上, 见 laf-cli企业信息化建设:企业私有部署一套 laf 云开发平台
laf 社区生态,直接使用现存的 laf 应用,开箱即用,降成本laf 开源免费,没有技术锁定的顾虑,可自由订制和使用个人开发者的「手边云」
laf 让开发者随手写的一段代码,瞬间具备随手上云的能力laf 是每个开发者的“烂笔头”,像记事一样写个函数laf 是每个开发者的“私人助理”,比如随时可以写一个定时发送短信、邮件通知的函数其它
laf 云存储当网盘使用laf 应用当成一个日志服务器,收集客户端日志数据,使用云函数做分析统计laf 来跑爬虫,抓取三方新闻和咨讯等内容laf 云函数做 webhook,监听 Git 仓库提交消息,推送到钉钉、企业微信群laf 云函数做拨测,定时检查线上服务的健康状态未来,
lafyun.com会上线一个应用市场,汇总收集这些应用,让laf用户一键即可使用海量应用 !
下面我们将在 lafyun.com 上,通过开发一个简单的「用户登录/注册」的功能,快速体验 laf 云开发。
新建 按钮,创建一个空应用;laf 应用的功能开发。本示例会编写两个云函数:register 处理注册请求,login 处理登录请求。
在「云函数」管理页面,点击 「新建函数」,创建注册云函数 register。然后点击 register 函数右侧的 「开发」按钮,进入 WebIDE,编写以下代码:
import cloud from '@/cloud-sdk'
import { createHash } from 'crypto'
exports.main = async function (ctx: FunctionContext) {
const username = ctx.body?.username || ''
const password = ctx.body?.password || ''
// check param
if (!/[a-zA-Z0-9]{3,16}/.test(username)) return { error: 'invalid username' }
if (!/[a-zA-Z0-9]{3,16}/.test(password)) return { error: 'invalid password' }
// check username existed
const db = cloud.database()
const exists = await db.collection('users')
.where({ username: username })
.count()
if(exists.total > 0) return { error: 'username already existed'}
// add user
const { id } = await db.collection('users')
.add({
username: username,
password: createHash('sha256').update(password).digest('hex'),
created_at: new Date()
})
console.log('user registered: ', id)
return { data: id }
}
点击右上角的 「显示调试面板」(Ctrl/Cmd + B) 即可调试运行。

点击 「保存」 & 「发布」 函数即发布上线!
同上,创建 login 云函数,编写以下代码:
import cloud from '@/cloud-sdk'
import { createHash } from 'crypto'
exports.main = async function (ctx: FunctionContext) {
const username = ctx.body?.username || ''
const password = ctx.body?.password || ''
// check user login
const db = cloud.database()
const res = await db.collection('users')
.where({
username: username,
password: createHash('sha256').update(password).digest('hex')
})
.getOne()
if (!res.data)
return { error: 'invalid username or password' }
// generate jwt token
const user_id = res.data._id
const payload = {
uid: user_id,
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7
}
const access_token = cloud.getToken(payload)
return {
uid: res.data._id,
access_token: access_token
}
}
点击右上角的 「显示调试面板」(Ctrl/Cmd + B) 即可调试运行。

点击 「保存」 & 「发布」 函数即发布上线!
最后可以通过云函数列表页面,查看 & 复制云函数的调用地址, 或将以下 curl 命令中的 APPID 替换成你的 APPID 后执行:
# 注册用户
$ curl -X POST -H "Content-Type: application/json" -d '{"username": "admin", "password": "admin"}' https://APPID.lafyun.com/register
# 用户登陆
$ curl -X POST -H "Content-Type: application/json" -d '{"username": "admin", "password": "admin"}' https://APPID.lafyun.com/login
APPID 可以在 lafyun.com 的欢迎页面找到。

在你的前端项目中安装 laf client sdk:
$ npm install laf-client-sdk
最后,可以在你的 Vue/React/Angular/小程序 页面中调用这两个云函数完成具体的登录注册功能!例如:
// user.ts
import { Cloud } from 'laf-client-sdk'
const cloud = new Cloud({
baseUrl: "https://APPID.lafyun.com",
getAccessToken: () => localStorage.getItem('access_token')
})
// regiser function
export async function register(username: string, password: string) {
const res = await cloud.invoke('register', {
username: username,
password: password
})
return res
}
// login function
export async function login(username: string, password: string) {
const res = await cloud.invoke('login', {
username: username,
password: password
})
if(res.access_token) {
// save token
localStorage.setItem('access_token', res.access_token)
}
return res
}
运维同学与后端同学请注意,由于 Laf 过于强悍,你们不再需要折腾基础架构和后端服务,很可能会因为工作量不饱和而面临被裁的风险!注意控制风险!
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain