Skip to content

kevindu1993/jdists

This branch is 114 commits behind zswang/jdists:master.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

9ec9ece · Dec 26, 2014

History

58 Commits
Dec 24, 2014
Dec 24, 2014
Dec 24, 2014
Dec 26, 2014
Dec 26, 2014
Oct 15, 2014
Dec 23, 2014
Oct 28, 2014
Oct 16, 2014
Dec 26, 2014
Dec 26, 2014

Repository files navigation

jdists(<>) 前端代码块预处理工具

Build Status NPM version

什么是 jdists

项目地址:https://github.com/zswang/jdists

关于命名

j dist s 就是 js 里插入了一个 dist (分发),避免和其他组件命名冲突,同时特殊好记。 本工具专注于前端代码块(js、css、html)预处理。

起因

一个页面从开发到上线基本会经历三个阶段:

  • 本机开发调试

    • 打印一些变量和执行状态、模拟数据接口
  • 内网测试

    • 跳过某些步骤、使用内网环境
  • 公网上线

    • 移除调试代码、使用线上环境。

其实前端代码和其他语言代码都需要编译,目前已经有很多成熟的工具来完成编译的事情。 比如:fis、grunt、gulp,基本都是依赖配置文件,将项目代码进行编译到相应版本。

问题

  • 代码和配置文件是分离的,这样开发维护起来不够直观。
  • 配置文件通常是基于 JSON,还是不够直观。
  • 调试代码容易遗忘,有导致线上事故的风险。

思考

那有没有一种方法能将部分编译逻辑写在代码中,就像 C 语言预编译宏定义,代码本身就包含了编译逻辑不依赖配置文件就能执行:

#include "headfile"
#ifdef DEBUG
fprintf("variant=%d", variant);
#endif

这样不仅利于维护也方便在本机开发时调试,那么接下来需求来了!

需求

  • 学习成本要很低。(使用 html 标记,这个大家再熟悉不过)
  • 支持 html、css、js 文件格式。
  • 本机开发调试时不依赖编译器。(编译逻辑写在注释中)
  • 不仅能 include 一个文件,还能 include 一个文件中的片段(代码块)。
  • 能引入当前文件的代码块。
  • 能够替换代码块的内容。
  • 能 include 二进制文件,变为 base64 字符串,方便转成 dataUri。
  • 自动合并 css 或 js 文件,能够输出合并文件并能打 md5 戳。
  • 能够处理一些 黑魔法,避免被压缩工具影响

比如:注释模板

var render = jhtmls.render( /*#*/ function () {
/*!
<div title="#{title}">#{content}</div>
*/});

jdists 处理后 --->

var render = jhtmls.render('<div title="#{title}">#{content}</div>');

比如:参数自识别

instance.get( /*,*/ function(a, b, c) {
	// TODO
});

jdists 处理后 --->

instance.get(['a', 'b', 'c'], function(a, b, c) {
	// TODO
});
  • 能够扩展替换规则。

设计思路

解决好如何定义代码块,其他问题基本就迎刃而解了。

用什么方式来定义代码块?

利用注释 + html 标记,并且又能和普通注释区分。

  • 在 html 中:
<!--debug-->
<div>测试版本</div>
<!--/debug-->
  • 在 js 中:
/*<debug>*/
console.log('测试版本');
/*</debug>*/
  • 在 css 中:
.version {
	font-size: 12px;
/*<debug>*/
	color: red;
/*</debug>*/
}

一些代码未必默认启用,所以支持如下方式

  • 在 html 中:
<!--release>
<div>线上版本</div>
</release-->
  • 在 js 中:
/*<release>
console.log('测试版本');
</release>*/
  • 在 css 中:
.version {
	font-size: 12px;
/*<release>
	color: red;
</release>*/
}

废弃的方式

<!--debug begin-->
<div>测试版本</div>
<!--debug end-->

<!--start debug-->
<div>测试版本</div>
<!--end debug-->
  • 使用 begin | start / end 的方式,容易遗忘:前缀还是后缀、begin 还是 start
/*<release
	color: red;
/release>*/
  • 不能处理单行

模块定义完整示例

<!--include file="base.html" block="b1"-->
<!--include file="base.html" block="b1" /-->
<!--debug file="base.html" block="b1" --><em>debug</em><!--/debug-->
<!--debug file="base.html" block="b1"><em>debug</em></debug-->
/*<include file="base.html" block="b1" >*/
/*<include file="base.html" block="b1" />*/
/*<debug file="base.html" block="b1">*/<em>debug</em>/*</debug>*/
/*<debug file="base.html" block="b1"><em>debug</em></debug>*/

基本概念

名称 含义 例子 备注
file 文件 1.js,1.png 包括二进制文件
block 代码块 只能是文本文件
block::tag 标签 <a>
block::attribute 代码块属性 <a encoding="md5">
encoding 编码器 将代码块进行编码处理

标准代码块

tag 功能 示例
include 引入文件或代码块 <!--include file="all.js" /-->
replace 将当前代码块替换成文件或代码块
remove 将当前代码移除

代码属性(attribute)

属性名 含义 例子 备注
encoding 编码 encoding="base64" 默认"original",可扩展
slice 裁剪 slice="1,-1" 参考 String.slice() 函数
file 文件名 file="all.js" 默认当前文件
export 导出文件 export="output.js" 如何为 '#' 或 ':' 开头则输出到内存中
block 代码名 block="hello" 引入的块名
type 类型 type="comment" 默认"original","comment":去掉包裹代码块的注释
trigger 触发器 trigger="release,LAN" 默认"release",存在这些触发器时才生效
js js 文件 js="all_{{md5,7}}.js" 输出的 js 文件名
css css 文件 css="all_{{md5,7}}.css" 输出的 css 文件名

