Gulp Babel Async/Await - javascript

Trying to minify a file and run it directly on the browser.
I'm using gulp & babel to do. The problem relies when I try to use async/await functions.
package.json
{
"#babel/core": "^7.11.6",
"#babel/plugin-transform-async-to-generator": "^7.12.1",
"#babel/plugin-transform-runtime": "^7.12.1",
"#babel/preset-env": "^7.11.5",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-concat": "^2.6.1",
...
}
The file
const i = async () => {
return await fetchAll();
};
Gulp/Babel config
const BabelConfig = {
presets: ['#babel/env'],
plugins: ['#babel/plugin-transform-async-to-generator']
};
const imports = ['./dev/**.*.js'];
return gulp.src(imports)
.pipe(babel(BabelConfig))
.pipe(concat('min.js'))
.pipe(gulp.dest(paths.dist.js));
This simply threw "regeneratorRuntime is not defined".
So I've tried adding "#babel/plugin-transform-runtime".
Gulp/Babel config
const BabelConfig = {
presets: ['#babel/env'],
plugins: ['#babel/plugin-transform-async-to-generator', '#babel/plugin-transform-runtime']
};
const imports = ['./dev/**.*.js'];
return gulp.src(imports)
.pipe(babel(BabelConfig))
.pipe(concat('min.js'))
.pipe(gulp.dest(paths.dist.js));
But now I get "require is not defined".
Does any one have any clues on how to achieve this?

You're almost there! I had a similar issue, the problem is that the compiled Gulp code includes "require" statements which aren't supported in most browsers. What fixed the issue for me was to add Webpack to the Gulp workflow to bundle everything:
npm install --save-dev webpack webpack-cli webpack-stream
in your gulpfile.js:
const {src, dest, watch} = require('gulp');
const gulpBabel = require('gulp-babel');
const webpack = require('webpack-stream');
const compiler = require('webpack');
function myES6Transpiler() {
return src('./es6/utilities.js')
.pipe(gulpBabel({
presets: ['#babel/preset-env', 'babel-preset-minify'],
plugins: ['#babel/transform-runtime', '#babel/plugin-transform-async-to-generator'],
}))
.pipe(webpack(require('./webpack.config-util.js'), compiler, function (err, stats) {
/* Use stats to do more things if needed */
}))
.pipe(dest('./js/'))
}
exports.myES6Transpiler = myES6Transpiler;
You also need to add a Webpack config file:
webpack.config.js
module.exports = {
mode: "production",
output: {
filename: "utilities.js"
}
}

Related

Prevent Webpack from dropping my unused code

