BABEL - How to do to separate ES6 modules and non-ES6 modules? - javascript

I have gulpfile.babel.js:
function javascript() {
return gulp.src(PATHS.javascript)
.pipe($.sourcemaps.init())
.pipe($.babel())
.pipe($.concat('app.js'))
.pipe($.if(PRODUCTION, $.uglify()
.on('error', e => { console.log(e); })
))
.pipe($.if(!PRODUCTION, $.sourcemaps.write()))
.pipe(gulp.dest(PATHS.dist + '/assets/js'));
}
Config.xml
PATHS:
# Paths to JavaScript libraries, which are compined into one file
javascript:
- "node_modules/gsap/src/uncompressed/TweenMax.js"
- "bower_components/scrollmagic/scrollmagic/uncompressed/ScrollMagic.js"
I need to do for this:
- 1 Answer of Stackoverflow
When using Babel 6 and babel-preset-es2015 (or Babel 5), Babel by default assumes that files it processes are ES6 modules. The thing that is causing you trouble is that in an ES6 module, this is undefined, whereas in the "script" case, this varies depending on the environment, like window in a browser script or exports in CommonJS code.
For this problem:
Uncaught TypeError: Cannot set property '[any AMD]' of undefined

Related

Gulp concat, uglify handling ES6 exported libraries

I use Gulp to merge a few javascripts as well as uglify them. When I tried to do it with countUp (can be other script as well) I've got an error.
Uncaught SyntaxError: Unexpected token 'export'
It tries to export the javascript back to the script tag. Now my javascript file is not just one script, but many.
How can I make it work? Is there a tool to convert it to common js or maybe a better way to include it with gulp?
Script
A part of my gulp-file looks like below:
function script() {
return gulp
.src(js.src)
.pipe(concat(js.filename))
.pipe(gulp.dest(js.dest))
.pipe(uglify())
.pipe(rename({ extname: ".min.js" }))
.pipe(gulp.dest(js.dest));
}
You can use a gulp task to convert es6 modules to other types:
const babel = require('gulp-babel'),
gulp.task('es6-commonjs',['clean-temp'], function(){
return gulp.src(['app/*.js','app/**/*.js'])
.pipe(babel({ modules: 'common' }))
.pipe(gulp.dest('dest/temp'));
});
Then use this task in your gulp pipe. More info here.

Transpile a bunch of ES7 js files into compatible files

