Grunt-terser failing to minify React JSX code on Sails - reactjs

I am using browserify with babelify to transpile React code from ES6 and everything went smoothly until trying to minify using Uglify and discovered that Uglify doesn't do ES6 syntax, so I switched to terser through grunt-terser but I cannot seem to find the appropriate options needed to minify React code and so I get the error "Unexpected token operator (<)" on basic React syntax when trying to use ReactDOM.render inside of my bundled javascript file.
The only other solutions I am seeing around the web is to switch from grunt to webpack but I don't want to make such a change and it not work, is there any way to make this work with terser and/or grunt?
module.exports = function(grunt) {
grunt.config.set('terser', {
dist: {
src: ['.tmp/public/concat/production.js'],
dest: '.tmp/public/js/app.js'
},
options: {
ecma: 6,
parse: {
ecma: 6,
module: true,
toplevel: true,
},
mangle: {
module: true,
keep_fnames: false,
toplevel: true
},
compress: {
unsafe_comps: true
}
}
});
grunt.loadNpmTasks('grunt-terser');
};
I have tried several different options to try and minify and all give the same error.

Related

Laravel mix & react - Module build failed on inline import

I seem to be having an issue when building my frontend using Laravel mix.
I'm using react-loadable for loading components with promises, as for routing I make use of a declarative config file:
export default [
{
path: '/clients',
exact: true,
auth: true,
component: Loadable({
loader: () => import('./screens/index'),
loading: LoadingComponent,
}),
},
]
When building the js files, I get following error (pointing to the 'i' of import):
ERROR in ./resources/js/modules/clients/routes.js Module build failed:
SyntaxError: Unexpected token (10:26)
When searching the web I came across the fact that, when you wanted to use arrow functions or class properties, you'd need to add a Babel plugin (babel-plugin-transform-class-properties).
So I did add a .babelrc file with following config (it also seems that laravel-mix would automatically make use of the babelrc file):
{
"plugins": ["transform-class-properties"]
}
Still no success.
Any ideas?
Try adding this to your .babelrc file:
{
"presets": [
["es2016"],
"react"
],
"plugins": [
"babel-plugin-transform-class-properties"
]
}

Webpack 4: Production mode fails for React Library

I'm trying to build my react library however it fails on mode: production. When I import my library to another application I get the following message:
Uncaught TypeError: Cannot set property props of #<TWithProps> which has only a getter.
Followed by:
The above error occurred in the <_class3> component
The problem is that it does seem to bundle up my library, however when importing the bundled libary, I get the 2 errors above. Additionally This does not happen in development mode.
I tried following many guides, however they all lead to the same result. My first assumption is that it's likely due to my minimizer plugin (I've tried both UglifyPlugin and TerserPlugin) however that is not the case. I've also read on webpack's documentation that it should use the minimizing plugin if given one. However it doesn't seem like it?
This is my webpack
module.exports = {
mode: 'production',
entry: {
index: [
'babel-polyfill',
'./src/index.js',
],
},
output: {
path: srcBuild,
filename: '[name].js',
chunkFilename: '[name].[chunkhash].js',
libraryTarget: 'commonjs',
libraryExport: 'default',
},
optimization: {
noEmitOnErrors: true,
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true,
terserOptions: {
mangle: false,
compress: {
reduce_funcs: false,
reduce_vars: false,
keep_classnames: true,
keep_fnames: true,
keep_fargs: true,
pure_getters: true,
},
},
}),
],
}
I'm expecting my library to run just fine as it does in mode: development.
May I ask how are you consuming your library from the other application? You have libraryTarget: 'commonjs' in your config. If you don't know how your clients will consume your library, the suggested option is to set the export to umd by setting libraryTarget: 'umd'.
This should allow you to use ES6 import or just require it, webpack or the other app's bundler will take care of resolving them.
Solved it by adding this plugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),

ESLint global vars included via <script> are causing undefined error

My react app is bundled with WebPack and it uses global scripts (e.g. jQuery) that are included via tags and are defined in WebPack externals.
But my ESLint configuration doesn't know about them and i get 'no-unded' error in ESLint.
So how can i tell ESLint that those are not undefined vars, or should i change my WebPack config somehow?
Did you tried adding globals in .eslintric.js config file
module.exports = {
"env": {
"browser": true,
"node": true
},
"globals": {
"SomeVar": true
},
};

Can I use an Angular es5 controller with a new es6 service using babel and grunt?

