使用 Express + EJS,如何呈现为静态站点?

Using Express + EJS, how can I render as a static site?

我正在使用 Express Application Generator,并从默认选项中选择 "EJS"。我有一个不错的工作站点,但老实说,我只需要服务器每天更新一次缓存 API。

在其他项目中,当我使用 hexo.js 时,我将所有 EJS 模板呈现到 'public' 文件夹中。

目前 express 可以很好地为我的 EJS 应用程序提供服务,但我如何让它吐出一个完整的静态版本?

查看 EJS 文档,我发现了一些促使我尝试这个的东西:


ejs /home/kyle/code/corona/corona-server/views/analysis.ejs -o test.html
/usr/local/lib/node_modules/ejs/lib/ejs.js:359
  throw err;
  ^

Error: ejs:1
 >> 1| <%- include("_partials/base", {
    2|     page:"analysis",
    3|     combo:["ionrangeslider"],
    4|     scripts: ["analysis"],

Could not find the include file "_partials/base"
    at getIncludePath (/usr/local/lib/node_modules/ejs/lib/ejs.js:183:13)
    at includeFile (/usr/local/lib/node_modules/ejs/lib/ejs.js:309:19)
    at include (/usr/local/lib/node_modules/ejs/lib/ejs.js:689:16)
    at eval (eval at compile (/usr/local/lib/node_modules/ejs/lib/ejs.js:661:12), <anonymous>:10:17)
    at anonymous (/usr/local/lib/node_modules/ejs/lib/ejs.js:691:17)
    at Object.exports.render (/usr/local/lib/node_modules/ejs/lib/ejs.js:423:37)
    at Immediate.run (/usr/local/lib/node_modules/ejs/bin/cli.js:197:20)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)

但无济于事,当 运行 像这样时,它似乎无法处理相对文件路径。

正确的做法是什么?

我最终为此使用了 express 而不是 EJS CLI。而在默认提供的设置中,一个人使用 res.render,我们可以改为使用 app.renderres.render 内部使用)。

完成后,我们使用节点 fs 将输出写入文件。

这是我在本地工作的一个切碎版本,虽然这个迭代本身未经测试(应该工作或非常接近)

// make-static.js
var express = require('express');
const fs = require('fs');
const { spawn } = require("child_process");


// note that whatever is in index 0 will be duplicated as 'index' as well
let activePages = ['compare', 'analysis', 'about'];

// `hasApp` can be req, res, or { app }. 
let renderPage = (hasApp, pageName, pageTemplate, data) => new Promise(
 (resolve, reject) => {
    hasApp.app.render(pageTemplate, { data, region:"" }, (err, renderedPage) => {
        fs.writeFile(`public/${pageName}.html`, renderedPage, (err) => {
            if (err) throw err;
            else {
                // success case, the file was saved
                console.log('Render successful!');
                resolve()
            }
        });
    })
 }
);


let renderEJS = function(data, hasApp) {
    return // feature flag for surge build

    Promise.all(
        activePages.map((page, i) => {
            let renderPromises = [];
            if (i === 0) renderPromises.push(renderPage(hasApp, '200', page, data))
            renderPromises.push(renderPage(hasApp, page, page, data))
            return Promise.all(renderPromises)
        })
    )

exports.renderEJS = renderEJS;

// app.js, root of express application

/* all the normal stuff, only commented out to draw your attention to the 
main focus here
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

const routerFor = {
  analysis: require('./routes/analysis.js'),
};
*/
var app = express();
require('./utils/make-static').renderEJS

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
/* etc., etc.
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
*/

renderEJS({ params:null, required:"", by:[1,2,3], your:"ejs templates" }, { app })