搜尋

首頁  >  問答  >  主體

node.js - nodejs 的sails 框架如何修改ejs的后缀为html

迷茫迷茫2876 天前719

全部回覆(2)我來回復

  • 伊谢尔伦

    伊谢尔伦2017-04-17 16:05:33

    已找到解決方案

    當我們將模板的後綴都改為html的時候,訪問頁面發現了報錯,很明顯是後綴​​配置不正確。 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

    我去查找了Could not render view這段程式碼,發現多出來一個節點view,這時候我找一個關鍵字defaultEngine來進行了全文搜索,找到了一處定位。 🎜 rrreee 🎜按照上面的程式碼來看,說明default Engine是從view engine的設定中取得的。那我們再繼續搜尋view engine。找到如下碼:🎜 rrreee 🎜透過上面的程式碼我們可以看出 這個view engine其實是來自sails.config.view.engine.ext的配置,跟我們的設定檔路徑一樣。 🎜 rrreee 🎜這時候我們在這程式碼裡打一個斷點🎜 rrreee 🎜然後奇妙的事情出現了🎜 rrreee 🎜看來這就是對應的配置,但是當我打開這個檔案的時候發現裡面的engine是這樣定義的🎜 rrreee 🎜wtf! ,這是什麼情況,為什麼格式不對。我以為會是json的字串。 🎜 🎜然後大膽的來調整吧🎜 rrreee 🎜再次輸出就得到了正確的配置改變🎜 rrreee 🎜這時候我們滿懷信心重啟後刷新頁面,卻發現了另外一個報錯! ! ! ! wtf🎜 rrreee 🎜報錯發生了變化,說明剛剛的修改肯定是有作用的。然後這時候我單獨把header的字尾名改回ejs發現,前端頁面正常了。看來這個header檔案載入的時候,後綴名是程式裡面寫好的了。 🎜 🎜剩下的流程就是判斷到底哪裡的問題了,根據報錯的執行順序來找下到底那兒的問題! 🎜 rrreee 🎜定位到上面的程式碼,發現是path變數除出了問題,導致沒有找到。我們印一下namefilename🎜 rrreee 🎜這時候我們定位到了方法resolveInclude🎜 rrreee 🎜看到了吧,說明這個地方是進行拼接了,但是只有在extname返回為空的情況下才會拼接,說明這裡的name傳遞進來的時候是沒有攜帶後綴名的! ! ! ! 🎜 🎜所以看到這裡基本上明白了,在模板layout.html中,使用了include命令來加載了header🎜 rrreee 🎜所以我們將這裡的header改為header.html然後再重新訪問,就正常了。 🎜

    回覆
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 16:05:33

    那為什麼不試試jade模板了,可以直接用原生html寫

    回覆
    0
  • 取消回覆