I want to start using ES6 (2015) in my Angular 1.3 + grunt stack without refactoring the entire existing ES5 code, (or switching grunt with other tool..)
But when trying to use a new ES6 service from an "old" controller I'm getting following error,
" Cannot read property '1' of null
at Function.annotate [as $$annotate] .... "
The babel configuration in grunt:
babel: {
options: {
sourceMap: true,
presets: ['es2015']
},
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>',
src: '**/*.es6.js',
dest: '.tmp/app',
ext: '.es5.js'
}]
},
test: {
files: [{
expand: true,
cwd: 'test/spec',
src: '{,*/}*.es6.js',
dest: '.tmp/spec',
ext: '.es5.js'
}]
}
},
The service code:
class InfoService {
constructor($http) {
this.$http = $http;
}
getInfo() {
console.log('getting');
return this.$http.get('/backend/something/readAll');
}
}
InfoService.$inject = ['$http'];
angular.module('app').service('Info', $http => InfoService($http));
The use in es5 controller:
angular.module('app').controller('SomeCtrl',
function ComposerCtrl(Info) {
Info.getInfo();
});
The transpiled ES5 InfoService was generated under .tmp/app (and I configured grunt watch to update changes while developing) so I wonder what am I doing wrong..
You have forgotten about new:
...
angular.module('app').service('Info', $http => new InfoService($http))
In this case, angular will not benefit from $inject property and you will need to ng-annotate your code, as it solves to:
angular.module('app').service('Info', function($http) { return new InfoService($http); });
The simpler solution it to replace service definition with:
angular.module('app').service('Info', InfoService);
Angular's DI will use $inject property and add new operator for you.
It is worth noting, that TypeScript users had the same problem:
How can I define an AngularJS service using a TypeScript class that doesn't pollute the global scope?
EDIT:
It is possible, that you are using wrong controller expression (for example unclosed ng-controller attribute:
<div .... ng-controller="SignupFormController as signupFormCtrl>
This messes up angular and leads to this error message on older versions of angular (1.3).
More info about issue:
https://github.com/angular/angular.js/issues/10875
So I've found a way to make it work but I don't like it so much..
I configured the babel to dist the files at the same place my *.es6.js files and updated the index.html so Angular will load the es5 transpiled file (InfoService.js), and when I debug I do it on the es6 file (I guess it relates to the sourceMap)
babel: {
options: {
sourceMap: true,
presets: ['es2015']
},
dist: {
files: [{
expand: true,
src: '**/*.es6.js',
ext: '.js'
}]
},

Grunt Typescript can't find angular core

Question
Why cant my Grunt Typescript compiler find the angular core?
I guess it has something to do with the paths so the compiler cant find the libs in the node_modules directory.
Error
typescript/add.component.ts(1,25): error TS2307: Cannot find module 'angular2/core'.
Setup
Gruntfile.js Task
typescript: {
all: {
src: ['typescript/**/*.ts'],
dest: 'javascript/frontend',
options: {
target: "es5",
module: "system",
moduleResolution: "node",
emitDecoratorMetadata: true,
experimentalDecorators: true,
removeComments: false,
noImplicitAny: false
}
}
typescript/add.component.ts
import {Component} from 'angular2/core';
#Component({
selector: 'mytest',
template: '<h1>test</h1>'
})
export class AppComponent { }
node_modules
Includes angular2
Includes typescript
Filepaths
app -- node_modules
-- typescript
-- app.component.ts
-- Gruntfile.js
-- package.json
Used libs/frameworks/tutorials
Grunt Typescript Github
Angular2 5min Quickstart
Just now I had the same exact problem. Running grunt in verbose mode showed the content of the ts config file it generated from the grunt config. Looking more closely, this revealed that the moduleResolution option isn't used at all. But, on the other hand, it wasn't described either on the official grunt-typescript page.
Anyway, long story short: I've used the grunt-ts package instead and everything worked out well! I've posted my config below for your convenience :-)
module.exports = function(grunt) {
grunt.initConfig({
ts: {
base: {
src: ['src/**/*.ts'],
dest: 'dist',
options: {
module: 'system',
moduleResolution: 'node',
target: 'es5',
experimentalDecorators: true,
emitDecoratorMetadata: true,
noImplicitAny: false
}
}
}
});
grunt.loadNpmTasks('grunt-ts');
grunt.registerTask('default', ['ts']);
};

Resources