node.js - nodejs 的sails 框架如何修改ejs的后缀为html
迷茫
迷茫 2017-04-17 16:03:33
0
2
688
迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

reply all(2)
伊谢尔伦

Solution found

When we changed the suffix of the template to html, we found an error when accessing the page. It was obvious that the suffix configuration was incorrect. 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 rrreee

I searched for the code Could not render view and found an extra node view. At this time, I looked for the keyword defaultEngine. A full-text search was conducted and a location was found. 🎜 rrreee 🎜According to the above code, it means that default Engine is obtained from the configuration of view engine. Then let’s continue searching for view engine. Find the following code: 🎜 rrreee 🎜We can see from the above code that this view engine is actually the configuration from sails.config.view.engine.ext, which is the same as our configuration file path. 🎜 rrreee 🎜At this time, let’s put a breakpoint in this code🎜 rrreee 🎜Then something wonderful happened🎜 rrreee 🎜It seems that this is the corresponding configuration, but when I opened this file, I found that the engine inside was defined like this🎜 rrreee 🎜wtf! , what is the situation and why the format is wrong. I thought it would be a json string. 🎜 🎜Then feel free to adjust it🎜 rrreee 🎜Export again and you will get the correct configuration changes🎜 rrreee 🎜At this time, we restarted with full confidence and refreshed the page, but found another error! ! ! ! wtf🎜 rrreee 🎜The error report has changed, indicating that the modification just now is definitely effective. Then at this time, I changed the header suffix name back to ejs and found that the front-end page was normal. It seems that when this header file is loaded, the suffix name is written in the program. 🎜 🎜The remaining process is to determine where the problem is, and find out where the problem is based on the execution order of the error report! 🎜 rrreee 🎜Locate the above code and find that there is a problem with the path variable, causing it not to be found. Let’s print name and filename🎜 rrreee 🎜At this time we have located the method resolveInclude🎜 rrreee 🎜See, it means that splicing is done here, but it will only be spliced ​​when extname returns empty, which means that when name is passed in, it will be spliced. There is no suffix! ! ! ! 🎜 🎜So after seeing this, I basically understand that in the template layout.html, the include command is used to load the header🎜 rrreee 🎜So we change the header here to header.html and then visit it again, and it will be normal. 🎜
伊谢尔伦

Then why don’t you try jade template, you can write it directly in native html

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template