{{md5,len}} 计算内容的 md5 值,len 指定长度

编码(encoding)

  • original:原文【默认】
  • string:作为字符串
  • base64:base64 输出
  • md5:内容 MD5 戳(小写)
  • concat:合并本地 js 或 css 并可以知道输出
  • inline:内链文件
  • relative:静态资源相对路径
  • require:AMD 自动依赖处理
  • template:模板
  • zero:零宽字符加密

可以通过 jdists.setEncoding(encoding, processor) 扩展

使用限制

  • 代码块不能交叉,可以嵌套
  • 代码块引用不能出现循环

实战

开始使用

  • 依赖 npm 环境

  • 安装 $ npm install jdists -g

  • 命令格式 $ jdists input1 [input2] [-output output] [-remove debug,test] [-tigger release]

  • 命令参数

参数 简写 功能 备注
-output -o 指定输出文件 默认输出到控制台
-remove -r 指定移除的代码块 默认 "debug,test"
-trigger -t 指定触发器 默认 "release"
-clean -c 清除空白行 默认 true
-version -v 打印当前版本

处理 js 中的 注释模板

假设文件 js/base.js 内容为:

var render = jhtmls.render(function() {/*!
<ul>
forEach(function(item) {
	<li>#{item.title}</li>
});
<ul>
*/});

如上可以省去拼接字符串的工作,直观好维护。但经过带压缩后就变成:

var render=jhtmls.render( /*#*/ function(){});

怎么避免 注释模板 被压缩代码的工具移除?

$jdists js/base.js -o dist/js/base.js

生成的文件是:

var render = jhtmls.render('<ul>\nforEach(function(item) {\n  <li>#{item.title}</li>\n});\n<ul>');

jdists 默认会处理 注释模板

处理 js 中的 参数名自识别

假设文件 js/base.js 内容为:

instance.get( /*,*/ function(name, x, y, width, height) { ... });

我们可以通过函数声明中的参数列表判断需要获取的值,但是参数经过压缩后名字就变了,如:

instance.get(function(a,b,c,d){ ... });

jdists 同样可以帮我们处理

$jdists js/base.js -o dist/js/base.js

生成的文件是:

instance.get(['name','x','y','width','height'],function(a,b,c,d){ ... });

发布代码

假设文件 js/net.js 内容为:

var ajax = ajax || {};
void function(exports) {
/*<replace>
	exports.host = 'http://api.baidu.com/1.0/getuser';
</replace>*/
}(ajax);

$jdists js/net.js -o dist/js/net.js

生成的文件是:

var ajax = ajax || {};
void function(exports) {
	exports.host = 'http://api.baidu.com/1.0/getuser';
}(ajax);

还有一种情况,是我们需要先编译一个局域网版本

假设文件 js/net.js 内容为:

var ajax = ajax || {};
void function(exports) {
/*<replace trigger="release">
	exports.host = 'http://api.baidu.com/1.0/getuser';
</replace>*/
/*<replace trigger="LAN">
	exports.host = 'http://http://192.168.1.67:8000/1.0/getuser';
</replace>*/
}(ajax);

$jdists js/net.js -o dist/js/net.js -t LAN

生成的文件是:

var ajax = ajax || {};
void function(exports) {
/*<replace trigger="release">
	exports.host = 'http://api.baidu.com/1.0/getuser';
</replace>*/
	exports.host = 'http://192.168.1.67:8000/1.0/getuser';
}(ajax);

指定 trigger 的代码块,会检查是否命中配置的触发器,如果没有命中则不启用功能。

合并静态资源

还是依所见即所得的设计思路,开发期的 html 指明了依赖的静态文件,如:

index.html

<html>
<head>
	<!--replace encoding="concat" js="dist/all.js" css="dist/all.css"-->
	<link rel="stylesheet" type="text/css" href="base.css">
	<link rel="stylesheet" type="text/css" href="button.css">
	<script src="base.js"></script>
	<script src="replace.js"></script>
	<!--/replace-->
</head>
<body>...</body>
</html>

$jdists index.html -o dist/index.html

生成的文件是:

<html>
<head>
	<script src="all.js"></script>
	<link rel="stylesheet" type="text/css" href="all.css">
</head>
<body>...</body>
</html>

同时将本地静态资源分别合并到 dist/all.jsdist/all.css

打包组件

通过 jdists 可以将零散的代码和静态资源,拼凑为一个完整的组件

void function() {
	var bar = document.getElementById('jfpss-bar');
	if (bar) {
		return;
	}

	/*<include components/jframes/src/jframes.js>*/
	;
	/*<include components/jhtmls/src/jhtmls.js>*/
	;
	/*<include src/jfpss.js>*/

	createStyle(function() {/*!<!--include src/tools.html style-->*/});

	var div = document.createElement('div');
	div.innerHTML = function() {/*!<!--include src/tools.html html-->*/};
	document.body.appendChild(div);

	/*<include src/tools.html js>*/
}();

这样就可以用静态页面开发 UI 组件了。

参考实例:https://github.com/zswang/jfpss/blob/master/src/tools.jdists

后续

  • 加入自动内联代码。
  • 提供 fis、grunt、gulp 插件。

项目地址:https://github.com/zswang/jdists

About

前端代码块预处理工具

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%