浏览器无法识别使用节点文件系统编写的 html 个文件

Browser doesn't recognize html files written with node file system

我正在使用 React 和 Apollo 2 构建一个应用程序,我正在尝试编写一个脚本来生成用于服务器端渲染的静态 html 文件。

我目前正在使用此逻辑在服务器上呈现我的 React 组件并且它工作正常:

export default (Page) => (req, res) => {
    const App = (
        <ApolloProvider client={client(fetch)}>
            <Main>
                <Page />
            </Main>
        </ApolloProvider>
    );

    getDataFromTree(App).then(() => {
        const data = {
            html: ReactDOMServer.renderToString(App),
            seo: { title: "Home", description: "" }
        };
        res.render("index", { data });
    });
}

但我想生成 .html 文件,这样我就可以静态地为它们提供服务,而无需每次都使用 运行 这种方法。我尝试将 renderToString 的结果编译为 .ejs 文件,然后使用 fs 写入文件,但没有成功。这是代码:

const component = ReactDOMServer.renderToString(App);
const template = ejs.compile(fs.readFileSync(path.join(__dirname, 'landing_template.ejs'), 'utf-8'));
const html = template({ component });

fs.writeFile(
    path.join(__dirname, "../views/landing.ejs"),
    html, 
    err => {
        if(err) console.log(err);
        else console.log("done.");
});

文件写入成功,但如果我打开我的页面源代码,编译方法添加的部分是灰色的,似乎被忽略了:

我也试过只读取文件并使用 .replace 替换字符串并插入一个虚拟 div,但结果始终相同。

// using compile
const template = ejs.compile(fs.readFileSync(path.join(__dirname, 'landing_template.ejs'), 'utf-8'));
const html = template({ component });

const template = ejs.compile(fs.readFileSync(path.join(__dirname, 'landing_template.ejs'), 'utf-8'));
const html = template({ component: "<div>teste</div>" });

// using readFile
const template = fs.readFileSync(path.join(__dirname, 'landing_template.ejs'), 'utf-8');
const html = template.replace("<%- component %>", component);

const template = fs.readFileSync(path.join(__dirname, 'landing_template.ejs'), 'utf-8');
const html = template.replace("<%- component %>", "<div>teste</div>");

// maybe this is the problem?
fs.writeFile(
    path.join(__dirname, "../views/landing.ejs"),
    html,
    { encoding: "utf8" },
    err => {
        if(err) console.log(err);
        else console.log("done.");
});

我猜浏览器无法将此新文本识别为 HTML 并且无法解析它。有谁知道我可以做这个的方法吗?

谢谢!

多么酷的主意!这可能是因为,正如您提到的,浏览器没有识别出您正在发送 html 这一事实。在调用 render:

之前尝试将 Content-Type header 显式设置为 text/html
export default (Page) => (req, res) => {
    const App = (
        <ApolloProvider client={client(fetch)}>
            <Main>
                <Page />
            </Main>
        </ApolloProvider>
    );

    getDataFromTree(App).then(() => {
        const data = {
            html: ReactDOMServer.renderToString(App),
            seo: { title: "Home", description: "" }
        };
        res.setHeader("Content-Type", "text/html");
        res.render("index", { data });
    });
}

编辑

啊,我看到了!不幸的是,您不能在 HTML 中使用 self-close <script> 标签,这会使浏览器出错。像这样关闭 header 中的脚本标签:

<script async src="/build/app.bundle.js" type="text/javascript"></script>

这应该可以解决问题。

<script /> 是错误的。你必须使用这个:

<script src="URL"></script>