Webpack & Babel : Server Side rendering of React Component "Unexpected token '<'" - node.js

I've been investigating this issue for 3 days now but cannot get it working.
The full error is :
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)
Here is my webpack.config.js :
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
};
Now the /server/routes/auth.jsx file :
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;
Finally the /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;
I first added the path.join(__dirname, '/server/routes') in order to tell Webpack and babel to also search for this folder to transpile jsx, but it fails no matter what.
I then replaced return res.send(ReactDOMServer.renderToString(<LoginPage />)); in auth.jsx by :
var html = ReactDOMServer.renderToString(React.createElement(LoginPage));
return res.send(ReactDOMServer.renderToString('base', html));
but, by doing this, node gives me another error which is :
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)
which is, again, a transpiling problem.
Note that without that route in auth.jsx, the web App works all fine, except that I can't access /login via URL.
What am I doing wrong ?
I'm using the latest versions of Express, React, React Router and Node. My OS is Windows 7.
Thanks in advance

I think I know what is the problem here.
You indeed compile your jsx file and your webpack.config.js seems perfect (it includes react presets, so it should work).
But you are only compiling for the client it seems, and you are trying to consume the uncompiled file on the server.
But node cannot read jsx on its own.
The option I would suggest here, it to allow babel to also compile server side files.
To do that, you can use babel-cli.
Simply add this in your package.json
"scripts": {
"start": "babel-node index.js --presets es2015,react"
}
And start you server like this
npm start
Then it should first compile the files with babel and start your server.
Here is an example you can inspire from https://github.com/babel/example-node-server
This should fix your problem

Related

NestJS Error: Error:Cannot find module './'

