2019独角兽企业重金招聘Python工程师标准>>>

Journey源码分析二:整体启动流程中提到了模板编译,这里详细说下启动流程

看下templates.Generate()源码:

func Generate() error {compiledTemplates.Lock()defer compiledTemplates.Unlock()// 首先清除模板(主题可能已经改变了)compiledTemplates.m = make(map[string]*structure.Helper)// 编译所有模板文件。err := checkThemes()if err != nil {return err}// If the dev flag is set, watch the theme directory and the plugin directoy for changes// TODO: It seems unclean to do the watching of the plugins in the templates package. Move this somewhere else.if flags.IsInDevMode {// Get the currently used theme pathactiveTheme, err := database.RetrieveActiveTheme()if err != nil {return err}currentThemePath := filepath.Join(filenames.ThemesFilepath, *activeTheme)// Create watchererr = watcher.Watch([]string{currentThemePath, filenames.PluginsFilepath}, map[string]func() error{".hbs": Generate, ".lua": plugins.Load})if err != nil {return err}}return nil
}

模板编译主要在checkThemes()函数中:

func checkThemes() error {// Get currently set theme from database// 从数据库获取当前数据库activeTheme, err := database.RetrieveActiveTheme()if err != nil {return err}currentThemePath := filepath.Join(filenames.ThemesFilepath, *activeTheme)err = compileTheme(currentThemePath)if err == nil {return nil}// 如果当前主题编译失败,则尝试默认主题(promenade)err = compileTheme(filepath.Join(filenames.ThemesFilepath, "promenade"))if err == nil {// Update the theme name in the databaseerr = methods.UpdateActiveTheme("promenade", 1)if err != nil {return err}return nil}// 如果默认主题也编译失败,则遍历所有可用的主题,选取第一个可用的。allThemes := GetAllThemes()for _, theme := range allThemes {err = compileTheme(filepath.Join(filenames.ThemesFilepath, theme))if err == nil {// Update the theme name in the databaseerr = methods.UpdateActiveTheme(theme, 1)if err != nil {return err}return nil}}return errors.New("Couldn't find a theme to use in " + filenames.ThemesFilepath)
}

看下compileTheme(currentThemePath)源码:

func compileTheme(themePath string) error {// 检查主题目录是否存在if _, err := os.Stat(themePath); os.IsNotExist(err) {return errors.New("Couldn't find theme files in " + themePath + ": " + err.Error())}err := filepath.Walk(themePath, inspectTemplateFile)if err != nil {return err}// Check if index and post templates are compiledif _, ok := compiledTemplates.m["index"]; !ok {return errors.New("Couldn't compile template 'index'. Is index.hbs missing?")}if _, ok := compiledTemplates.m["post"]; !ok {return errors.New("Couldn't compile template 'post'. Is post.hbs missing?")}// Check if pagination and navigation templates have been provided by the theme.// If not, use the build in ones.if _, ok := compiledTemplates.m["pagination"]; !ok {err = compileFile(filepath.Join(filenames.HbsFilepath, "pagination.hbs"))if err != nil {log.Println("Warning: Couldn't compile pagination template.")}}if _, ok := compiledTemplates.m["navigation"]; !ok {err = compileFile(filepath.Join(filenames.HbsFilepath, "navigation.hbs"))if err != nil {log.Println("Warning: Couldn't compile navigation template.")}}return nil
}

上面代码的核心代码是err := filepath.Walk(themePath, inspectTemplateFile),该方法遍历主题目录中的文件,并调用inspectTemplateFile()函数,看下inspectTemplateFile()的源码:

func inspectTemplateFile(filePath string, info os.FileInfo, err error) error {if !info.IsDir() && filepath.Ext(filePath) == ".hbs" {err := compileFile(filePath)if err != nil {return err}}return nil
}

如果filePath是文件并且以.hbs结尾则编译它。看下compileFile(filePath)源码:

func compileFile(fileName string) error {// 编译模板文件helper, err := createTemplateFromFile(fileName)if err != nil {return err}// 将模板放入到全局变量compiledTemplates.m中去。compiledTemplates.m[helper.Name] = helperreturn nil
}

看下createTemplateFromFile(fileName)源码:

func createTemplateFromFile(filename string) (*structure.Helper, error) {data, err := ioutil.ReadFile(filename)if err != nil {return nil, err}fileNameWithoutExtension := helpers.GetFilenameWithoutExtension(filename)// 如果同名的模板已经存在compiledTemplates.m字典中则报错。if compiledTemplates.m[fileNameWithoutExtension] != nil {return nil, errors.New("Error: Conflicting .hbs name '" + fileNameWithoutExtension + "'. A theme file of the same name already exists.")}helper := compileTemplate(data, fileNameWithoutExtension)return helper, nil
}

