Gulp 3.9 to 4 Migration - gulp-4

I know this has been asked many times before, but none of the answers helped me to solve my problem migrating gulp 3 to 4. We didn't necessarily have to upgrade to version 4 of gulp, but updating Node.js from 10 to 12 forced us to do so, since Node.js 12 doesn't support gulp 3 anymore. Here are just 2 of files in our build process, I think that it should be enough to understand what the problem is from these files alone, but I can add the other files if need be. And I have also removed the contents of most functions for brevity.
// gulpfile.js
'use strict';
var gulp = require('gulp');
var wrench = require('wrench');
/**
* This will load all js or coffee files in the gulp directory
* in order to load all gulp tasks
*/
wrench.readdirSyncRecursive('./gulp').filter(function (file) {
return (/\.(js|coffee)$/i).test(file);
}).map(function (file) {
require('./gulp/' + file);
});
/**
* Default task clean temporaries directories and launch the
* main optimization build task
*/
//gulp.task('default', ['clean'], function () { <-- Original line, worked in gulp 3.9
function main(done)
{
gulp.start(build);
done();
}
exports.default = gulp.series(clean, main);
And another file:
// build-dev.js
'use strict';
var path = require('path');
var gulp = require('gulp');
var conf = require('./conf');
var $ = require('gulp-load-plugins')({
pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del']
});
//gulp.task('html-dev', ['inject'], function () <-- Original line, worked in gulp 3.9
function htmlDev()
{
// Removed for brevity...
}
exports.htmlDev = gulp.series(exports.inject, htmlDev); <-- this is the line that fails
//gulp.task('fonts-dev', function () <-- Original line, worked in gulp 3.9
function fontsDev()
{
// Removed for brevity...
}
exports.fontsDev = fontsDev;
//gulp.task('other-dev', function () <-- Original line, worked in gulp 3.9
function otherDev()
{
// Removed for brevity...
}
exports.otherDev = otherDev;
//gulp.task('clean', function () <-- Original line, worked in gulp 3.9
function clean()
{
// Removed for brevity...
}
exports.clean = clean;
//gulp.task('build:dev', ['html-dev', 'fonts-dev', 'other-dev']); <-- Original line, worked in gulp 3.9
exports.buildDev = gulp.series(exports.htmlDev, fontsDev, otherDev);
And when I run gulp I get the following error:
AssertionError [ERR_ASSERTION]: Task never defined: undefined
at getFunction (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\helpers\normalizeArgs.js:15:5)
at map (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\arr-map\index.js:20:14)
at normalizeArgs (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\helpers\normalizeArgs.js:22:10)
at Gulp.series (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\node_modules\undertaker\lib\series.js:13:14)
at Object.<anonymous> (F:\Dev\DigitalRural\Main\Mchp.DigitalRural.Portal\gulp\build-dev.js:61:24)
at Module._compile (internal/modules/cjs/loader.js:936:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:947:10)
at Module.load (internal/modules/cjs/loader.js:790:32)
at Function.Module._load (internal/modules/cjs/loader.js:703:12)
at Module.require (internal/modules/cjs/loader.js:830:19) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: undefined,
expected: true,
operator: '=='
}
The error is in the second file, build-dev.js, and I indicate it in the code I provided. I have been trying to follow tutorials and SO questions, but to no avail. What gives?

