2017-06-26 4 views
1

Ich habe dieses Problem jetzt seit 3 ​​Tagen untersucht, kann es aber nicht funktionieren.Webpack & Babel: Serverseitiges Rendering der React-Komponente "Unerwartetes Token" <'"

Der vollständige Fehler ist:

C:\Users\XXXXXX\WebstormProjects\XXXX\server\routes\auth.jsx:58 
    return res.send(ReactDOMServer.renderToString(<LoginPage />)); 
               ^
SyntaxError: Unexpected token < 
    at createScript (vm.js:56:10) 
    at Object.runInThisContext (vm.js:97:10) 
    at Module._compile (module.js:542:28) 
    at Object.Module._extensions..js (module.js:579:10) 
    at Module.load (module.js:487:32) 
    at tryModuleLoad (module.js:446:12) 
    at Function.Module._load (module.js:438:3) 
    at Module.require (module.js:497:17) 
    at require (internal/module.js:20:19) 
    at Object.<anonymous> (C:\Users\XXXXXX\WebstormProjects\XXXX\index.js:10:20) 

Hier mein webpack.config.js ist:

const path = require('path'); 


module.exports = { 
    entry: path.join(__dirname, '/client/src/app.jsx'), 
    output: { 
     path: path.join(__dirname, '/client/dist/js'), 
     filename: 'app.js', 
     publicPath: "/" 
    }, 

    module: { 
     loaders: [{ 
      test: /\.jsx?$/, 
      include: [ 
       path.join(__dirname, '/client/src'), 
       path.join(__dirname, '/server/routes') 

     ], 
      loader: 'babel-loader', 
      query: { 
       babelrc: false, 
       presets: ['es2015', 'stage-2', 'react'] 
      } 
     }], 
    }, 

    devServer: { 
     historyApiFallback: true 
    }, 
    watch: true 
}; 

Nun ist die /server/routes/auth.jsx Datei:

const express = require('express'); 
const validator = require('validator'); 

const router = new express.Router(); 
const React = require('react'); 
const ReactDOMServer = require('react-dom/server'); 
const LoginPage = require('../../client/src/containers/LoginPage.jsx'); 


function validateLoginForm(payload) { 
    const errors = {}; 
    let isFormValid = true; 
    let message = ''; 

    if (!payload || typeof payload.email !== 'string' || payload.email.trim().length === 0) { 
     isFormValid = false; 
     errors.email = 'Please provide your email address.'; 
    } 

    if (!payload || typeof payload.password !== 'string' || payload.password.trim().length === 0) { 
     isFormValid = false; 
     errors.password = 'Please provide your password.'; 
    } 

    if (!payload || typeof payload.password !== 'string' || payload.password.trim().length <= 8) 
    { 
     isFormValid = false; 
     errors.password = 'Please provide a password that\'s more than 8 char'; 
    } 
    if (!isFormValid) { 
     message = 'Check the form for errors.'; 
    } 

    return { 
     success: isFormValid, 
     message, 
     errors 
    }; 
} 

router.post('/login', (req, res) => { 
    console.log("lol"); 
    const validationResult = validateLoginForm(req.body); 
    if (!validationResult.success) { 
     return res.status(400).json({ 
      success: false, 
      message: validationResult.message, 
      errors: validationResult.errors 
     }); 
    } 
    console.log("Went through validationResult without problems"); 
    return res.status(200).end(); 
}); 


router.get('/login', (req, res) => { 
    console.log(req.url); 
    return res.send(ReactDOMServer.renderToString(<LoginPage />)); // THE PROBLEM 
}); 

router.get('/', (req, res) => { 
    console.log(req.url); 
    console.log("lmao") 
}); 


module.exports = router; 

Schließlich ist /client/src/containers/LoginPage.jsx:

import React from 'react'; 
import LoginForm from '../components/LoginForm.jsx'; 


class LoginPage extends React.Component{ 

    /** 
    * Class constructor. 
    */ 
    constructor(props) { 
     super(props); 

     // set the initial component state 
     this.state = { 
      errors: {}, 
      user: { 
       email: '', 
       password: '' 
      } 
     }; 

     this.processForm = this.processForm.bind(this); 
     this.changeUser = this.changeUser.bind(this); 
    } 

    /** 
    * Process the form. 
    * 
    * @param {object} event - the JavaScript event object 
    */ 
    processForm(event) { 
     // prevent default action. in this case, action is the form submission event 
     event.preventDefault(); 

     const email = encodeURIComponent(this.state.user.email); 
     const password = encodeURIComponent(this.state.user.password); 
     const formData = `email=${email}&password=${password}`; 

     // create an AJAX request 
     const xhr = new XMLHttpRequest(); 
     xhr.open('post', '/login'); 
     xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 
     xhr.responseType = 'json'; 
     xhr.addEventListener('load',() => { 
      if (xhr.status === 200) { 
       // success 

       // change the component-container state 
       this.setState({ 
        errors: {} 
       }); 

       console.log('The form is valid'); 
      } else { 
       // failure 

       // change the component state 
       const errors = xhr.response.errors ? xhr.response.errors : {}; 
       errors.summary = xhr.response.message; 

       this.setState({ 
        errors 
       }); 
      } 
     }); 

     xhr.send(formData); 
    } 

