在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 path activeTheme, err := database.RetrieveActiveTheme() if err != nil { return err } currentThemePath := filepath.Join(filenames.ThemesFilepath, *activeTheme) // Create watcher err = 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 database err = 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 database err = 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 compiled if _, 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] = helper return 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)
做最终编译。
模板编译方面更细节的东西我就没什么兴趣了,大家有兴趣可以自己研究下,欢迎交流^_^