nodejs 的sails 框架如何修改ejs的后缀为html

如何修改sails的ejs后缀名称呢?

想要修改ejs的后缀为html,因为很多编辑器针对ejs不会进行html的标签自动补全。

从网上找到的大部分资料都是

1.在app.js的头上定义ejs:
var ejs = require('ejs');

2.注册html模板引擎:
app.engine('html',ejs.__express);

3.将模板引擎换成html:
app.set('view engine', 'html');

4.修改模板文件的后缀为.html。

但是貌似只是针对express框架的。

由于sails是基于express框架的,我在代码中看到如下说明

 * For engines that do not provide `.__express` out of the box,
 * or if you wish to "map" a different extension to the template engine
 * you may use this method. For example mapping the EJS template engine to
 * ".html" files:
 *
 *     app.engine('html', require('ejs').renderFile);

需要将这段代码进行设置,但是我尝试了很多地方。都不行。
求解

阅读 4.6k
2 个回答

已找到解决方案

当我们将模板的后缀都改为html的时候,访问页面发现了报错,很明显是后缀配置不正确。

{
  "message": "Could not render view \"index\".  Tried locating view file @ \"/Users/sun.huajie/Documents/Workspace/node_sails/myapp/views/index\". Layout configured as \"layout\", so tried using layout @ \"/Users/sun.huajie/Documents/Workspace/node_sails/myapp/views/layout\")",
  "code": "E_VIEW_FAILED",
  "status": 500,
  "view": {
    "name": "index",
    "root": "/Users/sun.huajie/Documents/Workspace/node_sails/myapp/views",
    "defaultEngine": "ejs",
    "ext": ".ejs"
  }
}

我去查找了Could not render view这段代码,发现多出来一个节点view,这时候我寻找一个关键字defaultEngine来进行了全文搜索,找到了一处定位。

// view
  if (!view) {
    view = new (this.get('view'))(name, {
      defaultEngine: this.get('view engine'),
      root: this.get('views'),
      engines: engines
    });
    .
    .
    .

按照上面的代码来看,说明default Engine是从view engine的配置中获取的。那我们再继续搜索view engine。找到如下代码:

// Configure views if hook enabled
      if (sails.hooks.views) {

        // TODO: explore handling this differently to avoid potential
        // timing issues with view engine configuration
        sails.after('hook:views:loaded', function() {
          var View = require('./view');

          // Use View subclass to allow case-insensitive view lookups
          expressApp.set('view', View);

          // Set up location of server-side views and their engine
          expressApp.set('views', sails.config.paths.views);

          // Teach Express how to render templates w/ our configured view extension
          expressApp.engine(sails.config.views.engine.ext, sails.config.views.engine.fn);

          // Set default view engine
          sails.log.verbose('Setting default Express view engine to ' + sails.config.views.engine.ext + '...');
          expressApp.set('view engine', sails.config.views.engine.ext);
        });

通过上面的代码我们可以看出 这个view engine实际上是来自sails.config.view.engine.ext的配置,跟我们的配置文件路径一样。

/Users/sun/Documents/Workspace/node_sails/myapp/config/view.js

这个时候我们在这代码里打一个断点

console.info(sails.config);

然后奇妙的事情出现了

...
  views:
   { engine: { name: 'ejs', ext: 'ejs', fn: [Function] },
     layout: 'layout',
     partials: false },
...

看来这就是对应的配置,但是当我打开这个文件的时候发现里面的engine是这样定义的

engine:'ejs'

wtf!,这是什么情况,为什么格式不对。我以为会是json的字符串。

然后大胆的来调整一下吧

engine: {
    name:'ejs',
    ext:'html'
  },
  

再次输出就得到了正确的配置改变

{ engine: { name: 'ejs', ext: 'html', fn: [Function] },

这个时候我们满怀信心重启后刷新页面,却发现了另外一个报错!!!!wtf

Error: ENOENT: no such file or directory, open '/Users/sun.huajie/Documents/Workspace/node_sails/myapp/views/header.ejs'
    at Error (native)
    at Object.fs.openSync (fs.js:640:18)
    at fs.readFileSync (fs.js:508:33)
    at Object.exports.parse (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:160:19)
    at exports.compile (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:225:15)
    at Object.exports.render (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:285:10)
    at Object.exports.renderFile (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:319:20)
    at module.exports (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/index.js:85:7)
    at /usr/local/lib/node_modules/sails/node_modules/ejs-locals/index.js:131:7
    at Object.exports.renderFile (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/node_modules/ejs/lib/ejs.js:319:3)
    at SailsView.module.exports [as engine] (/usr/local/lib/node_modules/sails/node_modules/ejs-locals/index.js:85:7)
    at SailsView.View.render (/usr/local/lib/node_modules/sails/node_modules/express/lib/view.js:76:8)
    at Function.app.render (/usr/local/lib/node_modules/sails/node_modules/express/lib/application.js:565:10)
    at ServerResponse.res.render (/usr/local/lib/node_modules/sails/node_modules/express/lib/response.js:845:7)
    at ServerResponse.res.view (/usr/local/lib/node_modules/sails/lib/hooks/views/res.view.js:284:16)
    at Object.index (/Users/sun.huajie/Documents/Workspace/node_sails/myapp/api/controllers/UserController.js:36:14)
    at wrapper (/usr/local/lib/node_modules/sails/node_modules/@sailshq/lodash/lib/index.js:3250:19)
    at routeTargetFnWrapper (/usr/local/lib/node_modules/sails/lib/router/bind.js:181:5)
    at callbacks (/usr/local/lib/node_modules/sails/node_modules/express/lib/router/index.js:164:37)
    at param (/usr/local/lib/node_modules/sails/node_modules/express/lib/router/index.js:138:11)
    at param (/usr/local/lib/node_modules/sails/node_modules/express/lib/router/index.js:135:11)
    at pass (/usr/local/lib/node_modules/sails/node_modules/express/lib/router/index.js:145:5)

报错发生了变化,说明刚刚的修改肯定是有作用的。然后这个时候我单独把header的后缀名改回ejs发现,前端页面正常了。看来这个header文件加载的时候,后缀名是程序里面写好的了。

剩下的流程就是判断到底哪儿的问题了,根据报错的执行顺序来找下到底那儿的问题!

if (0 == js.trim().indexOf('include')) {
        var name = js.trim().slice(7).trim();
        if (!filename) throw new Error('filename option is required for includes');
        var path = resolveInclude(name, filename);
        
        include = read(path, 'utf8');
        include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
        buf += "' + (function(){" + include + "})() + '";
        js = '';
      }

定位到上面的代码,发现是path变量除出了问题,导致没有找到。我们打印一下namefilename

header
/Users/sun.huajie/Documents/Workspace/node_sails/myapp/views/layout.html

这个时候我们定位到了方法resolveInclude

function resolveInclude(name, filename) {
  var path = join(dirname(filename), name);
  var ext = extname(name);
  if (!ext) path += '.ejs';
  return path;
}

看到了吧,说明这个地方是进行拼接了,但是只有在extname返回为空的情况下才会拼接,说明这里的name传递进来的时候是没有携带后缀名的!!!!

所以看到这里基本上明白了,在模板layout.html中,使用了include命令来加载了header

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <% include header %>

所以我们将这里的header改为header.html然后再重新访问,就正常了。

那你为什么不试试jade模板了,可以直接用原生html写

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