Git Product home page Git Product logo

Comments (81)

ChaoDIDI avatar ChaoDIDI commented on July 28, 2024 2

文章写的不错.有很多借鉴的地方

from blog.

wuxingfang avatar wuxingfang commented on July 28, 2024 2

好文章

from blog.

webfing avatar webfing commented on July 28, 2024 1

一看就知道是我想要的!希望看到PHP版本的demo哟

from blog.

fouber avatar fouber commented on July 28, 2024 1

@pannysp

把map构建的时候输出成一个后端模板文件,其他文件include它

from blog.

liuyanghejerry avatar liuyanghejerry commented on July 28, 2024

好文。网页确实是需要编译出来的,这是前端工程化的必然结果。

from blog.

robbenmu avatar robbenmu commented on July 28, 2024

niubility

from blog.

oxUnd avatar oxUnd commented on July 28, 2024

👍

from blog.

x404Nan avatar x404Nan commented on July 28, 2024

写得好详细。。

from blog.

lichunqiang avatar lichunqiang commented on July 28, 2024

受教了

from blog.

mgcnrx11 avatar mgcnrx11 commented on July 28, 2024

to 作者:

这些经验很值得介绍出去的呢,为什么没有类似的框架是专门做这类的工作的呢?作者有否考虑这样的框架?

from blog.

oxUnd avatar oxUnd commented on July 28, 2024

可了解下fis
2014年5月14日 上午9:23于 "mgcnrx11" [email protected]写道:

to 作者:

这些经验很值得介绍出去的呢,为什么没有类似的框架是专门做这类的工作的呢?作者有否考虑这样的框架?


Reply to this email directly or view it on GitHubhttps://github.com//issues/3#issuecomment-43032794
.

from blog.

fouber avatar fouber commented on July 28, 2024

@mgcnrx11 fis 就是一个这样专门帮助定制前端解决方案的框架啊。

from blog.

alphatr avatar alphatr commented on July 28, 2024

资源合并那里补充一个详细的方案 静态资源自动合并系统~~

from blog.

sqqihao avatar sqqihao commented on July 28, 2024

niubi

from blog.

fouber avatar fouber commented on July 28, 2024

@webfing

PHP版demo: https://github.com/fouber/static-resource-management-system-demo
上面demo的进化版,加上了前端模块化框架:https://github.com/fouber/fis-php-md.js

from blog.

fiture avatar fiture commented on July 28, 2024

拜读了您的文章,有个小疑问,每个文件改动后生产md5后缀,多次上线后线上会产生:

···
a_xxx1.js
a_xxx2.js
a_xxx3.js
···

也许是我要洁癖,但是这样循环N次后,上线的全量包会越来约大,不知道你们是如何处理这个的。

from blog.

fouber avatar fouber commented on July 28, 2024

@fiture

每次上线,只有修改过的文件才会出现新的md5戳,所以文件冗余没有想象中的那么多,我们做过测试,比较频繁修改的业务模块大概每年会产生100m左右的冗余,我们预计每3年有必要清理一次。

清理的时候,写一个脚本,根据文件名规则找到最后访问的文件然后删除其他的。活着干脆某次上线把发布后的文件之外的其他文件都清理一次,总之这个不成问题。

洁癖问题也没什么,因为文件源码是干干净净的,上线前做一次构建,把东西直接扔到服务器,服务器或许文件会比较多,但没有恶心到工程师。

from blog.

mexiQQ avatar mexiQQ commented on July 28, 2024

学生一枚,看完之后启发太大了,对我来说打开了一个新的世界之门

from blog.

wellstang avatar wellstang commented on July 28, 2024

好文

from blog.

gouchaowen avatar gouchaowen commented on July 28, 2024

棒棒棒

from blog.

pannysp avatar pannysp commented on July 28, 2024

看是看明白了,但是比如:HTML是后端们JAVA写的动态页面,前端们只写JS,css,然后静态资源发布后,生成了新的md5,那么JAVA写的页面里怎么去获取这个新的MD5,以保证加载正确的静态资源。是要在前端静态文件服务器上搞个监控,把新的MD5存某个地方,然后JAVA那边每次请求页面都要获取下新的MD5,替换生成新的链接?

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