OK, I apparently got it all wrong (yup, makes sense, from a guy that doesn't know either gulp 3 nor gulp 4 :)).
Since gulp 4 has some quite substantial changes, I had to actually rewrite the whole process (not the tasks themselves, they are more or less fine, except some here and there).
So basically, I changed the tasks to functions, used exports for some tasks to make them well known, and used series/parallel for the tasks' flow.
But I have another problem, related to the destination path, but that's a topic for another post.
Thanks everyone.

Related

CssSyntaxError in plugin "gulp-postcss" / You tried to parse SCSS with the standard CSS parser; try again with the postcss-scss parser

I'm using this plugin for years now, and it's the first time I get this error.
I'm working on an old project which i recently upgraded to the latests versions of node & npm, so I'm working with node v16.15.0 and npm v8.5.5. I also upgraded all of my npm packages to their latests versions (yes, I like to live dangerously).
Gulp v4.0.2 with gulpfile.js as such (there is some commented code in it because I'm still in the process of making it work with these versions of node & npm. Originally, this project was running fine with node v12.6.0 and npm v7.20.03 .
After upgrading, I encountered many errors, as for example the need to switch from node-sass to dart-sass, because it's deprecated. ) :
// MODULES
// ----------------------------------------------------------------------------
const gulp = require('gulp'),
//sass = require('gulp-sass')(require('dart-sass'), require('node-sass')),
sass = require('gulp-sass')(require('sass'), require('dart-sass')),
globImporter = require('node-sass-glob-importer'),
postcss = require('gulp-postcss'),
stylelint = require('gulp-stylelint'),
svgstore = require('gulp-svgstore'),
rename = require('gulp-rename'),
cssnano = require('cssnano'),
uglifyjs = require('uglify-js'),
del = require('del'),
autoprefixer = require('autoprefixer'),
// This is based on node-sass, which is deprecated
// find a replacement which works with something else...
//inliner = require('sass-inline-svg'),
connect = require('gulp-connect'),
openBrowser = require('open');
// Basic config for paths (cfg = config)
// ----------------------------------------------------------------------------
const cfg = {
scssDir: 'src/scss/',
builtCssDir: 'dist/css/',
scssPattern: '**/*.scss',
svgDir: 'src/assets/svg/',
compiledSvgDir: 'dist/svg/',
compiledSvgFileName: 'symbols.twig',
svgPattern: '**/*.svg',
jsLibsDir: 'src/js/libs/',
jsDir: 'src/js/',
compiledJsLibsDir: 'dist/js/libs/',
compiledJsDir: 'dist/js/',
jsPattern: '*.js'
}
// Launch a server
// ----------------------------------------------------------------------------
function serve() {
connect.server({
port: 8080,
livereload: true,
root: ['src']
});
}
// Open application in browser
// ----------------------------------------------------------------------------
async function open() {
await openBrowser('http://localhost:8080/');
}
// Construct style.css (Combine all scss files into one css final file)
// ----------------------------------------------------------------------------
function style() {
return gulp
.src(cfg.scssDir+cfg.scssPattern)
// Test files with `gulp-stylelint` to ckeck the coding style
/*.pipe(stylelint({
reporters: [
{formatter: 'compact', console: true}
]
}))*/
/*.pipe(sass({
importer: globImporter(),
functions: {
svg: inliner(cfg.svgDir, {encodingFormat: 'uri'})
}
}))*/
.on('error', sass.logError)
// Use postcss with autoprefixer and compress the compiled file using cssnano
.pipe(postcss([autoprefixer(), cssnano()]))
.pipe(gulp.dest(cfg.builtCssDir))
}
// Construct svg symbol file (Combine svg files into one with <symbol> elements)
// ----------------------------------------------------------------------------
/*function svg() {
return gulp
.src(cfg.svgDir+cfg.svgPattern, {base: cfg.svgDir})
.pipe(rename((filePath) => {
const name = filePath.dirname !== '.' ? filePath.dirname.split(filePath.sep) : []
name.push(filePath.basename)
filePath.basename = `symbol-${name.join('-')}`
}))
.pipe(svgstore({ inlineSvg: true }))
.pipe(rename(cfg.compiledSvgFileName))
.pipe(gulp.dest(cfg.compiledSvgDir));
}*/
// Catch JS libs and transfer it to dist folder
// ----------------------------------------------------------------------------
async function jslibs() {
return gulp
.src(cfg.jsLibsDir+cfg.jsPattern)
.pipe(gulp.dest(cfg.compiledJsLibsDir));
}
// Compile JS
// ----------------------------------------------------------------------------
async function js() {
return gulp
.src(cfg.jsDir+cfg.jsPattern)
.pipe(gulp.dest(cfg.compiledJsDir));
}
// Watcher
// ----------------------------------------------------------------------------
function watch() {
gulp.watch('../'+cfg.scssDir+cfg.scssPattern, style)
gulp.watch('../'+cfg.scssDir+cfg.scssPattern)
gulp.watch(cfg.scssDir+cfg.scssPattern, style)
gulp.watch(cfg.svgDir+cfg.svgPattern, svg)
gulp.watch(cfg.scssDir+cfg.scssPattern);
}
// Empty the build folder of its front asset like css & svg (We're not emptying it totally, because there is other assets in it)
function clean() {
return del([
cfg.builtCssDir,
cfg.compiledSvgDir+'/'+cfg.compiledSvgFileName,
cfg.compiledJsDir
], {force: true});
}
clean.description = 'Delete the content of the build folder.';
// Serve
// ----------------------------------------------------------------------------
// Launch server
const launch = gulp.series(open, serve);
// Builder
// ----------------------------------------------------------------------------
// Regenerate the build folder.
const build = gulp.series(clean, style, jslibs, js);
// Export default task
// ----------------------------------------------------------------------------
// Regenerate the build folder & launch watcher
const defaultTask = gulp.series(clean, style, jslibs, js, watch);
// Export Tasks
// ----------------------------------------------------------------------------
module.exports = {
open,
serve,
launch,
clean,
style,
jslibs,
js,
build,
watch,
default: defaultTask
};
I get the following error when I try to throw my gulp default task in my terminal :
error
[11:42:55] CssSyntaxError in plugin "gulp-postcss"
Message:
/Users/emma/Desktop/www/photosbroth/src/scss/styles.scss:3:1: Unknown word
You tried to parse SCSS with the standard CSS parser; try again with the postcss-scss parser
1 | #charset "UTF-8";
2 |
> 3 | // Import EXTERNAL libs
| ^
4 | // - `sass-mq` for breakpoints management
5 | #import '../../node_modules/sass-mq/mq';
Apparently, it doesn't like the // scss comments, which were perfectly fine before I tried to upgrade my stack.
Could anyone help please ? I wasn't able to find a solution to this.
I tried this in the gulpfile :
postcss = require('gulp-postcss')(require('postcss'))
this
postcss = require('gulp-postcss')(require('postcss-scss'))
and this
postcss = require('gulp-postcss')(require('postcss'), require('postcss-scss'))
None of those expressions worked.
Is this a bug or anything else ? Am I missing something ?
Thank you.

How do I mix promises and pipe in gulp?

In my project I compile multiple bundles from source files in nested directories using rollup.
I had a gulpfile with the following code, which worked fine:
function build_app_js(file, name) {
return gulp.src(file)
.pipe(sourcemaps.init())
.pipe(rollup({format:'iife'}))
.pipe(terser())
.pipe(rename(name + '.js'))
.pipe(rename({suffix: '.min'}))
.pipe(sourcemaps.write())
.pipe(gulp.dest(js_apps_dir))
}
// call the above for multiple sets of file+app_name
But then I changed one of the dependencies in my ES6 code which I accessed by relative path into an npm package, so it is now in node_modules. Rollup needs a plugin to resolve this, so I changed the above to this:
.pipe(rollup({plugins: [resolveNodeModules()], format:'iife'}))
However this simply does not work.
I consulted rollup's docs on gulp, and adapted the example to my case, so it now looks like this:
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
This works, but has no minification step, and I don't know how to add one.
More generally, this is a totally different paradigm from using pipe(), and I do not know how to make both work together.
Do I try to add minification in the Promise syntax, or do I wrap the Promise function in such a way that I can use it with pipe?
Answering own question after 8 days.
Minification can be achieved via rollup plugins, such as rollup-plugin-terser.
You just need to be careful with how you import them:
var rollup = require('rollup');
var resolveNodeModules = require('rollup-plugin-node-resolve');
//var terser = require('rollup-plugin-terser'); // WRONG
var {terser} = require('rollup-plugin-terser'); // CORRECT
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules(),
terser()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
If you import it the wrong way, you will get a terser() is not a function type error, which is because it will have imported terser as a module.
It's a bit annoying that different rollup-plugins can't be imported the same way, but hey.

Gulp not copying Angular2 to lib-npm

I'm following this tutorial. http://www.c-sharpcorner.com/article/using-mvc-6-and-angularjs-2-with-net-core/
I have gotten to the point of using gulp to copy files to the lib-npm folder. All the expected files copy except angular. I receive no error message, the files just are there.
here is my gulp file
/// <binding />
/*
This file in the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/
"use strict";
var gulp = require("gulp");
var root_path = {
webroot: "./wwwroot/"
};
//library source
root_path.nmSrc = "./node_modules/";
//library destination
root_path.package_lib = root_path.webroot + "lib-npm/";
gulp.task("copy-systemjs", function () {
return gulp.src(root_path.nmSrc + '/systemjs/dist/**/*.*', {
base: root_path.nmSrc + '/systemjs/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/systemjs/'));
});
gulp.task("copy-angular2", function () {
return gulp.src(root_path.nmSrc + '/angular2/bundles/**/*.js', {
base: root_path.nmSrc + '/angular2/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/'));
});
gulp.task("copy-es6-shim", function () {
return gulp.src(root_path.nmSrc + '/es6-shim/es6-sh*', {
base: root_path.nmSrc + '/es6-shim/'
}).pipe(gulp.dest(root_path.package_lib + '/es6-shim/'));
});
gulp.task("copy-rxjs", function () {
return gulp.src(root_path.nmSrc + '/rxjs/bundles/*.*', {
base: root_path.nmSrc + '/rxjs/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/rxjs/'));
});
gulp.task("copy-all", ["copy-rxjs", 'copy-angular2', 'copy-systemjs', 'copy-es6-shim']);
I have also noticed that my .\node_modules\Angular2 folder in my project doesn't have an .js files in it. Is this normal?
Angular2 version is 1.0.2
I receive the following errors on build because the files are missing
Cannot find name 'Component'.
Build:Cannot find module 'angular2/core'.
Build:Cannot find module 'angular2/platform/browser'.
Build:Cannot find name 'Component'.
Cannot find module 'angular2/core'.
Cannot find module 'angular2/platform/browser'
I would suggest you not to copy node_modules every time you build an app. You can easily amend the UseStaticFiles middleware inside the Startup.cs class as described here. By doing this your node_modules stay where they are and you don't need to repeatedly copy them.
Btw. Recently (before switching to UseStatisFiles modification) I have done the same in the Gulp and the following has worked well:
gulp.task('build-angular-js', function () {
return gulp.src(paths.angularJs)
.pipe(cache('linting'))
.pipe(gulp.dest(paths.jsNgDest));
});
..where paths equals to:
var paths = {
webroot: "./wwwroot/",
angularJs: [
"./node_modules/core-js/client/shim.min.js",
"./node_modules/zone.js/dist/zone.js",
"./node_modules/reflect-metadata/Reflect.js",
"./node_modules/systemjs/dist/system.src.js",
"./App/External/systemjs.config.js",
"./node_modules/#angular/**/*.js",
"./node_modules/rxjs/**/*.js"
],
appJs: [
"./App/App/**/*.js"
]
};
paths.jsDest = paths.webroot + "app";
paths.jsNgDest = paths.webroot + "app";
The complete template and all sources including gulpfile.js can be found here on GitHub. Note that cache is a gulp plugin to avoid copying not modified files. As said above though - better to avoid copying node_modules.