    /** 
    * Change the user object. 
    * 
    * @param {object} event - the JavaScript event object 
    */ 
    changeUser(event) { 
     const field = event.target.name; 
     const user = this.state.user; 
     user[field] = event.target.value; 

     this.setState({ 
      user 
     }); 
    } 

    /** 
    * Render the component. 
    */ 
    render() { 
     return (
      <LoginForm 
       onSubmit={this.processForm} 
       onChange={this.changeUser} 
       errors={this.state.errors} 
       user={this.state.user} 
      /> 
     ); 
    } 

} 

export default LoginPage; 

Ich habe zuerst die path.join(__dirname, '/server/routes')10 hinzugefügt, um Webpack zu sagen und babel, auch nach diesem Ordner zu suchen, um jsx zu transpilieren, aber es scheitert, egal was.

I ersetzt return res.send(ReactDOMServer.renderToString(<LoginPage />)); in auth.jsx dann durch:

var html = ReactDOMServer.renderToString(React.createElement(LoginPage)); 
return res.send(ReactDOMServer.renderToString('base', html)); 

aber, indem Sie dies tun, gibt mir Knoten einen anderen Fehler, der ist:

C:\Users\XXXXXX\WebstormProjects\XXXX\client\src\containers\LoginPage.jsx:1 
(function (exports, require, module, __filename, __dirname) { import React from 'react'; 
                   ^^^^^^ 
SyntaxError: Unexpected token import 
    at createScript (vm.js:56:10) 
    at Object.runInThisContext (vm.js:97:10) 
    at Module._compile (module.js:542:28) 
    at Object.Module._extensions..js (module.js:579:10) 
    at Module.load (module.js:487:32) 
    at tryModuleLoad (module.js:446:12) 
    at Function.Module._load (module.js:438:3) 
    at Module.require (module.js:497:17) 
    at require (internal/module.js:20:19) 
    at Object.<anonymous> (C:\Users\XXXXXX\WebstormProjects\XXXX\server\routes\auth.jsx:8:19) 

, die wiederum ist ein transpiling Problem .

Beachten Sie, dass ohne diese Route in auth.jsx, funktioniert die Web App alles gut, außer dass ich nicht über URL zugreifen/einloggen kann.

Was mache ich falsch?

Ich verwende die neuesten Versionen von Express, React, React Router und Node. Mein Betriebssystem ist Windows 7.

Vielen Dank im Voraus

+0

es das 'webpack.config.js', dass Sie zeigen, nicht die' package.json' beheben inspirieren kann, ist nicht es? – atomrc

+0

@atomrc ups, korrigiert. Danke :) –

+0

könnte sein, weil .jsx-Datei enthält und nicht-es2015 Code, den Webpack nicht lesen kann –

Antwort

2

Ich glaube, ich weiß, was das Problem hier ist.

Sie tatsächlich Ihre jsx Datei kompilieren und Ihre webpack.config.js scheint perfekt (es enthält react Presets, so sollte es funktionieren).

Aber Sie kompilieren nur für die client es scheint, und Sie versuchen, die nicht kompilierte Datei auf dem Server zu konsumieren.

Aber node kann nicht lesen jsx für sich.

Die Option würde ich hier vorschlagen, damit babel auch serverseitige Dateien kompilieren kann.

Um dies zu tun, können Sie babel-cli verwenden.

einfach fügen Sie diese in Ihrem package.json

"scripts": { 
    "start": "babel-node index.js --presets es2015,react" 
} 

und starten Sie Server wie dieser

npm start

Dann sollte es zuerst die Dateien mit babel kompilieren und Server starten.

Hier ist ein Beispiel, das Sie vom https://github.com/babel/example-node-server

Dies sollte Ihr Problem

+0

Vielen Dank für Ihre Antwort. Der zweite Teil des Codes, den du gepostet hast, löste tatsächlich die erste Ausgabe, nämlich das 'Unexpected Token <'. Der erste Teil des Codes sollte das zweite Problem beheben, 'Unexpected token import', außer dass ich neu in React und Javascript im Allgemeinen bin, also weiß ich nicht, wie man Webpack mehrere Dateien gleichzeitig kompiliert. Soll ich das tun, was hier gesagt wird: https://webpack.github.io/docs/multiple-entry-points.html? –

+0

Ich habe meine Antwort aktualisiert. Diese Lösung sollte beide Ihre Probleme beheben, ohne irgendwelche Bits in irgendeiner Ihrer Quelldateien zu ändern :) – atomrc

+0

Sorry für den doppelten Kommentar, aber versucht, node-jsx und immer noch den gleichen Fehler zu installieren, aber anders geschrieben: 'Fehler bei der Umwandlung von C: \ Users \ XXXXXX \ WebstormProjects \ XXXX \ client \ src \ components \ LoginPage.jsx zu JS: Fehler: Parse Fehler: Zeile 1: Illegale Import-Deklaration ', die mir das Gefühl gibt, dass der Fehler durch meinen Code provoziert wird, egal wie oft ich lese es, ich kann nicht finden, wo der Fehler ist. –

Verwandte Themen