Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method to retrieve a list of dependencies used to compile a template #233

Closed
rdmurphy opened this issue Jun 23, 2020 · 2 comments
Closed

Comments

@rdmurphy
Copy link

Hello! I've poked around a bit but haven't had any luck figuring out if this is already possible — is there/could there be a way to determine what all files were involved in compiling a template? This would essentially be the list of "dependencies" that went into preparing a template. This would be useful for setting up a file watcher or doing intelligent re-compiles of templates only when one of a template's dependencies change.

Some examples in the wild:

  • In Nunjucks this is handled by an .on('load') event on the Nunjucks instance itself, but IMO it suffers from a couple flaws — it's not clear which input file being rendered triggered a load event, and setting this up is removed from the compile process.

  • In dart-sass this is undocumented but each render returns a list of includedFiles which references every single sass file that was touched in the process of preparing the styles. This is particularly ideal because there's no confusion as to how an entrypoint was prepared — this list is part of the render's response.

I will admit I am not 100% familiar with how liquidjs parses files and whether it eagerly does so or not, but I could imagine some sort of reference being added to Template instances (AKA the return value of parse and parseFile) may be workable.

@harttle
Copy link
Owner

harttle commented Jun 25, 2020

File access can be controlled by File System API, by which you can simulate the .on('load'). As you commented, there's a deficiency: it does not provide infomation about which template triggered the file access.

This problem can be solved by analysing the templates one by one: setup listeners, start render, collect dependencies when the render promise resolved. This won't work in production environments where templates are rendered asyncly. But it handles recursiveness correctly.

Another way to implement this is to make render() return a list of dependencies (which is not supported yet) along with the rendered HTML. Adding references to the Template won't work because file lookups (and thus dependencies) are determined during render and filenames can be variables when dynamicPartials is set to true.

harttle added a commit that referenced this issue Feb 12, 2021
harttle pushed a commit that referenced this issue Feb 12, 2021
# [9.23.0](v9.22.1...v9.23.0) (2021-02-12)

### Bug Fixes

* respect `fs` in parser options, for [#233](#233) ([4e82da6](4e82da6))

### Features

* support filters in if/unless/case, see [#287](#287) ([2f059f6](2f059f6))
* support function calls, closes [#222](#222) ([e37824f](e37824f))
* support layout none, closes [#299](#299) ([81e11bb](81e11bb))
@harttle
Copy link
Owner

harttle commented Feb 12, 2021

I made a snippet to collect the files read during one single render call. Note: it only works on >9.23.0, previous versions don't use the fs passed in when calling render.

const { Liquid } = require('liquidjs')
const { exists, existsSync, readFile, readFileSync } = require('fs')
const { resolve } = require('path')

const engine = new Liquid({ root: __dirname })

class MyFS {
  constructor() {
    this.list = []
  }
  exists(file) {
    return exists(file)
  }
  existsSync(file) {
    return existsSync(file)
  }
  readFile(filepath) {
    this.list.push(filepath)
    return readFile(filepath, 'utf8')
  }
  readFileSync(filepath) {
    this.list.push(filepath)
    return readFileSync(filepath, 'utf8')
  }
  resolve(root, file){
    return resolve(root, file)
  }
}

const fs = new MyFS(), ctx = {}, options = { fs }
const html = engine.renderFileSync('index.liquid', ctx, options)
console.log(html, fs.list)

@harttle harttle closed this as completed Feb 12, 2021
Repository owner locked and limited conversation to collaborators Feb 12, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

2 participants