mya-golang-template
v1.0.5
Published
Plugin for golang html/template template
Downloads
12
Readme
mya-golang-template
基于 mya 的针对 go html/template 模板的前端工程解决方案
背景
利用后端模板的能力实现后端模块化(组件化)和静态资源按需加载
方案构成
- html/template 扩展,负责解析自定义标签,并根据静态资源映射表渲染最终页面
mya-golang-template
(mya插件),输出静态资源映射表,编译打包相关配置,路径修正等- 其他:脚手架
预备工作
在阅读以下内容之前,建议可以先安装一下mya,然后利用脚手架初始化一个项目,对着项目看,会更容易理解以下内容。
npm install -g mya
mya init go your_project_name
原生标签
template
page/home/index.html
{{ template "component/common/button/index.html" . }} <!-- . 符号表示将当前上下文变量传递给模板 -->
go html/template 自带的标签,类似 jinja2/django 中的 include
。在项目中可以通过此标签引用一个组件。
在构建过程中,我们会为每个模板自动插入 require
标签(见自定义标签),这样仅需要使用 template 引用模板文件,其同目录下同名的 css 和 js 就会被当作依赖收集并自动插入到页面。
比如:
component/common/button/index.html
<div>button</div>
output/template/component/common/button/index.html
<div>button</div>
{{ require "web:component/common/button/index.html" }}
web
为命名空间,用于区分前端项目,在 fis-conf.js
中配置
自定义标签
framework
{{ framework "static/script/lib/mya.js" }}
<!DOCTYPE html>
<html>
...
</html>
指定项目依赖的模块加载器
注意:
- 如果在页面中手动引用了模块加载器(eg. mya.js/mod.js)或者包含模块加载器的文件(eg. core.js),则无需添加 framework 标签
- 可以通过命名空间引用其他模块的文件,比如
{{ framework="common:static/lib/mya.js" }}
require
{{ require src="static/script/lib/base.js" }}
{{ require src="common:static/script/lib/mya.js" }}
{{ require src="common:static/style/lib/core.css" }}
require
标签用于引用js或者css文件,支持跨模块引用。通过 require 引用的文件会按顺序收集起来,以js文件为例,最终和组件js(template引用的组件)一起插入到body最后或者指定位置(在 {% script %} 标签收集的js之前)。
非跨模块调用时,引用路径无需携带命名空间,构建时会自动添加上。
script
<div>
</div>
{{ script }}
require('page/home/index').init({{ .user }});
{{ endscript }}
script
标签包裹的js语句会被收集起来,和页面依赖的js文件(组件js、页面入口js等)一同插入到body最后其中页面依赖的js文件在前,script
标签包裹的js语句在后。多个 script
标签包含的语句会被合并到一对 <script></script>
当中,每个语句块会被自执行函数包裹起来。
比如上面例子实际渲染的结果是:
<body>
...
<script src="pkg.js"></script> <!-- 打包合并后的js -->
<script>
(function() {
require('page/home/index').init({{ .user }});
})();
</script>
</body>
script
标签主要的用途是包裹 组件调用 的语句。如果有些内嵌脚本,如统计脚本,不想被收集到最后面,直接使用原生标签即可。
注意:
- 被
script
包裹的js语句不能使用es6,因为这些语句可能包含模板语法,在babel编译时会报错。 - require可以通过命名空间引用其他模块的文件,比如
require('common:component/util/index')
style
{{ style }}
.home-comp1 {
color: red
}
{{ endstyle }}
style
标签包裹的css语句会被收集起来,和页面依赖的css文件(组件css、页面入口css等)一同插入到head最后,其中页面依赖的css文件在前,style
标签包裹的css语句在后。多个 style
标签包含的语句会被合并到一对 <style></style>
当中。
style
标签使用的场景不多,其意图主要也是实现组件的自我管理。比如一个组件只有少量样式,不希望外链接,可以放在 style
标签中。
注意: style
标签中的内容不会参与编译,所以不能使用 sass
或者 less
语法。
项目开发
前端项目
https://code.byted.org/mya/scaffold-go
后端项目
在后端项目里引用 gin 中间件。
文件合并
脚手架默认生成了以下打包合并规则:
/**
* 说明:以下是默认配置,可以根据自己业务进行调整
* 规则:
* 1. 页面组件和页面入口文件打包到一个文件中,比如
/component/home/comp1/index.js
/component/home/comp2/index.js
/page/home/index.js
->
/page/home.js
* 2. 公共组件打包到 common 文件中
*/
/**
* 页面文件配置
*/
// 页面组件和页面入口 allInOne
fis.match('/component/(*)/**.js', {
packTo: '/pkg/page/$1.js'
});
fis.match('/page/(*)/*.js', {
packTo: '/pkg/page/$1.js'
});
fis.match('/component/(*)/**.{scss,less}', {
packTo: '/pkg/page/$1.css'
});
fis.match('/page/(*)/*.{scss,less}', {
packTo: '/pkg/page/$1.css'
});
/**
* 公共文件配置
*/
// 项目公共组件
fis.match('/component/{api,common,const,util}/**.js', {
packTo: '/pkg/common.js'
});
fis.match('/component/{api,common,const,util}/**.{scss,less}', {
packTo: '/pkg/common.css'
});
需要说明的是,按照目录规范,component 下的目录(除了common、util、const、api等公共目录)都应该对应一个页面,比如 component/reflow_video、component/reflow_person,尽量不要出现 component/reflow/video component/reflow/person 的情况。page 下面可以出现分组,比如 page/reflow/reflow_video、page/reflow/reflow_person。可以看到,页面组件目录和页面入口目录的名字是相同的,这样做方面配置打包策略,让页面组件和页面入口合并到一个文件中。
比如:
fis.match('/component/(*)/**.js', {
packTo: '/pkg/page/$1.js'
});
fis.match('/page/reflow/(*)/*.js', {
packTo: '/pkg/page/$1.js'
});
这样 component/reflow_video 下的js 和 page/reflow/reflow_video 下的js 都会打到 /pkg/page/reflow_video.js 中。
我们的初衷是,如果你完全按照目录规范来组织项目(component和page下面的一级目录都是页面,没有分组),那么使用默认打包配置就能满足最小文件数的需求,如果你的目录结构下存在分组,可以通过自定义规则来实现精细化的打包。