[英]How can I pre-render a react app in gulp/node?
我接管並將舊的 react (0.12.0) 應用程序升級到最新版本。 這也涉及升級到 ES6。 React 代碼本身已經完成,但我們還需要預渲染應用程序(該應用程序是一個交互式文檔,必須被搜索引擎抓取)。
以前,gulp 構建過程在代碼上運行 browserify,然后使用 vm.runInContext 運行它:
// source code for the bundle
const component = path.resolve(SRC_DIR + subDir, relComponent);
vm.runInNewContext(
fs.readFileSync(BUILD_DIR + 'bundle.js') + // ugly
'\nrequire("react").renderToString(' +
'require("react").createElement(require(component)))',
{
global: {
React: React,
Immutable: Immutable,
},
window: {},
component: component,
console: console,
}
);
我很驚訝它以前有效,但確實有效。 但是現在它失敗了,因為源使用了 ES6。 我尋找了預制的解決方案,但它們似乎都針對舊的 React 版本,其中 react-tools 仍然存在。
我用 browserify & babel 打包了下面的特殊服務器端腳本,然后使用 runInNewContext 運行它。 它不會失敗但也不會輸出任何代碼,它只是記錄一個空對象
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './index';
const content = renderToString(<App />);
我發現了大量關於“服務器端渲染”的文章,但它們似乎都是關於用 express 渲染的,並且使用與上面腳本相同的行。 我無法直接在 gulp 中運行該代碼,因為它不適用於 ES6 導入,ES6 導入僅在節點 14 之后可用(並且是實驗性的)。
我沒有顯示 gulp-browserify 任務,它直接呈現應用程序組件,而不是上面的服務器端入口點腳本。 如果有人需要這樣做,這里有一個可行的解決方案。
使用vm.runInNewContext
允許我們定義一個合成瀏覽器上下文,而require
沒有。 如果您在應用程序的任何位置訪問window
這很重要。
源代碼/服務器.js:
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './index';
const content = renderToString(<App />);
global.output = content;
上面的腳本作為瀏覽器的入口點。 要編譯的 Gulp 任務:
function gulpJS() {
const sourcePath = path.join(SRC_DIR, 'src/server.js');
return browserify(sourcePath, { debug:true })
.transform('babelify', {
presets: [
["@babel/preset-env", { targets: "> 0.25%, not dead" }],
"@babel/preset-react",
],
})
.bundle()
.pipe(source('server_output.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('.'))
.pipe(dest(BUILD_DIR));
}
生成的文件現在可以供以后的任務使用,例如將呈現的內容插入到 HTML 文件中。
const componentContent = fs.readFileSync(path.join(BUILD_DIR, 'server.js'));
const context = {
global: {
React: React,
Immutable: Immutable,
data: {
Immutable
},
},
window: {
addEventListener() { /* fake */ },
removeEventListener() { /* fake */ },
},
console,
};
vm.runInNewContext(componentContent, context);
const result = context.global.output;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.