Vue SFC 中 nunjucks 模板引擎的使用与配置

1,075 阅读1分钟

此文针对 vue-loader@13.7.2 版本。 后续版本如果对应实现没有大的变化,也适用。 模板编译相关代码见 vue-loader/lib/template-compiler

preprocessor

通过引入 consolidate 库对 template 进行预处理来支持比如pugnjk 等 html 模板语言。

const cons = require('consolidate')
const loaderUtils = require('loader-utils')

module.exports = function (content) {
  this.cacheable && this.cacheable()
  const callback = this.async()
  const opt = loaderUtils.getOptions(this) || {}

  if (!cons[opt.engine]) {
    return callback(
      new Error(
        "Template engine '" +
          opt.engine +
          "' " +
          "isn't available in Consolidate.js"
      )
    )
  }

  // allow passing options to the template preprocessor via `template` option
  if (this.options.__vueOptions__) {
    Object.assign(opt, this.options.__vueOptions__.template)
  }

  // for relative includes
  opt.filename = this.resourcePath

  cons[opt.engine].render(content, opt, (err, html) => {
    if (err) {
      return callback(err)
    }
    callback(null, html)
  })
}

所以其实 SFC 中可以支持自己喜欢的任意 consolidate 支持的模板语言。 我的选择是 nunjucks

从上面的代码我们可以看出。可以通过在 vueOptions 中增加 template 配置项来将模板渲染的配置传递给 render 函数。 比如 vue-loader.conf.js 中可以这样写。

module.exports = {
  loaders: loaders,
  transformToRequire: {
    video: "src",
    source: "src",
    img: "src",
    image: "xlink:href"
  },
  template: {
  }
};

但是值得注意的是这个 options 传递给的是 render 函数。 由于 nunjucks 中的 变量插值语法跟 vue 的模板的想冲突。 所以我想修改 nunjucks 中的语法。因为 nunjucks 毕竟使用场景比较少一些。

实现自定义 nunjucks 变量插件语法

通过查看 nunjucks 的源代码发现,nunjucks 默认使用了一个全局的 Enviroment 配置。 也就是说可以在 webpack 打包运行开始时对 nunjucks 进行配置,因为他们都在同一个进程中运行,全局变量的修改可以影响后续的代码执行。 所以可以在 vue-loader.conf.js 中进行如下配置。

  1. 导入 nunjucks
    const nunjucks = require("nunjucks");
    
  2. 配置
nunjucks.configure( {
 tags: {
   variableStart: '<$',
   variableEnd: '$>',
 }
});

最终 It Works