For example, my javascript file contains function that's only called when I press HTML button. As far as I know, Webpack will treat the function as a 'dead code' because it isn't used anywhere in javascript file and then dropped the code.
So, the question is how can I disable Webpack from dropping the dead code? (or any other way would also helpful)
For more information, I tried following this thread but still can't figure out how:
How to prevent unused code from being dropped during webpack build?
What I also already did was exporting everything inside index.js and import them in main.js along with other things like jquery and mathjs which then be compiled by Webpack. The output file has jquery, mathjs, and only console.log from main.js and general.js.
Even when I set the mode in development or none, the output file doesn't work at all.
// package.json
{
"private": true,
"devDependencies": {
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^4.2.2",
"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.7.2",
"purgecss-webpack-plugin": "^5.0.0",
"terser-webpack-plugin": "^5.3.6",
"uglify-js": "^3.17.4",
"uglifyjs-folder": "^3.2.0",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"dependencies": {
"jquery": "^3.6.3",
"mathjs": "^11.5.0"
}
}
Here's my webpack.config.js (though I don't think there's problem here):
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = [
{
mode: 'production',
module: {
rules: [
{
test: /.html$/i,
loader: "html-loader",
},
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
optimization: {
minimizer: [...,new CssMinimizerPlugin()]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.php'
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
],
},
]
Here's some part of the javascript file:
// main.js
import 'jquery';
import { evaluate } from 'mathjs';
console.log(evaluate('2+3'));
import js from './general.js';
// general.js
export let result;
export function clr() {
$('.input').text('0');
$('.result').text('0').removeClass('visible');
$('.input').addClass('highlight');
$('.result').removeClass('highlight');
return result = 0;
}
...
console.log('javascript loaded');
// output.js
// (...last part of the code, just to show that the javascript files are compiled successfully)
.......ImmutableDenseMatrix:Eb,Index:Ab,Spa:$b,Unit:Gb,SymbolNode:kN,FunctionNode:zN,Help:UN,Parser:GN}),FN.createProxy(hN),console.log("javascript loaded"),console.log($N("2+3"))})()})();
(I'm sorry if I can't explain it well. If there's something that I missing please let me know)

Connecting files via import does not work

For a day now, I can not understand why babel for gulp does not work for me, or I incorrectly connect the modules ...
The error in the browser is like this:
Uncaught ReferenceError: require is not defined
at main.min.js:1
I connect the modules like this:
import focusVisible from "focus-visible";
Code in main.min.js file:
"use strict";var e;(e=require("focus-visible"))&&e.__esModule;
Gulp task:
const { src, dest, series, watch, parallel } = require('gulp'),
fileinclude = require('gulp-file-include'),
rename = require("gulp-rename"),
uglify = require('gulp-uglify-es').default,
babel = require("gulp-babel"),
notify = require("gulp-notify"),
browserSync = require("browser-sync").create()
const changingScripts = () => {
return src(['src/js/main.js', 'src/js/pages/**/*.js'])
.pipe(babel())
.pipe(fileinclude())
.pipe(dest('dist/js'))
.pipe(uglify({
toplevel: true
}).on('error', notify.onError()))
.pipe(rename({
extname: '.min.js'
}))
.pipe(dest('dist/js'))
.pipe(browserSync.stream())
}
The package.json file is like this:
{
"name": "project_name",
"version": "1.0.0",
"description": "some description of the project",
"scripts": {},
"keywords": ["keyword_1", "keyword_2", "keyword_3"],
"author": "project_author",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.16.0",
"#babel/eslint-parser": "^7.16.3",
"#babel/preset-env": "^7.16.4",
"#babel/register": "^7.16.0",
"browser-sync": "^2.27.7",
"eslint": "^8.2.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.3",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-file-include": "^2.3.0",
"gulp-notify": "^4.0.0",
"gulp-rename": "^2.0.0",
"gulp-uglify-es": "^3.0.0"
}
}
The .babelrc file looks like this:
{
"presets": ["#babel/preset-env"]
}
It seems like everything has applied what is needed.
If you can help, I will be grateful.
The whole project got stuck because of this error ...
It is advisable to solve the problem without using Webpack :)
It seems like you could be missing a build step where you transform your code to be browser compatible. The require method is not available in the browser.
You have to use a tool which transforms your code so that it can be ran in the browser. One such tool is Browserify, another is rollup, and there may be more. These tools, generally speaking, bundle dependency sources in conjunction with your application code, which allows require statements to be transformed into some other pattern the browser does understand.
You can think of it like this (example is simplified):
Code written by you
// main.js
const stringify = require('stringify')
alert(stringify({ error: "No authorization" })
Dependency source in node_modules
// node_modules/stringify/index.js
function stringify(obj) {
return JSON.stringify(obj);
}
expost.default = stringify
Bundle result
// dist/main.js
function stringify(obj) {
return JSON.stringify(obj);
}
alert(stringify({ error: "No authorization" })
Gulp hosts an official example of usage in their repository for browserify:
'use strict';
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var log = require('gulplog');
var uglify = require('gulp-uglify');
var reactify = require('reactify');
gulp.task('javascript', function () {
// set up the browserify instance on a task basis
var b = browserify({
entries: './entry.js',
debug: true,
// defining transforms here will avoid crashing your stream
transform: [reactify]
});
return b.bundle()
.pipe(source('app.js', { sourcemaps: true }))
.pipe(buffer())
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', log.error)
.pipe(gulp.dest('./dist/js/', { sourcemaps: '../sourcemaps/' }));
});
Gulp Version control: Browserify + Transforms
I attempted to create an example for you, but it's difficult to say what the most usable gulp script would be for your project. I'll add an example, but please don't consider it as a fix that's ready for general use. It attempts to mimic the behaviour your current gulp script has. You may want other behaviour in the long run for instance because the bundling this script creates may not be as optimized as other configurations or tooling would allow.
const { dest } = require("gulp"),
browserify = require("browserify"),
babelify = require("babelify"),
glob = require("glob"),
source = require("vinyl-source-stream"),
fileinclude = require("gulp-file-include"),
rename = require("gulp-rename"),
uglify = require("gulp-uglify-es").default,
notify = require("gulp-notify"),
browserSync = require("browser-sync").create(),
es = require("event-stream");
const changingScripts = (done) => {
// Define files you want to have as inputs
var files = ["src/js/main.js", ...glob.sync("src/js/pages/**/*.js")];
// Bundle each file separately so that file structure is preserved in
// dist
var tasks = files.map((file) => {
return (
browserify({
entries: [file],
debug: true,
transform: [
// Apply babel transforms here so that browserify knows how to bundle
// the files
babelify.configure({
presets: ["#babel/preset-env"],
}),
],
})
.bundle()
// Transform the stream content bable bundling returns into a gulp
// friendly format
.pipe(source(file))
// Not sure how fileinclude is used in your project. May be that it
// doesn't work when it's configured in this way.
.pipe(fileinclude())
.pipe(dest("dist/js"))
.pipe(
uglify({
toplevel: true,
}).on("error", notify.onError())
)
.pipe(
rename({
extname: ".min.js",
})
)
.pipe(dest("dist/js"))
.pipe(browserSync.stream())
);
});
return es.merge(tasks).on("end", done);
};
exports.default = changingScripts;
Gulp: Creating multiple bundles with Browserify

Can't get babel-loader to add polyfill for String.prototype.trimLeft() (aka trimStart)

I'm bundling my javascript with webpack/babel-loader (with the #babel/preset-env "useBuiltIns: 'usage' " setting), and during compilation the String.prototype.trimStart() polyfill doesn't get added. I tried using its alternate name "trimLeft()," and still no luck. Is this a bug or am I doing something wrong?
I'm using Node on Mac, I have #babel/polyfill as a project dependency, and I have #babel/core, #babel/preset-env, and babel-loader as devDependencies (as well as webpack). My babel configurations are in my webpack.config.js file.
I'm running babel-loader in debug mode, so I can see which polyfills are being added to which modules; as far as I can tell, it's only trimLeft/trimStart that's a problem. As a result, running my app in IE throws an error.
From package.json:
"dependencies": {
"#babel/polyfill": "^7.2.5"
},
"devDependencies": {
"#babel/core": "^7.2.2",
"#babel/preset-env": "^7.3.1",
"babel-loader": "^8.0.5",
"webpack": "^4.29.1",
"webpack-cli": "^3.2.1"
}
From webpack.config.js (within module.exports.module.rules):
use: {
loader: 'babel-loader',
options: {
presets: [
['#babel/preset-env', {
useBuiltIns: 'usage',
debug: true,
targets: {
browsers: ['IE >= 10']
}
}]
]
}
}
From the module where I use String.prototype.trimLeft() (within a default export arrow function):
const messageInput = document.querySelector('#message-input');
const usernameInput = document.querySelector('#username-input');
messageInput.addEventListener('keydown', handleKeydown);
usernameInput.addEventListener('keydown', handleKeydown);
function handleKeydown(event) {
if (event.key === 'enter') {
const username = usernameInput.value.trim();
const text = messageInput.value.trimLeft();
// etc.
}
}
In browsers that support trimLeft() / trimStart(), this code works fine. I'll add that when I experimented with changing babel settings to target a browser that doesn't support trim(), the trim() polyfill was imported into this module during compilation.

Visual Studio Gulp Babel Resolve Imports

How to make gulp-babel resolve the imports of a js file. Because right now it is running without error in visual studio but the imports are not resolved. Does the source directory of modules to import need to be specified - how to do that in the gulpfile.js?
gulpfile.js
"use strict";
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("js", function () {
return gulp.src('./wwwroot/js/app.js')
.pipe(babel())
. pipe(gulp.dest('./wwwroot/js/babel'));
});
app.js:
import { MDCRipple } from '#material/ripple';
import { MDCTextField } from '#material/textfield';
const username = new MDCTextField(document.querySelector('.username'));
const password = new MDCTextField(document.querySelector('.password'));
new MDCRipple(document.querySelector('.cancel'));
new MDCRipple(document.querySelector('.next'));
This solved the issue:
https://github.com/babel/babelify/issues/247
In my current understanding the issue was: the dependencies are not being transpiled to a javascript version understandable by browserify.
[What worked]
gulpfile.js:
"use strict";
var gulp = require("gulp");
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var babelify = require('babelify');
gulp.task("js", function () {
browserify('./wwwroot/js/app.js')
.transform("babelify", {
global: true,
presets: ["es2015", "es2016", "stage-0"],
ignore: /\/node_modules\/underscore/
})
.bundle()
.pipe(source('babel.js'))
.pipe(gulp.dest('./wwwroot/js'));
});
package.json:
{
"version": "1.0.0",
"name": "asp.net",
"private": true,
"devDependencies": {
"babel-core": "6.26.3",
"gulp": "3.9.1",
"browserify": "15.0.0",
"babelify": "8.0.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-es2016": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"vinyl-source-stream": "2.0.0",
"material-components-web": "0.28.0"
}
}

UglifyJs error with Gulp and webpack

I am currently discovering the module bundler "Webpack". I am trying to do something quite easy : I have a main.js entry and a bundle.js output. I use babel in order to translate in ES6.
My package.json :
{
"name": "me",
"version": "1.0.0",
"description": "Builder",
"main": "index.js",
"scripts": {
...
},
"author": "me",
"license": "ISC",
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-preset-env": "^1.5.2",
"babel-preset-es2015": "^6.24.1",
"gulp": "^3.9.1",
"lodash": "^4.17.4",
"webpack": "^3.0.0",
"webpack-stream": "^3.2.0"
},
"dependencies": {
"jquery": "^3.2.1"
}
}
Webpack.config.js :
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: path.resolve(__dirname, 'js/main.js'),
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
When I prompt webpack in the CLI, it works pretty well, a bundle.js file which is minified is created in the dist folder.
Now, I want to combine with Gulp
Here is my gulpfile.js :
var gulp = require('gulp');
var webpackS = require('webpack-stream');
gulp.task('default', function() {
return gulp.src('./app/js/main.js')
.pipe(webpackS( require('./app/webpack.config.js') ))
.pipe(gulp.dest('./app/dist/'));
});
When I enter gulp in the CLI, I have this error :
stream.js:74
throw er; // Unhandled stream error in pipe.
^
Error: bundle.js from UglifyJs
Unexpected token: name (_) [bundle.js:47,8]
However, when I remove the line new webpack.optimize.UglifyJsPlugin() from webpack.config.js and prompt gulp in the CLI it works perfectly !
I reinstalled all the npm packages but the problem is still here.
Does anybody have an idea ?
I would like to suggest you to don't mix webpack and gulp,
just create a script inside your package.json#scripts which runs webpack and then if you still want to exec webpack inside a gulp task you can do:
var exec = require('child_process').exec;
gulp.task('runWebpack', function (callback) {
exec('npm run webpack', callback);
})
How do you run the Webpack config? I assume by webpack path-to-config/webpack.config.js?
You have new webpack.optimize.UglifyJsPlugin() in your config, so by using webpack -p which executes the production mode, you get an error because UglifyJsPlugin is executed twice.
I guess the same happens with your Gulp setup.
However, the error message points to "_" not defined, which could be related to lodash. Maybe the import can't be resolved by Gulp?
However, I would not mix Gulp and Webpack. See the discussion here: Gulp + Webpack or JUST Webpack?
There is also an example using Webpack from within a gulp task.

Categories