【问题标题】:Browser doesn't recognize html files written with node file system [duplicate]浏览器无法识别使用节点文件系统编写的 html 文件 [重复]
【发布时间】:2018-09-24 21:20:45
【问题描述】:

我正在使用 React an 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 代码的问题是
  • 脚本标签不是自闭合标签。即使&lt;script&gt;&lt;/script&gt; 之间没有任何内容,您也不能只使用&lt;script/&gt;

标签: javascript html node.js ejs server-side-rendering


【解决方案1】:

真是个好主意!这可能是因为,正如您所提到的,浏览器没有识别您正在发送 html 的事实。尝试在调用渲染之前将Content-Type 标头显式设置为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 中自行关闭 &lt;script&gt; 标记,这会使浏览器跳闸。像这样关闭标题中的脚本标签:

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

这应该可以解决问题。

【讨论】:

  • 我试过了,但没用。 :/ 在浏览器中查看,content-type是text/html,但是仍然解析失败。
  • @ThiagoLoddi 啊,我现在看到了问题!更新了我的答案。 :)
【解决方案2】:

&lt;script /&gt; 是错误的。你必须使用这个:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 2022-08-10
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2014-04-04
    相关资源
    最近更新 更多