java写动态页面不是?不要让他们在java的模板中写这样的代码:

<script src="a.js"></script>

改成写这样的代码:

<fis:require id="a.js"/>

这个 fis:require 的标签,是扩展了jsp的自定义标签。然后,构建工具扫描前端写的js、css,建立一个map资源表,内容大概是:

{
    "a.js" : {
        "url": "/static/js/a_0fa0c3b.js",
        "deps": [ "b.js" ]
    },
    "b.js" : {
        "url": "/static/js/b_4cb04f9.js"
    }
}

然后,我们把这个资源表和java的动态页面放在一起。前面提到的模板中的那个 fis:require 标签,在模板解释执行的时候,会去查这个map表,根据 a.js 这个资源id找到它的带md5戳的url就是“/static/js/a_0fa0c3b.js”,同时还知道这个文件依赖了 b.js 就顺便把b.js的url也收集起来。

最后,在java动态页面生成html之前,把收集到的两个js标签用字符串替换的方式生成script标签插入到页面上,得到:

<script src="/static/js/a_0fa0c3b.js"></script>
<script src="/static/js/b_4cb04f9.js"></script>

我有一个项目展示了这个思路的整个实现过程: https://github.com/fouber/fis-java-jsp

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

这个 资源表(map)fis:require标签是解决这个问题的重点,map是构建工具生成的,通过静态扫描整个前端工程代码得到。map的作用是记录资源的依赖关系和部署路径,然后交给资源管理框架去决定资源加载策略,因此我们最终要把map跟java动态语言部署在一起。

fis:require 是运行在后端动态模板语言中的资源管理框架,它依赖map表的数据信息,你可以把它理解成一个写在模板引擎中的requirejs。设计这个框架的目的是彻底替代<script>标签和<link>标签这种字面量资源定位符,把它们改造成可编程的资源管理框架,在模板渲染的过程中收集页面所用资源,实现去重、依赖管理、资源加载、带md5等等功能

from blog.

pannysp avatar pannysp commented on July 28, 2024

@fouber 嗯,谢谢,有点明白了。还有几点疑问:
1、构建工具扫描前端写的js、css,是根据ID匹配文件名截取文件名上的MD5还是扫描文件内容生成MD5?然后生成MAP。
2、JS源文件是PUSH到server1,然后在server1上fis编译JS,后端代码是放server2,构建工具是往server1上扫描编译好后的js吧,还是源文件?
3、我们后端是groovy语言和grails框架写的页面,fis支持吗?

from blog.

nimoc avatar nimoc commented on July 28, 2024

@pannysp

fis 只生成 资源表 .map 文件作为对后端框架的“接口”,所以任何框架都可以根据 .map 扩展资源定位语法。
读JSON,根据 key 输出 value。

from blog.

pannysp avatar pannysp commented on July 28, 2024

@nimojs
我意思是fis:require标签也可以写在groovy语言和grails框架写的页面里?支持的?

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

每个框架自己实现,算法描述在文章中已经给出了。
在百度的时候,我们曾经在php、nodejs、jsp中分别实现了一套,代码很少的,只是一个查表收集、递归查找的简单算法而已

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

不同的公司、不同的业务可能又会不同的定制,鉴于资源管理框架代码非常少,又通用性非常低,所以fis只给出使用描述和示例,并不给出固定的框架。

比如我在松鼠公司,以移动端为主,设计的资源管理框架又会有一定的改造,前端架构的设计精髓也就体现在这么几行代码上了

from blog.

pannysp avatar pannysp commented on July 28, 2024

@fouber
嗯,等手上空了,再具体调试下,谢谢你的解答

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

1、构建工具扫描前端写的js、css,是根据ID匹配文件名截取文件名上的MD5还是扫描文件内容生成MD5?然后生成MAP。

扫描所有文件,计算文件的摘要,然后生成url。再以文件工程路径为key,建立map表,整个过程不会替换任何文件内容,只是建立表。

2、JS源文件是PUSH到server1,然后在server1上fis编译JS,后端代码是放server2,构建工具是往server1上扫描编译好后的js吧,还是源文件?

