为什么 React hydration 没有加载?

问题描述

我正在尝试使用 React、Fastify 和 esbuild 构建我自己的服务器端渲染应用程序。捆绑过程成功运行而无需担心。但是当我尝试运行服务器时,没有加载客户端包脚本。 HTML 预计会显示在浏览器中,并且会请求客户端脚本(通过 chrome 开发工具检查 200 个响应代码)。就像脚本被请求但没有加载一样。我错过了什么吗?

显然影响任何事件监听器(onclick 等)都不会被调用。您可以在 repository

中查看完整版本的代码

src/client/index.tsx

import React from 'react';
import { hydrate } from 'react-dom';
import canUseDOM from '@bconnorwhite/can-use-dom';
import { createbrowserHistory,createMemoryHistory } from 'history';
import App from './App';

const bootstrap = (): void => {
  const root = document.getElementById('root');
  const history = canUseDOM ? createbrowserHistory() : createMemoryHistory();

  hydrate(<App history={history} />,root);
};

export default bootstrap;

src/server/index.ts

import fastify from 'fastify';
import helmet from 'fastify-helmet';
import staticAsset from 'fastify-static';
import debug from 'debug';
import { config } from 'dotenv';
import path from 'path';

import routes from './routes';
import assetParser from './decorators/assetParser';

config();

const log = debug('server:app');
const app = fastify({
  logger: true,disableRequestLogging: true,});

app.decorate('assetManifest',assetParser(log));

app.register(staticAsset,{
  root: path.join(process.cwd(),'dist'),});

app.register(helmet);
app.register(routes,{ log });

const PORT: number =
  process.env.NODE_ENV === 'development' ? Number(process.env.DEV_PORT || '') : Number(process.env.PROD_PORT || '');

const HOST: string = process.env.NODE_ENV === 'development' ? process.env.DEV_HOST || '' : process.env.PROD_HOST || '';

app.listen(PORT || 3000,HOST,(err,address) => {
  if (err) {
    log('Error bootstraping server:',err);
    app.log.error(JSON.stringify(err));

    process.exit(1);
  } else {
    log('Server listening to',address);
  }
});

builder/index.js

const path = require('path');
const debug = require('debug')('builder');
const { startService } = require('esbuild');
const { DEFAULT_CONfig } = require('./constant');

/**
 * Build function performs bundle and transpilation operation using esbuild. The function works
 * by reaching the configuration file (usually named esbuild.config.js) and parse the configuration
 * to the startService parameter.
 *
 * The function also calculates the process time using process.hrtime() and translate the result
 * into milisecond. The timer log is displayed for debugging purpose only.
 * @function build
 * @returns {void}
 */
const build = async () => {
  let config = {};

  try {
    config = await require(path.resolve(process.cwd(),'esbuild.config.js'));

    if (!config) {
      throw new Error('Config file is not defined');
    }
  } catch (error) {
    debug('Failed to read config file: ',error);
    process.exit(1);
  }

  const service = await startService();
  const startTimer = process.hrtime();

  try {
    await Promise.all(
      config.map(async (currentConfig) => {
        await service.build({
          ...DEFAULT_CONfig,...currentConfig,});
      }),);
  } catch (error) {
    debug('Error happened during build process:',error);
  } finally {
    service.stop();

    const endTimer = process.hrtime(startTimer);
    const timeInMs = (endTimer[0] * 1e9 + endTimer[1]) / 1e3;

    debug('Bundle process is finished at',timeInMs,'ms');
  }
};

(async () => {
  debug('Starting bundle process...');

  try {
    await build();
  } catch (error) {
    debug('Error happend during bundle process:',error);
  }
})();

esbuild.config.js

const path = require('path');
const { nodeExternalsPlugin } = require('esbuild-node-externals');

module.exports = [
  {
    entryPoints: [path.resolve(__dirname,'src/client/index.tsx')],outfile: './dist/index.browser.js',platform: 'browser',loader: {
      '.svg': 'file','.jpg': 'file','.png': 'file','.gif': 'file',},tsconfig: 'tsconfig.json',banner: '/* client dist */',Metafile: 'dist/asset-client-manifest.json',{
    entryPoints: [path.resolve(__dirname,'src/server/index.ts')],outfile: './dist/index.js',platform: 'node',minify: false,banner: '/* server dist */',format: 'cjs',plugins: [nodeExternalsPlugin()],];

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...