clam
v1.0.12
Published
A full Web front end develop envirment.
Downloads
85
Readme
Clam
是什么
Clam
是一套基于 Node.js 的前端工程项目开发环境(支持HTTP和HTTPS)。
Clam
内部集成了本地开发服务器、前端模块化开发管理等功能。Clam
志在为前端工程师提供更简单和一致的项目开发体验。
Clam
的安装
安装Clam
最简单的方式是通过 Node.js 提供的包管理工具npm
来安装:
npm -g install clam
# Mac 和 Linux 环境下可能需要 sudo 权限
# 注意:Windows 平台下请使用原生命令行环境,不要在 Cygwin 下安装。
开始使用 Clam
Clam
的使用非常简单,首先需要新建一个空的项目目录,例如hello_clam
:
mkdir hello_clam
cd hello_clam
然后在此目录下执行Clam
的项目初始化命令:
clam init
这条命令会在项目目录下生成一套标准的Clam
项目目录结构:
hello_clam
- build
- src
- pages
- mods
- widgets
- tests
- .clam
- project.json
# src: 项目源文件目录,包括 html 模板、样式、脚本、图片资源等;
# tests: 项目测试脚本;
# build: 项目打包发布上线的目标文件;
# .clam: 项目元信息,project.json 为项目配置文件。
其中在项目开发阶段核心工作目录是src
。其目录结构对应了Clam
提供的一套标准的前端模块化开发架构(基于Page,Module,Widget的分层模块开发,具体参考Clam
模块化开发章节)。
对于一个简单的项目,只需将所有文件都丢到pages
目录,并以相对路径在html
文件里引入所需样式和脚本即可,只需要一个简单的配置项cdnPath
:
# 在项目配置文件 .clam/project.json 里修改 cdnPath
"cdnPath": "http://yourcdn.com/yourproject"
# >> 这样项目打包时就会将相对路径替换为指定的`cdnPath`
# 注意:结尾不要附加斜杠
至此使用Clam
就完成了一个最基本的前端项目的开发。
关于Clam
提供的更多功能:
- 本地资源文件代理(支持
combo
功能) - 接口模拟
- 模块化开发管理
- 打包和发布管理
- 项目 Hosts 管理
- 基于模板创建页面和模块
强烈推荐继续阅读。
Clam
本地文件代理
Clam
本地文件代理提供了一个方便调试测试或线上问题的机制。其工作原理很简单,当你需要调试一个测试或线上页面如hello_clam.html
时,首先找到该页面所属的项目hello_clam
。确保已经配置了项目的cdnPath
,并将文件服务器域名指向本机:
# 在 hosts 文件中将文件服务器指向本机
127.0.0.1 yourcdn.com
然后开启或切换到此项目的 Clam 环境:
cd hello_clam
clam on
注: Mac、Linux下需加sudo
此时再访问 hello_clam.html
页面时,Clam
内置的本地服务器会将此文件所引用的样式和脚本资源替换为该项目目录的源文件。
Tips~ 对于手机端检测FPS,手势和console.log的处理可以用 clam on wap
进行注入。并在电脑端打开http://clam.com进行查看数据
值得一提的是Clam
的文件代理功能提供了combo
支持,其中默认支持的combo
格式以?
作为servlet
,以,
作为文件分隔符。如果需要定制combo
,可以到用户根目录的~/.flex-combo/config.json
配置文件里更改flex-combo
的配置。
flex-combo
是一个提供本地combo
服务的Node.js
模块。Clam
本身的combo
功能也是基于此模块实现的。
关于flex-combo
的详细信息参见 flex-combo官方文档。
Clam
接口模拟
依托于Node.js
,Clam
提供了方便且强大的接口模拟能力。
- 通过
dataApi
方式进行本地自动代理。模拟接口。enabled参数分别为auto
local
remote
- 若设置为
auto
则为自动查找模式。优先本地查找。本地文件对应目录为${root}/.clam/dataApi
- dataApi如果
exports.handle
存在,并且是一个函数。则认定用户需要自助解决数据返回情况。其它认为反回数据为json
- 参数
remote
由以往的域名模式改为完整地址模式。 匹配正则为
// 'https://www.taobao.com:80/a/d/b?a=1&b=2'.match(/^(?:(http(?:s*)|socket):\/\/)*([^\:\/]+)*(?:\:(\d+))*(\/[^?]*)(?:\?(.*))*$/)
// ["https://www.taobao.com:80/a/d/b?a=1&b=2", "https", "www.taobao.com", "80", "/a/d/b", "a=1&b=2"]
// 'socket://www.taobao.com:80/a/d/b?a=1&b=2'.match(/^(?:(http(?:s*)|socket):\/\/)*([^\:\/]+)*(?:\:(\d+))*(\/[^?]*)(?:\?(.*))*$/)
// ["socket://www.taobao.com:80/a/d/b?a=1&b=2", "socket", "www.taobao.com", "80", "/a/d/b", "a=1&b=2"]
// 'socket://www.taobao.com:80/a/d/b?a=1&b=2'.match(/^(?:(http(?:s*)|socket):\/\/)*([^\:\/]+)*(?:\:(\d+))*(\/[^?]*)(?:\?(.*))*$/)
目前仅支持
http
,https
和socket
等待完善中。
"dataApi" : [
{
"url": "/api/fake_api", // 需要模拟的接口路径
"enabled": "local", // 转发到远程服务器或者本地处理
"remote": "http://remotehost.com:9023/s/a?a=1&b=2", // 远程服务器
"local": "local_a.js" // 本地处理脚本
},
{
"url": "/api/", // 需要模拟的接口路径
"enabled": "remote", // 转发到远程服务器或者本地处理
"remote": "remotehost.com", // 远程服务器
"local": "local_b.js" // 本地处理脚本
}
]
其中url
是需要匹配的接口路径(最长路径匹配);enabled
用来控制接口本地处理还是做远程转发;remote
和local
字段分别指定了远程转发服务器地址和本地处理脚本的文件名。本地处理脚本需要放置在项目的.clam/json/
目录下。
假如此时项目请求/api/fake_api
接口,Clam
将调用.clam/json/local_a.js
处理;若请求/api/another_fake_api
则Clam
会将此请求转发到远程服务器remotehost.com
上。
本地处理脚本使用Node.js
内置的http
模块来实现,它提供了一个接收http request
和http response
对象参数的处理函数:
exports = module.exports = function(req, res){
res.end('this is a fake api response~')
return true
}
关于此函数的详细用法请参考Node.js
官方文档的http
模块部分。
Clam
代理配置
在.clam
目录下的 project.json
中增加了一个 proxy
的配置项。关于此配置项的详细说明请参考:Doji配置
Clam
模块化开发
除了一系列的贴心功能外,Clam
还非常激进的提供了从底层架构层面对于前端模块化开发的支持。先来了解一下Clam
对于前端项目的理解。
传统上前端工作里“项目”的概念远没有后台软件开发领域里那么清晰,这主要是由于以往的客户端页面较简单,不需要太多“项目”层面的支持。随着现在客户端功能的越趋复杂,有必要系统的来引入一套针对前端业务特点构建的架构模式。
Clam
里对于项目的定义是一个完整的前端应用,或其中一个相对独立的某一个业务场景。如:一个单页富应用,可以作为一个Clam
项目;或者业务耦合度较高,用户使用路径很近的一组页面,也可以作为一个Clam
项目。
对于一个Clam
项目的具体页面,除了页面自身的html
模板,样式和脚本外,它还可以引用一组模块,其中每个模块都有其独立的html
模板,样式和脚本文件。同时页面上还可以存在一些通用的组件,如下图所示:
- 一个
Clam
项目由若干页面Page
、模块Module
、和组件Widget
构成; - 其中
Page
和Module
可以由html
,css
,js
等组成;Widget
则不应包含html
; Page
可以在其html
里包含Module
的html
文件来使用模块;通过静态包含或动态加载使用Widget
;Module
通常是与业务关系较密切的独立功能块,比如一个订票网站的常用联系人模块;Module
应做到尽可能独立,最理想的情况是完全独立于页面;Widget
是与具体业务耦合较松,复用性更强的功能块,如日历组件;Page
的html
部分通常是用来包含模块html
或为组件提供容器的。
要使用一个模块很简单,只需在页面html
里引用模块html
即可,拿我们的hello_clam
项目做例子,我们目前的项目目录结构为:
hello_clam
- build
- src
- pages
- home.html
- home.css
- home.js
- mods
- say_hello
- say_hello.html
- say_hello.css
_ say_hello.js
- contact
- contact.html
- contact.css
- contact.js
- widgets
- tests
- .clam
- project.json
其中home.html
内容为:
<html>
<head>
<title>hello clam</title>
<link rel="stylesheet" href="home.css" />
<script type="text/javascript" src="home.js"></script>
</head>
<body>
<h1>hello clam!</h1>
<!--#include file="/mods/say_hello/say_hello.html"-->
</body>
</html>
say_hello.html
内容为:
<link rel="stylesheet" href="say_hello.css" />
<script type="text/javascript" src="say_hello.js"></script>
<p>Hello! Dear Clam User!</p>
现在启动Clam
后就可以在浏览器里输入127.0.0.1/home.html
,可以看到home.html
页面为嵌入了say_hello.html
的内容:
<html>
<head>
<title>hello clam</title>
<link rel="stylesheet" href="home.css" />
<script type="text/javascript" src="home.js"></script>
</head>
<body>
<h1>hello clam!</h1>
<link rel="stylesheet" href="say_hello.css" />
<script type="text/javascript" src="say_hello.js"></script>
<p>Hello! Dear Clam User!</p>
</body>
</html>
clam
动态内容生成
你可以在页面和模块中使用Juicer语法,避免大量重复代码出现。
可以使用#def
语法定义一个变量。在def后面的JSON格式数据(格式请严格按照JSON格式编写)。
<!--#def {"a":[1,2,3],"b":{data:[1,2,3]} -->
默认情况下创建的数据的作用域只限定与本模板执行环境中。只要你愿意你可以把数据通过以下语法传递给子模板,引入子模板有两种语法格式(完整/简易)。
写法:
<!--#include data='{"b":${b}}' file="/mods/mod.html"-->
数据源的写法也分为两种:
- 如上例展示的,直接写在#def中定义的JSON数据的key,该写法需要注意的是,传递给子模块的数据的类型必须为Object
- 在数据源位置以key / value的形式重新定义,使用$符表示引用#def中定义的JSON数据,无$则以普通字符串的形式传入子模块,该写法对数据类型无要求
例子
template.html
<!--#def {"data":[1,2,3],"data2":{"data":[1,2,3]}} -->
{@each data as item,index}
<div>data:${item},index:${index}</div>
{@/each}
<!--#include "sub-template.html" "data2"-->
sub-template.html
<h2>this is sub template</h2>
{@each data as item,index}
<div>data:${item},index:${index}</div>
{@/each}
output
<div>data:1,index:0</div>
<div>data:2,index:1</div>
<div>data:3,index:2</div>
<h2>this is sub template</h2>
<div>data:1,index:0</div>
<div>data:2,index:1</div>
<div>data:3,index:2</div>
clam
引用远程HTML代码
写法:
<!--#remote url="http://foo.com/path/to/bar.html"-->
clam
特殊标签属性
fe-move
该属性用于外联js的script标签中,以提示clam解析时,将该外联js文件引入放于页面的何处。共有2种属性值:top | bottom
写法:
<script type="text/javascript" src="xxx.js" fe-move="top|bottom"></script>
属性值解释:
top:放于<head></head>的头部
bottom:放于</body>之前
fe-group
对assets进行combo
写法:
<script type="text/javascript" src="xxx.js" fe-group="cc"></script>
<script type="text/javascript" src="yyy.js" fe-group="cc"></script>
=>
<script type="text/javascript" src="~/??xxx.js,yyy.js"></script>