gpt4 book ai didi

javascript - 路由导入的服务器端渲染问题

转载 作者:行者123 更新时间:2023-12-03 06:10:02 25 4
gpt4 key购买 nike

我发现了很多关于 React 的 SSR 的信息,并且所有这些信息都采用完全不同的方法。因此,我找到了一个在我的情况下看起来更有用的示例(React/graphQL/Apollo/Express/Webpack 上的网络应用程序),但我坚持了一个问题。下面是一些示例:

server.js

    ...
import {router} from './client/App';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { match, RoutingContext, Route } from 'react-router';
...
function renderApp(props, res) {
const markup = renderToString(<RoutingContext {...props}/>);
const html = createPage(markup);
write(html, 'text/html', res);
}

app.get('*', (req, res, next) => {
const location = hist.createLocation(req.path);
match({routes: router, location: location}, (err, redirectLocation, renderProps) => {
if (err) {
writeError('ERROR!', res);
next(err);
} else if (redirectLocation) {
redirect(redirectLocation, res);
} else if (renderProps) {
renderApp(renderProps, res);
} else {
writeNotFound(res);
}
});
});
...

App.js 从我们导入路由器的地方:

...

import Login from './components/Login';
import Register from './components/Register';
...
let routes = (
<Route>
<Route path="login" component={Login}/>
<Route path="register" component={Register}/>
...
</Route>
);

export let router = [{
path: '/',
component: Layout,
indexRoute: {
component: View
},
getChildRoutes(location, cb) {
require.ensure([], () => cb(null, routes));
}
}];

match({router, location}, () => {
render(
<ApolloProvider client={client}>
<div>
<Router routes={router} onUpdate={() => window.scrollTo(0, 0)} history={browserHistory}/>
</div>
</ApolloProvider>,
document.getElementById('root')
);
});

我尝试做类似 example 中的所有事情但问题是,在 server.js 中,我尝试从 App.js 导入 router 服务器不运行,并给出与 React 相关的错误组件(样式导入等。我们可以在客户端执行但不能在服务器上执行的所有操作)。

所以问题是,我做错了什么?我还能如何导入路由而不出现此问题?我已经在这个小任务上浪费了这么多时间,这真的很烦人。

如果有任何帮助,我将不胜感激,谢谢!

最佳答案

如您所知,服务器端渲染是在 Node 服务器中渲染您的 react 组件。但 Node 服务器不支持导入 css/png 文件。

如果您不想更改客户端代码,可以尝试用户 webpack-isomorphic-tools ,它将帮助您生成一个assert.json文件,该文件可以使require('*.css')调用返回一个json对象并生成CSS类名映射,就像在webpack css中一样-加载程序

有兴趣的话可以看看这个demo .

这是你的 webpack-isomorphic-tools.js

var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin');


module.exports = {


assets: {
images: {
extensions: [
'jpeg',
'jpg',
'png',
'gif'
],
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},
fonts: {
extensions: [
'woff',
'woff2',
'ttf',
'eot'
],
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},
svg: {
extension: 'svg',
parser: WebpackIsomorphicToolsPlugin.url_loader_parser
},

bootstrap: {
extension: 'js',
include: ['./src/theme/bootstrap.config.js'],
filter: function(module, regex, options, log) {
function is_bootstrap_style(name) {
return name.indexOf('./src/theme/bootstrap.config.js') >= 0;
}
if (options.development) {
return is_bootstrap_style(module.name) && WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log);
}

},

path: WebpackIsomorphicToolsPlugin.style_loader_path_extractor,
parser: WebpackIsomorphicToolsPlugin.css_loader_parser
},
style_modules: {
extensions: ['less','scss'],
filter: function(module, regex, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log);
} else {
return regex.test(module.name);
}
},
path: function(module, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.style_loader_path_extractor(module, options, log);
} else {
return module.name;
}
},
parser: function(module, options, log) {
if (options.development) {
return WebpackIsomorphicToolsPlugin.css_modules_loader_parser(module, options, log);
} else {
return module.source;
}
}
}
}
}

你的 server.js 应该是这样的

function renderFullPage (title, css, html, initialState) {
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<style type="text/css">${css}</style>
</head>
<body>
<div id="app">${html}</div>

<script>
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
</script>
<script src="/assets/scripts/app.bundle.js"></script>
</body>
</html>
`;
}

const asyncStore = (store, renderProps) => {
let promise = Promise.all([
store.dispatch(queryArtistList()),
store.dispatch(queryAuth())
]);
return promise;
}

const HomeCtrl = {
index: async (req, res) => {
// 补全同构应用运行时缺失的全局对象
global.window = {
navigator: {
userAgent: req.get('User-Agent'),
},
location: {
protocol: req.protocol + ':',
hostname: req.hostname,
},
};
match({ routes, location: req.url }, async (err, redirectLocation, renderProps) => {
if (err) {
res.status(500).end(`Internal Server Error ${err}`);
} else if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search + '/');
} else if (renderProps) {
let store = configureStore();
const state = store.getState();
await asyncStore(store, renderProps);
const components = (<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>);
const html = renderToStaticMarkup(components);

res.end(renderFullPage('tokyo Artist', '', html, store.getState()));

} else {
res.status(404).end('Not found');
}
})
}
}

请确保在生成 webpack-asserts.json 后启动服务器;

所以你的app.js应该是这样的:

#!/usr/bin/env node
const path = require('path');
const rootDir = path.resolve(__dirname, '..');
const fs = require('fs');

const babelrc = fs.readFileSync(rootDir + '/.babelrc', 'utf-8');
var config;

try {
config = JSON.parse(babelrc);
} catch (err) {
console.error('==> ERROR: Error parsing your .babelrc.');
console.error(err);
}

require('babel-register')(config);

/**
* Define isomorphic constants.
*/
global.__CLIENT__ = false;
global.__SERVER__ = true;
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';
global.__DEVTOOLS__ = __DEVELOPMENT__;


const WebpackIsomorphicTools = require('webpack-isomorphic-tools');
global.webpackIsomorphicTools = new WebpackIsomorphicTools(require('../webpack/webpack.isomorphic-tools'))
.development(__DEVELOPMENT__)
.server(__DEVELOPMENT__ ? __dirname : rootDir, function() {
require('../server/app.js');
});

关于javascript - 路由导入的服务器端渲染问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39358611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com