I encountered a error when using NestJS. The console shows 0 error first and then crahsed with the Error: Cannot find module './'. This is similar to the
Error:Cannot find module '../module_name'.
However, for this one, it shows './'. And I tried to delete the node_module and the dist folder and rerun the npm install that was usually used to solve the similar people.
The full error message is:
[6:32:11 PM] Starting compilation in watch mode...
[6:32:14 PM] Found 0 errors. Watching for file changes.
Error: Cannot find module './'
Require stack:
- C:\Users\Vibrant\Desktop\inventory_demo\dist\client\client.service.js
- C:\Users\Vibrant\Desktop\inventory_demo\dist\client\client.controller.js
- C:\Users\Vibrant\Desktop\inventory_demo\dist\client\client.module.js
- C:\Users\Vibrant\Desktop\inventory_demo\dist\app.module.js
- C:\Users\Vibrant\Desktop\inventory_demo\dist\main.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (C:\Users\Vibrant\Desktop\inventory_demo\src\client\client.service.ts:3:1)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
The client.service.js:
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientService = void 0;
const common_1 = require("#nestjs/common");
const client_1 = require("./");
let ClientService = class ClientService {
async client(clientWhereUniqueInput) {
return client_1.default.client.findUnique({
where: clientWhereUniqueInput,
});
}
async clients(params) {
const { skip, take, cursor, where } = params;
return client_1.default.client.findMany({
skip,
take,
cursor,
where,
});
}
async createClient(data) {
return client_1.default.client.create({ data });
}
async deleteClient(where) {
return client_1.default.client.delete({ where });
}
async getClientByID(id) {
return await client_1.default.client.findUnique({
where: { client_id: Number(id) },
});
}
async updateClient(params) {
const { where, data } = params;
return client_1.default.client.update({ where, data });
}
};
ClientService = __decorate([
(0, common_1.Injectable)()
], ClientService);
exports.ClientService = ClientService;
//# sourceMappingURL=client.service.js.map
I have two ts files has client in the name:
First one is called client.ts which is a prism database client:
import { PrismaClient } from '#prisma/client';
interface CustomNodeJsGlobal extends NodeJS.Global {
prisma: PrismaClient;
}
// Prevent multiple instances of Prisma Client in development
declare const global: CustomNodeJsGlobal;
const prisma = global.prisma || new PrismaClient();
if (process.env.NODE_ENV === 'development') global.prisma = prisma;
export default prisma;
The second one is a model called client, it only imports the basic nestjs modules I think.
The client module.ts
import { Module } from '#nestjs/common';
import { ClientController } from './client.controller';
import { ClientService } from './client.service';
#Module({
controllers: [ClientController],
providers: [ClientService]
})
export class ClientModule {}
The client controller(haven't start it yet):
import { Controller } from '#nestjs/common';
#Controller('client')
export class ClientController {}
and the client service:
import { Injectable } from '#nestjs/common';
import { Client, Prisma } from '#prisma/client';
import prisma from 'src/client';
#Injectable()
export class ClientService {
// The service to return a single client
async client(
clientWhereUniqueInput: Prisma.ClientWhereUniqueInput,
): Promise<Client> {
return prisma.client.findUnique({
where: clientWhereUniqueInput,
});
}
// The service to return a list of clients
async clients(params: {
skip?: number;
take?: number;
cursor?: Prisma.ClientWhereUniqueInput;
where?: Prisma.ClientWhereInput;
}): Promise<Client[]> {
const { skip, take, cursor, where } = params;
return prisma.client.findMany({
skip,
take,
cursor,
where,
});
}
// The service to create a client
async createClient(data: Prisma.ClientCreateInput): Promise<Client> {
return prisma.client.create({ data });
}
// The service to delete a client
async deleteClient(where: Prisma.ClientWhereUniqueInput): Promise<Client> {
return prisma.client.delete({ where });
}
// The service to find an client by id
async getClientByID(id: string) {
return await prisma.client.findUnique({
where: { client_id: Number(id) },
});
}
// The service to update a client
async updateClient(params: {
where: Prisma.ClientWhereUniqueInput;
data: Prisma.ClientUpdateInput;
}): Promise<Client> {
const { where, data } = params;
return prisma.client.update({ where, data });
}
// End of class
}
The problem is I used a model called client.
The solution is to rename it to clients since NestJS itself uses the name client. After the name modification, I will need to delete the whole dist folder and run npm rebuild.

Jest mock a const

I want to test a js file where it has a reference of a const coming from another import (parser.js)
const { cp } = CML
How can I mock this and only this and not the rest of functions?. It is throwing this error:
ReferenceError: CML is not defined
at Object.<anonymous> (src/state/lib/parser.js:2:16)
at Object.<anonymous> (src/state/reducers/stateReducer.js:2:1)
at Object.<anonymous> (src/state/reducers/index.js:4:1)
at Object.<anonymous> (src/state/store/index.js:4:1)
at Object.<anonymous> (src/state/store/store.spec.js:4:1)
CML is a var defined in other js resource file.
This is the parser.js file:
/* global CML */
const { cp } = CML;
// Massaging approvals array data
// Adding status and trimming unused values
export default {
approvals: (approvals = [], globalActions = []) => (
approvals.map(approval => {
let status = 'default';
let rejected = false;
let reviewed = 0;
...
And in stateReducer class this is the import of the parser:
import parser from '../lib/parser';
jest.mock('./state/lib/parser', function() { // Put the exact path you've imported in your file
return {
CML: 123,
};
});

Rollup Creating Undefined Variable

I am trying to use a grunt rollup plugin, grunt-rollup, to compile two es6 files into Javascript that can be run from node and eventually the browser. Currently, it compiles, but rollup seems to be creating an undefined variable from one of my class names. Here is my current configuration.
Imported ES6 File (src/base.js):
class Base{
constructor() {
return this;
}
}
export default Test;
Rollup Entrypoint ES6 File (src/test.js):
import Base from "./base";
class Test extends Base{
constructor() {
super();
return this;
}
}
export default Test;
Gruntfile.js
module.exports = function(grunt) {
var babel = require('rollup-plugin-babel');
var resolve = require('rollup-plugin-node-resolve');
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
rollup: {
options: {
sourceMap: true,
format: 'cjs',
plugins: function () {
return [
resolve({
// pass custom options to the resolve plugin
customResolveOptions: {
moduleDirectory: 'node_modules'
}
}),
babel({
exclude: './node_modules/**',
presets: ['es2015-rollup']
}),
];
},
},
main: {
dest: 'dest/bundle.js',
src: 'src/test.js'
}
},
uglify: {
main: {
options: {
sourceMap: true,
sourceMapName: 'dest/bundle.min.js.map'
},
files: {
'dest/bundle.min.js': ['dest/bundle.js']
}
}
}
});
grunt.loadNpmTasks('grunt-rollup');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['rollup', 'uglify']);
};
Output file (dest/bundle.js)
'use strict';
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var Test$1 = function (_Base) {
inherits(Test$$1, _Base);
function Test$$1() {
var _ret;
classCallCheck(this, Test$$1);
var _this = possibleConstructorReturn(this, (Test$$1.__proto__ || Object.getPrototypeOf(Test$$1)).call(this));
return _ret = _this, possibleConstructorReturn(_this, _ret);
}
return Test$$1;
}(Test);
module.exports = Test$1;
//# sourceMappingURL=bundle.js.map
Terminal output
Output after running node dest/bundle.js.
/Users/christianjuth/Desktop/mb-problems/dest/bundle.js:67
}(Test);
^
ReferenceError: Test is not defined
at Object.<anonymous> (/Users/christianjuth/Desktop/mb-problems/dest/bundle.js:67:3)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Function.Module.runMain (module.js:605:10)
at startup (bootstrap_node.js:158:16)
at bootstrap_node.js:575:3
The problem seems to be with the very end of bundle.js where }(Test); is looking for an undefined variable. As far as I can tell this is not a bug with my code. It seems to be an issue with how rollup is compiling the ES6.
That's because you have an undefined variable in your code. Take a second look at base.js:
class Base{
constructor() {
return this;
}
}
export default Test;
...where have you defined Test? Did you mean export default Base?