I have a folder with a bunch of javascript. I want to be able to use recent js syntax (especially await/async). But the target should compatible with most browsers.
Since these javascript files will be used standalone (will be imported in a 3rd party app as plugin), I want to respect these scheme:
src/file1.js ==> dist/file1.js
src/sub/file2.js ==> dist/sub/file2.js
...
each files should be transpiled into a es5 js file.
I'm using gulp 4 as build tool.
How to reach my goal ?
First try : use babel-gulp:
import gulp from 'gulp';
import sourcemaps from 'gulp-sourcemaps';
import babel from 'gulp-babel';
const javascript = () => {
return gulp.src('src/**/*.js')
.pipe(sourcemaps.init())
.pipe(babel({
"presets": [
["#babel/preset-env", {
"targets": {
"browsers": [">0.25%", "not ie 11", "not op_mini all"]
}
}]
]
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist'));
};
The build succeeds, but at runtime, it fails with ReferenceError: regeneratorRuntime is not defined
Second try, using browserify and #babel/polyfill, inspired from Browserify + Globs (multiple destination)
Added require("#babel/polyfill"); at top of my javascript files.
in gulp file:
const javascript2 = () => {
return gulp.src('src/**/*.js', {
read: false
}) // no need of reading file because browserify does.
.pipe(tap(function(file) {
file.contents = browserify(file.path).bundle();
}))
.pipe(buffer())
.pipe(sourcemaps.init({
loadMaps: true
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'));
};
The build succeed, but the file is not transpiled (async keywords remain) and moreover, the whole babel polyfills are included in the output (and it's quite big) which conflicts with the target app (the app is also redefining startsWith function).
It looks like you are trying to set up a development environment. I would suggest using webpack instead of gulp, 'cause it's more relevant these days. Here's the guide I used to set one up: https://www.valentinog.com/blog/webpack-tutorial/.

es2015 preset issue with moment

I'm using gulp-babel to transpile es6, below is the gulp task
gulp.task('uglify', [], function() {
var notMinified = config.scripts.src;
notMinified.push('!javascripts/*.min.js');
// console.log(notMinified);
return gulp.src(notMinified)
.pipe(babel({
"presets": ["es2015-without-strict"]
}))
.pipe(ngAnnotate())
.pipe(gp_uglify().on('error', function(e) {
console.log(e);
}))
.pipe(gulp.dest(config.scripts.dest));
});
I have tried presets es2015, es2015-without-strict etc.
While using es2015 preset, there was an error in moment.js which says 'cannot set moment of undefined'. After googling the error I found es2015 preset uses use strict at top level which converts this to undefined, hence the error in moment. So I used es2015-without-strict preset which says it transpiles without use strict but still no luck, having same error.
What could be possibly wrong here?

How to solve this minification error on Gulp?

I'm getting below error running this command
gulp.task('minify', function () {
return gulp
.src('public/app/js/myapp.bundle.js')
.pipe(uglify())
.pipe(gulp.dest('public/app/js/myapp.bundle.min.js'));
});
GulpUglifyError: unable to minify JavaScript Caused by: SyntaxError: Unexpected token: name (MenuItem) (line: 1628, col: 18, pos: 53569)
Code on that location is this
setters: [],
execute: function () {
class MenuItem { // <-- line 1628
What's wrong?
UglifyJS does not currently support EcmaScript 6 structures like classes.
You'll probably need to run your JavaScript through a transpiler step first, or find a minifier that knows what to do with ES6 code.
Update 2017-06-17
The branch of UglifyJS that is designed to work with ES6 is now published as uglify-es on npm.
Update 2018-09-10
terser is the new uglify-es, uglify-es is no longer maintained.
If using gulp both npmjs gulp-uglify-es and npmjs gulp-terser packages support terser.
npm install gulp-terser --save-dev
const gulp = require('gulp');
const terser = require('gulp-terser');
function es(){
return gulp.src('./src/index.js')
.pipe(terser())
.pipe(gulp.dest('./build'))
}
gulp.task('default', es);
If you run into this problem and you have in fact a transpiler step like Babel, make sure that you include the proper Babel preset in you .babelrc file. Otherwise Babel will simply leave your code as is.
E.g.
{
"presets": ["es2015"]
}

How to use both 'gulp-babel' and 'gulp-browserify'

I try to write these code
gulp.task('script', function() {
'use strict'
return gulp.src(['app.js', 'components/**/*.jsx'])
.pipe(babel())
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
but it shows some error:
SyntaxError:
/Users/Zizy/Programming/learn-react-js/components/CommentBox.jsx:58
<div className="commentBox">
^
ParseError: Unexpected token
at wrapWithPluginError (/Users/Zizy/Programming/learn-react-js/node_modules/gulp-browserify/index.js:44:10)
It seems that before .pipe(browserify()) the gulp did't transform the jsx code. But if I just remove .pipe(browserify()) I find that did transform, just cannot let babel and browserify work together.
I know maybe I can use like babelify or browserify plugin for babel though, I just want figure out the reason.
gulp-browserify doesn't quite work like that. You don't give it a bunch of buffers to collect and bundle.
You give it one file—the entry file—which it passes into Browserify. Browserify checks to see what other files the entry file references, then loads those files directly from the file system, meaning that you can't modify them with gulp plugins beforehand.
So, really, if we pretend you don't want to use Babel on your source files, your gulpfile should look like this, only passing in the entry file:
gulp.task('script', function() {
'use strict'
return gulp.src('app.js')
.pipe(browserify())
.pipe(gulp.dest("dist"));
});
However, note that gulp-browserify is no longer maintained, and this is exactly why. gulp plugins aren't supposed to read directly from the file system. That's why you're supposed to use Browserify (or, in your case, Babelify) directly with vinyl-source-stream as recommended in the gulp recipes. It's more idiomatic and less confusing.
That wraps up my answer to your question, but I'd like to add: if you're using the ES2015 module syntax (and you probably should be), there's a better way to do this. Browserify wraps all your modules separately in a bunch of code to make the programmatic CommonJS API work properly, but ES2015 modules have a declarative syntax, which makes it much easier for tools to operate on them statically. There's a tool called Rollup that takes advantage of this, allowing it to produce bundles that are smaller, faster, and more minfication-friendly than Browserify's.
Here's how you might use it with gulp:
var gulp = require('gulp'),
rollup = require('rollup-stream'),
babel = require('gulp-babel'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer');
gulp.task('script', function() {
return rollup({entry: 'app.js'})
.pipe(source('app.js'))
.pipe(buffer())
.pipe(babel())
.pipe(gulp.dest('dist'));
});
Starting from Babel 6 you need to declare the presets manually, check this.
Basically, in the root of your project you need a .babelrc with the following content:
{
"presets": [ "es2015", "react" ]
}
And the corresponding npm modules in package.json:
// package.json
{
"devDependencies": {
...
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18",
...
}
}
Here is a sample repository with gulp, babel and browserify
Following is the code snippet
gulp.task("js", (done) => {
const bundler = browserify({ entries: paths.js.source }, { debug: true }).transform(babel);
bundler.bundle()
.on("error", function (err) { console.error(err); this.emit("end"); })
.pipe(source(paths.build.destMinJSFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write(paths.js.destMapFolder))
.pipe(gulp.dest(paths.build.destBuildFolder));
done();
});

Categories

Resources