都是线下编译。线下设置好js、css要发布的server1的域名、路径,然后release,生成编译后的代码和map,把代码发布到server1上,把map发布到server2上,map中写入的js、css的路径都是符合预期的。构建工具扫描的并不是简单的编译后的结果。我们用工具读取所有文件,然后逐个编译,然后把编译后的结果发布为带md5戳的资源,同时在map中记录的是 源码的文件路径(也就是开发中的工程路径)发布后的资源路径 的映射关系,工程路径 ≠ 部署路径,它们有很大差别。部署路径带md5戳,而且可能变换了发布目录。这样我们采用源码的工程路径作为文件id,在java等动态语言中也可以使用工程路径去加载资源,看起来非常符合人类的直觉。

3、我们后端是groovy语言和grails框架写的页面,fis支持吗?

其他语言可以根据fis的map.json结构,和fis资源管理的**自己实现这个框架,并不复杂

from blog.

pannysp avatar pannysp commented on July 28, 2024

@fouber
非常感谢,非常明白了。

from blog.

pannysp avatar pannysp commented on July 28, 2024

我又来发问题了,呵呵:
前提:后端套静态页面为java动态页面,前端写css,JS。然后java通过获取前端文件发布后生成的map.json(加载http://xxx.com/static/map.json),来更新java页面上静态资源版本号。这个map.json是和前端文件放一起的,是不能发布到后端java项目中的(因为后端代码版本库中是不包含这个map.json的,如果后端有提交新代码,那这个map.json就不存在了,如果版本库里含map.json似乎也不合理吧)。如果前端文件发布地址是:http://xxx.com/static/。 那map.json地址就是http://xxx.com/static/map.json。
那么问题来了:
假设当前线上跑的JAVA页面读取的map.json(生成日期是2015.3.22的)。
然后2015.3.23这天前端修改JS了,后端JAVA页面也修改,2个需要一起上线,才能配合新的更新。
但是按楼主第1楼所说的,MD5戳的版本号,前端先上,后端再上,可以无缝更新。
但像我刚说的这样,前端先上,后端上慢的话,存在1个问题了。前端发布更新后,map.json已经更新了,但后端没上,线上跑的JAVA页面此时去加载的map.json就是新的了(2013.3.23日的),那此时页面的JS映射的就是新的JS了,那旧页面加载了新的JS,那会出错了,因为需要新的JAVA页面才行,这样就实现不了无缝更新了。
当然除非JAVA那边来控制map.json的生成,但这如果只上线前端文件,那我们前端还要跑JAVA那边去说下,给我生成下map.json,那也不合理。

以上不知道我说的清楚不。还是我没有理解java那边怎么来获取map.json更合理,望指教,谢谢。

from blog.

fouber avatar fouber commented on July 28, 2024

@pannysp

这个问题是map.json的升级问题,有两个方案:

  1. 非覆盖式发布map.json,配置fis,让map.json发布的时候带一个构建时间戳,然后把这个时间戳写入到java模板中,先发布map.json,但是线上运行的java页面读取的还是旧的map,然后部署模板,模板中声明了使用新版本的map.json,问题解决
  2. 持久化模板中的map数据。模板引擎一般只有再模板修改后才会重新编译模板,你把读取map的逻辑变成编译后静态写入的结果,下次上线后,先覆盖map.json,这个时候所有模板都还只是使用上一个版本的map数据,然后发布模板,再触发一下模板编译,读入新的map

from blog.

pannysp avatar pannysp commented on July 28, 2024

@fouber
你所说的2种方式,都针对map由部署模板时候触发更新。
1、还有种是只更新前端,不更新后端模板情况下,如何触发map更新。
这种情况,我觉得搞个消息机制,前端更新后,做个开关或命令,通知后端该更新你的map了。
2、前后端都需要更新的情况,那只能map由后端模板这边声明使用新版本的map。
所以看来要满足这2种情况,必须同时要搞这2个方法来升级map,才能保证无缝更新完成。

from blog.

Galen-Yip avatar Galen-Yip commented on July 28, 2024

云龙兄 我有个问题哈 拆分初始化负载的时候,既然dialog已经写在资源表里的,为什么不跟其他的一样,直接利用替换成md5后的文件名就好,还要把资源表的一部分放入页面做这个映射呢

from blog.

fouber avatar fouber commented on July 28, 2024

@Galen-Yip

因为这些资源需要在浏览器运行时,在合适的时机下,由前端异步加载。前端加载需要知道文件的url。

from blog.

Galen-Yip avatar Galen-Yip commented on July 28, 2024

@fouber 不是 我是指一样是放在require.asyn里面 一样是异步加载 但是在编译的时候 直接把md5后的名字替换了dialog.js这名字 浏览器运行时 在需要的时候加载的也还是对应的资源

from blog.

fouber avatar fouber commented on July 28, 2024

@Galen-Yip

那是因为require.async要做两件事,一个是加载资源,一个是加载完成后回调。

加载资源不仅仅是加载资源本身,还要加载依赖的资源,以及依赖的依赖。比如这个dialog.js,并不是独立资源,它可能还会依赖其他文件,假设它依赖了component.js和dialog.css两个资源,component.js又依赖component.css,那么我们得到一颗依赖树:

dialog.js
    ├ dialog.css
    └ component.js
        └ component.css

问题来了,我们怎么告诉require.async,在加载dialog.js的时候,要一并加载其他3个资源呢?我们势必要将依赖关系表放在前端才能实现这个优化,也就有了针对require.async加载的依赖配置项。有这个依赖表,还意味着我们根本没必要把 require.async(id, callback) 接口设计成 require.async(url, callback),因为保留id,在查询依赖关系的时候最方便。

当然,你或许会想到“我们用文件的url建立依赖关系不就行了么?”,这里还涉及到另外一个问题,就是我们加载dialog.js,未必就是加载dialog.js这个文件的独立url,如果它被打包了,我们其实要加载的是它所在资源包的url,比如dialog.js和component.js合并成了aio.js,我们虽然require.async('dialog.js'),但实际上请求的是aio.js这个url。

你或许又想到了“我们用构建工具把require.async的资源路径改成打包后的url地址不就行了?”,恩,这里又涉及到另外一个资源加载问题:动态请求。比如我们需要根据一些运行时的参数来加载模块:

var mod = isIE ? 'fuck.js' : 'nice.js';
require.async(mod, function(m){
     //blablabla
});

前端只有资源表的好处是支持动态加载模块,只要把依赖表输出给前端,就能实现真正的按需加载,这是单纯的静态分析所无法实现的。

此外,require.async还要监听资源加载完毕时间,require.async(id, callback) 这样的设计,可以让define(id, factory)接口被调用的时候,根据id派发模块加载完毕事件,如果把require.async设计成使用url作为参数,那就要改成通过监听script的onload事件来判断资源加载完成与否,这样也麻烦一些。

from blog.

cdll avatar cdll commented on July 28, 2024

学习了~推荐一款基于nodejs的前端工具:coolie

from blog.

javasmile avatar javasmile commented on July 28, 2024

请问,出书吗?求购

from blog.

javasmile avatar javasmile commented on July 28, 2024

请问,出书吗?求购

from blog.

javasmile avatar javasmile commented on July 28, 2024

请问,出书吗?求购

from blog.

sstong123 avatar sstong123 commented on July 28, 2024

好文章!

from blog.

 avatar commented on July 28, 2024

受教

from blog.

CheekyFE avatar CheekyFE commented on July 28, 2024

特别佩服能把一个事物或方向系统地联系实际地总结出来的人,你这个家伙我watch定了!

from blog.

Jihann avatar Jihann commented on July 28, 2024

拜读了

from blog.

koo4 avatar koo4 commented on July 28, 2024

拨开迷雾,豁然开朗的感觉。

from blog.

zack-lin avatar zack-lin commented on July 28, 2024

好吧,一个月的包就超过300M 的我来说,有这么两种场景:

  1. 某几个页面使用了离线缓存,JS 和 CSS 缓存到 localStorage,页面引用的组件其他非离线缓存的页面也在共用,为了保证用户访问离线缓存的页面在加载静态资源的过程中,能够顺利加载到旧的静态资源。
    eng...为啥用户的页面会去加载旧的静态资源?
    因为有这么一种场景,离线缓存的页面在第一次加载中,如果遇到不稳定的网络环境资源加载失败,会导致页面报错,下次进入页面的时候,还是会去加载旧的静态资源。所以,我们不得不保留旧版本代码包一段时间。
  2. 离线缓存的 manifest 文件一般都是程序自己扫描目录维护的,没人会去手动维护吧?!如果是程序自动维护的话,那么增量的更新会导致用户端下载了冗余的代码。

from blog.

acrens avatar acrens commented on July 28, 2024

颇受教育,多谢

from blog.

YuweiYang avatar YuweiYang commented on July 28, 2024

求教 如果使用nodejs当做后端呢?应该怎么写?

from blog.

oxUnd avatar oxUnd commented on July 28, 2024

@YuweiYang 可参考 yog2

from blog.

YuweiYang avatar YuweiYang commented on July 28, 2024

@xiangshouding 谢谢

from blog.

74sharlock avatar 74sharlock commented on July 28, 2024

特别想知道实际开发debug调试的时候和最终打包发布线上这之间是如何区分的

from blog.

fouber avatar fouber commented on July 28, 2024

@74sharlock

这其实是一个构建工具的使用技巧,本地开发和上线部署的构建过程稍微有一些差别而已,上线部署的构建过程需要给资源加上domain。

以fis为例,我们把压缩、资源合并、加md5,加域名等构建操作变成命令行的参数,比如我们本地开发这样的命令:

fis release --dest ../dev

就是构建一下代码,把结果发布到dev目录下,然后我们在dev目录下启动服务器进行本地开发调试,而当我们要提测的时候,并不是用dev目录的东西,而是真的源码又发布一次:

fis release --optimize --hash --pack --dest ../test

这回,我们对代码进行了压缩、加md5、资源合并操作,并发布到了另外一个test目录中,测试是在test目录下进行的。

最终上线,我们也不是使用的test目录下的代码,而是又从源码重新发布一份:

fis release --optimize --hash --pack --domain --dest ../prod

有多了一个 --domain 参数,给资源加上CDN的域名,最终上线用的是prod里的代码。设计原则是始终从源码构建出结果,构建结果可能是开发中的,可能是提测用的,也可能是部署到生产环境的。

作为构建构建,至少要保证针对不同环境的构建代码逻辑是等价的,不能引入额外的不确定因素导致测试和部署结果不一致

from blog.

74sharlock avatar 74sharlock commented on July 28, 2024

@fouber 分三种情况吗?
dev的时候不会对源码以及资源进行整合
test的时候算是模拟线上环境然后进行代码压缩、加md5、资源合并等操作
如果测试无误, 然后就是加上CDN域名去发布上线了
从同一版源码里面执行不同的构建命令, 进行不同的任务
我想我差不多明白了.
相当感谢啊!困惑了很久一下子茅塞顿开!不知道该说什么好, 去放挂鞭炮庆祝一下吧~~

from blog.

74sharlock avatar 74sharlock commented on July 28, 2024

@fouber 感觉必须要尝试下个fis了.

from blog.

fouber avatar fouber commented on July 28, 2024

@74sharlock 用什么工具不重要,选择趁手的就行,思路大同小异

from blog.

yinglau avatar yinglau commented on July 28, 2024

受益良多,呵呵

from blog.

ace-han avatar ace-han commented on July 28, 2024

@fouber 提个问题(可能比较极端),对于目前流行起来的单页面应用(SPA),按需加载应该难度不大了,但是怎么应用上这篇文章中所提到的资源表按md5时间截更新呢?

Render出来的页面上不断请求·map.json·? 按情况刷新对应资源的缓存吗?

from blog.

nimoc avatar nimoc commented on July 28, 2024

@ace-han php java 等后端语言在渲染的时候读取 map.json 即可
或者用构建工具将 html 构建的时候就加入 hash

php 读取map.json

index.php
<script src="<?php _src("static/js/index.js") ?>"></script>
_src 函数

function _src($path) {
    $json = file_get_contents('../output/view/map.json');
    $json = json_decode($json, true);
    if (isset($json['res'][$path]['uri'])) {
        echo $json['res'][$path]['uri'];
    }
    else {
        echo $path .'不存在';
    }
}

map.json

{
    "res" : {
        "static/js/index.js" : {
             "uri": "static/js/index-1688c82.js"
       }
    }
}

实现代码可以参考 https://github.com/nimojs/fis-fms-php

from blog.

ace-han avatar ace-han commented on July 28, 2024

@nimojs 谢谢回答,但是我问的是单页面应用(SPA), 一般在只有render index.html 时跟后端服务器交互一次

<?php require_static('lib1'); ?>
<?php require_static('lib2'); ?>
<?php require_static('lib3'); ?>
...

之后所有请求大部分都是restful ajax call

假设用户在成功加载后不再刷新html页面,或者是hybrid app, 那怎么通知页面用更新的不同时间截的js+css

from blog.

atian25 avatar atian25 commented on July 28, 2024

@ace-han 这里涉及到一个问题:

你们用户停留的时间是多久? 你们升级后需要用户第一时间访问到新页面的时间差是多少?

如果要求不高, 那就用户下次进来再更新就好咯, 无需做什么通知.
另外, 需要让用户访问新页面的时候, 一般是强刷下页面就好了, 不会在原来的页面里面加载新资源的.

可以看下 scrat webapp 模式, 资源依赖表是输出到HTML中的. http://scrat.io/#!/index

@fouber 上面的代码示例, 是后端渲染模式的, 对应于 scrat pagelet 模式. 你SPA的话更适用于 scrat webapp

from blog.

nimoc avatar nimoc commented on July 28, 2024

@ace-han
静态资源表可以存成 map.json 供后端读,也可以以对象的形式嵌入在js里面,或者直接嵌入在 html <script></script>


一般静态资源表是构建工具构建时候扫描所有文件生成的,即静态资源表发布后是不变的。所以也没加载成功后嵌入到 js 或html 中供js读取即可。


你的SPA场景是 ajax call 后的页面也是异步请求页面对应js,然后由这个请求的js渲染?

from blog.

nimoc avatar nimoc commented on July 28, 2024

以前我用 fis 简单封装过 静态资源表。页面js分别有

loader.js
config.js
page.js

loader 是模块加载器
config 是用fis 封装过的的静态资源表
page.js 的内容是

require('view/detailrender.js')

require 或读取 config.js 中的表,然后读取到 view/detailrender.js 对应的文件是 /view/detailrender-2hsf2f.js ,然后用 loader 加载这个文件

from blog.

cosmosdawn avatar cosmosdawn commented on July 28, 2024

6

from blog.

shinyruo-nmsl avatar shinyruo-nmsl commented on July 28, 2024

现在是2023年了,想请教一下,文中所述的这些工程化的经验还适用于当前的前端构建吗?

from blog.

7greenfrog7 avatar 7greenfrog7 commented on July 28, 2024

from blog.

zhouqimark avatar zhouqimark commented on July 28, 2024

from blog.

liucan233 avatar liucan233 commented on July 28, 2024

from blog.

ccfung avatar ccfung commented on July 28, 2024

from blog.

nice2meu avatar nice2meu commented on July 28, 2024

from blog.

staxing avatar staxing commented on July 28, 2024

from blog.

FairyYang avatar FairyYang commented on July 28, 2024

from blog.

imondo avatar imondo commented on July 28, 2024

from blog.

JeffCP9527 avatar JeffCP9527 commented on July 28, 2024

from blog.

tachibanakaori avatar tachibanakaori commented on July 28, 2024

from blog.

liyueS777 avatar liyueS777 commented on July 28, 2024

from blog.

veraLX avatar veraLX commented on July 28, 2024

from blog.

qzoushi avatar qzoushi commented on July 28, 2024

from blog.

rookie233333 avatar rookie233333 commented on July 28, 2024

from blog.

heihuahe avatar heihuahe commented on July 28, 2024

from blog.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.