node.js simple project: ReferenceError: <ClassName> is not defined

I try to learn Node.js (ES6) but fail on require
This is my structure:
baseModel.js
"use strict";
class BaseModel {
constructor(options = {}, data = []) { // class constructor
this.name = 'Base'
this.url = 'http://azat.co/api'
this.data = data
this.options = options
}
getName() { // class method
console.log(`Class name: ${this.name}`)
}
}
AccountModel.js
"use strict";
require('./baseModel.js');
class AccountModel extends BaseModel {
constructor(options, data) {
super({private: true}, ['32113123123', '524214691']) //call the parent method with super
this.name += 'Account Model'
this.url +='/accounts/'
}
get accountsData() { //calculated attribute getter
// ... make XHR
return this.data
}
}
main.js
"use strict";
require('./AccountModel.js');
let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData);
Now I run: node --harmony-default-parameters main.js
and get error:
ReferenceError: BaseModel is not defined
at Object. (/Users/tamirscherzer/POC/projects/NodeJS/tutorials/classes/AccountModel.js:5:28)
at Module._compile (module.js:397:26)
at Object.Module._extensions..js (module.js:404:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at Object. (/Users/tamirscherzer/POC/projects/NodeJS/tutorials/classes/main.js:5:1)
at Module._compile (module.js:397:26)
at Object.Module._extensions..js (module.js:404:10)
Really strange, if I change require('./baseModel.js'); to other name, I get error that file not found so the path is written properly.
Also defined permissions 777 - same thing, BaseModel is not defined
Any Ideas?
When you define a variable in Node, it isn't added to the global scope like it would be in a browser - it's local to that one file/module. Therefore, you can't simply import a file and expect the things you defined inside it to be available - you explicitly have to export and import them.
BaseModel.js:
class BaseModel {
constructor(options = {}, data = []) { // class constructor
this.name = 'Base'
this.url = 'http://azat.co/api'
this.data = data
this.options = options
}
getName() { // class method
console.log(`Class name: ${this.name}`)
}
}
module.exports = BaseModel;
AccountModel.js:
"use strict";
let BaseModel = require('./baseModel.js');
class AccountModel extends BaseModel {
constructor(options, data) {
super({private: true}, ['32113123123', '524214691']) //call the parent method with super
this.name += 'Account Model'
this.url +='/accounts/'
}
get accountsData() { //calculated attribute getter
// ... make XHR
return this.data
}
}
module.exports = AccountModel;
main.js:
"use strict";
let AccountModel = require('./AccountModel.js');
let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData);

Protractor addLocator : how to get the object for the document

Im trying to create a custom locator in protractor using addLocator
My conf.js is
// An example configuration file.
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
//multiCapabilities: [{
// browserName: 'firefox'
// }, {
// browserName: 'chrome'
//}],
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['DriverSpec.js'],
onPrepare: function () {
require('tech')(protractor);
}
//function (protractor) {
protractor.by.addLocator('test', function (toState, opt_parentElement) {
var using = opt_parentElement || document;
var possibleAnchors = using.querySelectorAll( toState );
var result = undefined;
if (possibleAnchors.length === 0) {
result = null;
} else if (possibleAnchors.length === 1) {
result = possibleAnchors[0];
} else {
result = possibleAnchors;
}
return result;
});
//};// The protractor object is available here.
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 1000000
}
};
Error shown :
C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\protractor\conf\addLocator\Ne
w folder\conf.js:18
By.addLocator('customLink',
^
SyntaxError: Unexpected token .
at Module._compile (module.js:439:25)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at ConfigParser.addFileConfig (C:\Users\jeevan.s\AppData\Roaming\npm\node_mo
dules\protractor\lib\configParser.js:183:20)
at Object.init (C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\protracto
r\lib\launcher.js:35:18)
at Object.<anonymous> (C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\pr
otractor\lib\cli.js:129:23)
at Module._compile (module.js:456:26)
Issues :
1) How to create a Protractor object
2) Trying to build object opt_parentElement by using this code lines
var using = browser.driver.findElement(By.css(".nav"));
buttons = using.querySelectorAll('active')
Its throwing the error as the "querySelectorAll" not found in the "using OBJECT"
Not able to access querySelectorAll method.
3). Could anyone can please help us addLocator with executable example. It would be great!!

Resources