该函数主要是读取模板文件,然后调用compileTemplate(data, fileNameWithoutExtension)做最终编译。

模板编译方面更细节的东西我就没什么兴趣了,大家有兴趣可以自己研究下,欢迎交流^_^

转载于:https://my.oschina.net/fmnisme/blog/502487

Journey源码分析三:模板编译相关推荐

  1. 【投屏】Scrcpy源码分析三(Client篇-投屏阶段)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  2. Spring源码分析(三)

    Spring源码分析 第三章 手写Ioc和Aop 文章目录 Spring源码分析 前言 一.模拟业务场景 (一) 功能介绍 (二) 关键功能代码 (三) 问题分析 二.使用ioc和aop重构 (一) ...

  3. 【投屏】Scrcpy源码分析一(编译篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  4. Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe

    Nouveau源码分析(三) 向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照. 对于匹配的设备,PCI模块 ...

  5. janusgraph源码分析1-下载编译启动 1

    date: 2018-04-26 title: "janusgraph源码分析1-下载编译启动" author: "邓子明" tags: - 源码 - janu ...

  6. v58.03 鸿蒙内核源码分析(环境脚本) | 编译鸿蒙原来很简单 | 百篇博客分析HarmonyOS源码

    颜渊问仁.子曰:"克己复礼为仁.一日克己复礼,天下归仁焉.为仁由己,而由人乎哉?"颜渊曰:"请问其目."子曰:"非礼勿视,非礼勿听,非礼勿言,非礼勿动 ...

  7. java 源码分析_Java 源代码编译成 Class 文件的过程分析

    原标题:Java 源代码编译成 Class 文件的过程分析 在上篇文章< Java三种编译方式:前端编译 JIT编译 AOT编译 >中了解到了它们各有什么优点和缺点,以及前端编译+JIT编 ...

  8. ABP源码分析三十四:ABP.Web.Mvc

    ABP.Web.Mvc模块主要完成两个任务: 第一,通过自定义的AbpController抽象基类封装ABP核心模块中的功能,以便利的方式提供给我们创建controller使用. 第二,一些常见的基础 ...

  9. 【转】ABP源码分析三十六:ABP.Web.Api

    这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net w ...

最新文章

  1. C#温故而知新学习系列之.NET框架高级特性—概述.NET框架中的反射(一)
  2. 电脑显示器不亮主机正常_为什么会突然显示器黑屏但主机正常工作和解决办法。...
  3. 珍惜那些爱你的人,不要令他们失望,加油吧,我们。
  4. 移动端适配--meta标签玩的是什么
  5. 变频器服务器电路板维修,变频器线路板常见维修方法
  6. 计算机网络项目——最小网元设计(阶段四)
  7. When we first heard of Linux
  8. LeetCode 139. 单词拆分(动态规划)
  9. 源码安装MySQL步骤
  10. 选择排序的Java代码实现(超详细代码)
  11. FPGA写约束文件+固化+上板抓信号方法(vivado软件)
  12. Centos 修改主机名称
  13. 1-20的两个数把和告诉A,积告诉B,A说不知道是多少,B也说不知道,这时A说我知道了,B说我也知道了,请你猜猜这两个数的和是多少
  14. 『幸运 9 点』IVR游戏商业计划书(转)
  15. Explorer.exe崩溃后自动重启任务栏托盘区图标丢失
  16. 解决VMware安装后网络连接中没有VMnet虚拟网络适配器
  17. ecshop促销剩余时间 的函数调用方法
  18. 转载 tiny6410 使用rt5370 usb无线网卡
  19. 【C语言】通讯录(文件版)
  20. GitHub上README.md写法暨GFM语法解读

热门文章

  1. 用ext_skel,实现一个PHP扩展,添加到PHP并调用
  2. 深入理解malloc和free
  3. AWS攻略——使用CodeCommit托管代码
  4. 一种清除windows通知区域“僵尸”图标的方案——问题分析
  5. YAML开源库yaml-cpp简介及使用
  6. C/C++中static关键字用法汇总
  7. C++/C++11中std::exception的使用
  8. C++11中default的使用
  9. 你,保持童心;我,帮你保持童颜
  10. php将关联数组输出到前台,如何使用foreach从PHP中的关联数组输出特定数据