Rollup Creating Undefined Variable - node.js

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?

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.

Webpack & Babel : Server Side rendering of React Component "Unexpected token '<'"

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

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);

System.js builder.buildStatic just outputs the filename

I have just simplified the source file to below, which works fine when I use System.import in a script tag.
import angular from "angular";
angular.element(document).ready(function () {
alert('Hello word');;
});
Below is my config.js
System.config({
baseURL: "/",
defaultJSExtensions: true,
transpiler: "typescript",
paths: {
"npm:": "jspm_packages/npm/"
},
map: {
"angular": "npm:angular#1.5.2",
"typescript": "npm:typescript#1.8.9"
}
});
I have a gulp task to build it:
gulp.task('bundle:js', ['clean:js'], function () {
var builder = new Builder();
builder.loadConfig('./config.js').then(function () {
var destination = paths.coreJsDest;
builder.buildStatic(paths.srcRoot + 'js/ng/homepage', destination, {
minify: false,
sourceMaps: false,
runtime: false
});
});
});
But the output file contains the file name rather than JavaScript from the file and its imports:
(["1"], ["1"], function($__System) {
})
(function(factory) {
if (typeof define == 'function' && define.amd)
define(["D:/Projects/etc-etc/assets/js/ng/homepage.js"], factory);
else if (typeof module == 'object' && module.exports && typeof require == 'function')
module.exports = factory(require("D:/Projects/etc-etc/js/ng/homepage.js"));
else
throw new Error("Module must be loaded as AMD or CommonJS");
});
Doh, I just needed to change the baseUrl from "/" to "./".

require.js listener or callback

I am loading a 3rd party script that simply creates an overlay on a site it has been loaded onto. It works fine but sites using require.js seem to have intermittent issues I'm assuming with async loading some js files. Is there any type of callback or way to create a module in the DOM as sort of a listener to see if require.js is done loading?
I tried this but not even close:
define(function() {
alert('test');
return {};
});
and
define('myModule',
function () {
var myModule = {
doStuff:function(){
console.log('Yay! Stuff');
}
};
return myModule;
});
console.log(myModule);
I ended up just creating a secondary require.config file and loading the module with require if require is detected, seems to work fine.
if(typeof require === 'function') {
var base = 'http://' + someDomainVar;
function getJSTreeURL() {
var url = base + '/js/libs/jstree.min';
return url;
}
function getModuleURL() {
var url = base + '/module';
return url;
}
var reqTwo = require.config({
context: "instance2",
baseUrl: "instance2",
paths: {
'jq': 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
'jqTree': getJSTreeURL(),
'module': getModuleURL()
},
shim: {
'jq': {
exports: 'jq'
},
'jqTree': {
deps: ['jq'],
exports: 'jqTree'
},
'module': {
deps: ['jq', 'jqTree'],
exports: 'module'
}
}
});
reqTwo(['require', 'jq', 'jqTree'],
function(require, jq, jqTree) {
setTimeout(function() {
require(['module'],
function(module) {
console.log('loaded');
}
);
}, 0);
});

Resources