gulp-cache: How can I use a file cache for LESS builds

We are using gulp to compile all our LESS files into the target/ of a Maven project. This task alone takes ~51secs, so we would like to speed it up and skip unchanged LESS files. We need a file cache because gulp is called from Maven and the build runs inside an IDE, so the gulp process cannot stay in memory.
At best, the cached CSS files should be copied to target/ even if /target was deleted by a Clean & Build.
Here's my code:
var cache = require('gulp-cache');
var fileCache = new cache.Cache({ cacheDirName: 'gulp-cache' });
gulp.task('less', function () {
return gulp.src([webappPath + '/**/*.less'])
.pipe(fileCache('less'))
.pipe(sourcemaps.init())
.pipe(less({
paths: [path.join(__dirname, 'less', 'includes')],
plugins: [cleancss],
relativeUrls: true
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(target));
;
});
The line .pipe(fileCache('less')) runs into an error:
TypeError: fileCache is not a function.
(Documentation at https://www.npmjs.com/package/gulp-cache )
(1) The gulp-cache plugin needs to wrap your less plugin. That way only files that have changed will be passed through to less.
(2) You don't necessarily need to instantiate your own cache.Cache object. gulp-cache will create one for you if you don't. You only need to do it yourself if you want to have multiple caches. In that case you can pass the cache.Cache object using the fileCache option.
gulp.task('less', function () {
return gulp.src([webappPath + '/**/*.less'])
.pipe(sourcemaps.init())
.pipe(cache(less({
paths: [path.join(__dirname, 'less', 'includes')],
plugins: [cleancss],
relativeUrls: true
}), {
fileCache: new cache.Cache({ cacheDirName: 'gulp-cache' })
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(target));
});

Trying to run a Gulp script that needs ruby on PHPStorm

I've edited a simple Gulp pipeline (that i've tested and works outside the IDE) and i'm now trying to include it into PHPStorm Project in order to achieve a better css workflow in a real project.
This is the script, (it's a simple css optimization pipeline):
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
livereload = require('gulp-livereload'),
del = require('del');
// Styles
gulp.task('styles', function() {
return sass('../scss/base.scss', { style: 'expanded' })
.pipe(autoprefixer('> 1%, last 2 versions, Firefox ESR, Opera 12.1'))
.pipe(minifycss())
.pipe(gulp.dest('../css'))
.pipe(notify({ message: 'Styles task complete' }));
});
// Clean
gulp.task('clean', function(cb) {
del(['css/base.css'], cb)
});
// Default task
gulp.task('default', ['clean'], function() {
gulp.start('styles');
});
The annoying problem i cannot solve is related to the module sass that is the missing a proper ruby environment initialization, needed in order to run the command.
sass = require('gulp-ruby-sass') ->
'sass' not recognized as an internal or external command.
As i said before, I managed to run this gulp script using an external shell link from the ruby installer:
Start Command Prompt with Ruby
C:\Windows\System32\cmd.exe /E:ON /K C:\Ruby21\bin\setrbvars.bat
Do you have any clue on how to run gulp scripts that needs ruby inside PhpStorm?
Thanks in advance,
Please make sure that Ruby is in your system PATH - in Control Panel, go to System properties, Advanced, press Environment variables, in System variables section select PATH and append C:\Ruby21\bin to it. Make sure to restart PHPStorm after changing PATH

Resources