解决“当前未启用对实验性语法 'jsx' 的支持” - React + Express + Webpack + Babel

问题描述

我已经阅读了类似的回复,但无法根据这些问题/答案找到我的具体问题,因此对于经常出现的问题,我提前道歉。

我在托管 React 应用程序的 AWS EB 上运行快速服务器。但是,我目前正在使用通用路由,并希望出于 SEO 目的切换到同构路由/服务器端渲染。我按照 this guide 获得了托管 React 前端的初始 express 应用,效果很好!

然后我尝试使用 this guide 添加服务器端渲染。

我的错误是:

Module build Failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /express-app/client/src/index.js: Support for the experimental Syntax 'jsx' isn't currently enabled (13:5):
Add @babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation.

这是我的文件结构:

express-app/
- package.json
- server.js
- router.js
- routes.js
- renderFullPage.js
- .babelrc
- webpack.config.js
- client/ // This houses the React app
-- package.json
-- src/
--- index.js
--- app.js
--- // Other component sources
-- build/
--- Output from `npm run build-web`

最初,express 应用程序基本上只是用于为客户端构建提供服务的单个 server.js。

express-app/.babelrc:

{
  "presets": [
    "@babel/preset-env","@babel/preset-react"
  ]
}

以前,这不包括“@babel/preset-react”行。

express-app/webpack.config.js:

var path = require('path');
var webpack = require('webpack');

module.exports = {
    devtool: 'inline-source-map',entry: ['./client/src/index.js'],output: {
        path: path.join(__dirname,'client','build'),filename: 'bundle.js'
    },module: {
        rules: [
            {
                loader: 'babel-loader',include: path.join(__dirname,'src'),exclude: /node_modules/,/*query: {
                    presets: ['es2015','react']
                }*/
            }
        ]
    }
};

这里值得注意的是,我遵循的指南有 module.loaders 而不是 module.rules,因为该指南较旧。首先我将加载器更改为规则,然后它抱怨查询,所以我将其注释掉。

express-app/package.json

{
  "name": "redacted","version": "1.0.0","description": "redacted","main": "server.js","scripts": {
    "start": "nodemon --exec babel-node server.js --ignore client","build": "babel server.js --out-file server.compiled.js","build:client": "webpack --config ./webpack.config.js/","build:prod": "npm run build && npm run build:client"
  },"author": "redacted","license": "ISC","dependencies": {
    "cors": "^2.8.5","express": "^4.17.1","node-jsx": "^0.13.3"
  },"devDependencies": {
    "@babel/cli": "^7.13.10","@babel/core": "^7.13.10","@babel/node": "^7.13.12","@babel/preset-env": "^7.13.12","@babel/preset-react": "^7.12.13","nodemon": "^2.0.7","babel-loader": "^8.2.2","babel-preset-react": "^6.24.1","webpack": "^5.28.0","webpack-cli": "^4.5.0"
  }
}

在之前的实现中,脚本部分不包括 build:client 或 build:prod 行。我会在创建我的构建文件夹的 npm run build-web 文件夹中运行 client/,然后从顶级文件夹运行 npm run build,这将创建我编译的 server.js 文件。然后我会把它上传到 EB 并且一切顺利! devDependencies 是相同的,除了 nodemon 下面的所有内容都是遵循第二个指南后的新内容

express-app/client/package.json:

{
    "name": "redacted","main": "./App.js","engines": {
        "node": "12.21.0","npm": "6.14.11"
    },// ...
    "dependencies": {
        "react": "^17.0.1","react-art": "^16.13.1","react-dom": "^17.0.1","react-native": "^0.63.4","react-native-linear-gradient": "^2.5.6","react-native-web": "^0.15.0","react-native-webview": "^11.3.1","react-router-dom": "^5.2.0","react-scripts": "4.0.1","request": "^2.88.2","web-vitals": "^0.2.4"
    },"scripts": {
        "start-web": "react-scripts start","build-web": "react-scripts build","test-web": "react-scripts test","eject-web": "react-scripts eject","start:prod": "NODE_ENV=production node build/index.js","eb:prod": "npm run build-web && npm run start:prod"
    },"devDependencies": {
        "@babel/preset-react": "^7.12.13","babel-cli": "^6.26.0","babel-plugin-module-resolver": "^4.1.0","babel-plugin-transform-object-rest-spread": "^6.26.0","babel-plugin-transform-react-jsx-source": "^6.22.0","babel-preset-es2015": "^6.24.1","babel-preset-expo": "^8.3.0","eslint": "^7.22.0","eslint-plugin-react": "^7.22.0"
    }
}

从这个文件中为你剪下我认为是膨胀的内容。此文件目前未更改,但从其他一些类似的问题/答案来看,我尝试将 "main": "./App.js", 更改为使用 ./build/App.js,但无济于事。

这是我的 express-app/server.js

//Server.js

const express = require('express');
const path = require('path');
import router from './router';

const PORT = process.env.HTTP_PORT || 4001;
const app = express();

app.use(express.static(path.join(__dirname,'build')));


// Old routing before using isomorphic
/*
app.get('/*',(req,res) => {
    res.sendFile(path.join(__dirname,'build','index.html'));
});
*/

// Now using router.js for isomorphic handling
app.get('*',router);


app.listen(PORT,() => {
    console.log(`Server listening at port ${PORT}.`);
});

我留下了之前版本的评论,所以你可以看到我的代码是如何变化的。

express-app/router.js:

import {renderToString} from 'react-dom/server';
import React from 'react';
import {matchPath,StaticRouter} from 'react-router-dom';

import routes from './routes';
import renderFullPage from './renderFullPage';
import App from './client/src/app';

export default function router(req,res) {
    const match = routes.reduce((acc,route) => matchPath(req.url,{path: route,exact: true}) || acc,null);

    if( !match ){
        res.status(404).send('page not found :(');
        return;
    }

    const context = {};
    const html = renderToString(
        <StaticRouter context={context} location={req.url} >
            <App />
        </StaticRouter>
    );
    
    res.status(200).send(renderFullPage(html));

};

我注意到 App 的路径是 ./client/src/app,所以这可能是 an 问题,但似乎不是 the 问题,因为它是index.js 变坏了。

express-app/client/src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import {browserRouter as Router} from 'react-router-dom';
import './index.css';
import App from './App';




// For isomorphic handling
ReactDOM.render((
    <browserRouter>
        <App />
    </browserRouter>),document.getElementById('root')
);

// This was used prior to isomorphic handling
/*
ReactDOM.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>,document.getElementById('root')
);
*/

我再次将旧代码注释掉以进行比较。这就是我的错误的根源。在 browserRouter 行抛出错误

我一直在纠结如何在不破坏东西的情况下解决这个问题。我需要重构我的整个应用程序吗?基本上改变我对客户端目录的划分?有没有我错过的愚蠢的衬里?任何帮助非常感激!

解决方法

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

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

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