How do I mix promises and pipe in gulp? - promise

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.

Related

StoryShots Directory of snapshots

I am using the StoryShots addon for Storybook to test snapshots from my React project. I would like to save all snapshot files in one directory in relation to the project directory. The default is that the snapshots are saved in relation to the story's location. I tried various configurations (like working with __dirname) but couldn't come up with a solution yet. Maybe someone has an idea?
Here is my storyshots test file used by Jest (storyshots.test.ts):
import initStoryshots, { multiSnapshotWithOptions, Stories2SnapsConverter } from '#storybook/addon-storyshots'
initStoryshots({
test: multiSnapshotWithOptions(),
stories2snapsConverter: new Stories2SnapsConverter({
snapshotsDirName: './__snapshots__/',
storiesExtensions: ['.js', '.jsx', '.ts', '.tsx'],
})
})
You can do something like this:
const IMAGE_SNAPSHOT_DIR = path.resolve(path.join(__dirname, 'component-image-snapshots'));
initStoryshots({
test: imageSnapshot({
getMatchOptions: (option) => {
const filename = option.context.kind.replace(' ', '');
return {
customSnapshotsDir: path.join(IMAGE_SNAPSHOT_DIR, filename),
};
},
}),
});

Specify the webpack "mainFields" on a case by case basis

Webpack has a resolve.mainFields configuration: https://webpack.js.org/configuration/resolve/#resolvemainfields
This allows control over what package.json field should be used as an entrypoint.
I have an app that pulls in dozens of different 3rd party packages. The use case is that I want to specify what field to use depending on the name of the package. Example:
For package foo use the main field in node_modules/foo/package.json
For package bar use the module field in node_modules/bar/package.json
Certain packages I'm relying on are not bundled in a correct manner, the code that the module field is pointing to does not follow these rules: https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md This causes the app to break if I wholesale change the webpack configuration to:
resolve: {
mainFields: ['module']
}
The mainFields has to be set to main to currently get the app to work. This causes it to always pull in the CommonJS version of every dependency and miss out on treeshaking. Hoping to do something like this:
resolve: {
foo: {
mainFields: ['main']
},
bar: {
mainFields: ['module'],
}
Package foo gets bundled into my app via its main field and package bar gets bundled in via its module field. I realize the benefits of treeshaking with the bar package, and I don't break the app with foo package (has a module field that is not proper module syntax).
One way to achieve this would be instead of using resolve.mainFields you can make use of resolve.plugins option and write your own custom resolver see https://stackoverflow.com/a/29859165/6455628 because by using your custom resolver you can programmatically resolve different path for different modules
I am copy pasting the Ricardo Stuven's Answer here
Yes, it's possible. To avoid ambiguity and for easier implementation,
we'll use a prefix hash symbol as marker of your convention:
require("#./components/SettingsPanel");
Then add this to your configuration file (of course, you can refactor
it later):
var webpack = require('webpack');
var path = require('path');
var MyConventionResolver = {
apply: function(resolver) {
resolver.plugin('module', function(request, callback) {
if (request.request[0] === '#') {
var req = request.request.substr(1);
var obj = {
path: request.path,
request: req + '/' + path.basename(req) + '.js',
query: request.query,
directory: request.directory
};
this.doResolve(['file'], obj, callback);
}
else {
callback();
}
});
}
};
module.exports = {
resolve: {
plugins: [
MyConventionResolver
]
}
// ...
};
resolve.mainFields not work in my case, but resolve.aliasFields works.
More details in https://stackoverflow.com/a/71555568/7534433

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

Find a good way to get a coverage report on ES6 code

Here is my problem : in an AngularJS project, I use Babel 6 (ES2015 + stage3 + decorators), SystemJS and Karma + Jasmine.
All is OK, except for code coverage : I can't find a good way to get a coverage report on ES6 code instead of transpiled ES5.
I have some restrictions :
no Github npm dependencies
no deprecated projects (like isparta)
should run on Windows (yeah, I know, but I have to) and GNU/Linux
This question is especially oriented to a local html coverage report, but I also need a format that could be used in SonarQube.
There seems to be a huge lake of support on this question (especially with Decorators and SystemJS), so, along with some issues on Github, maybe the stackoverflow community could share a way to do this.
If you need some extras, you can see this project on Github (Sedona-Solutions/sdn-angularjs-seed), and look at the related issues (Sedona-Solutions/sdn-angularjs-seed#5) with references to all related issues and projects I could found.
About remap-istanbul
Here is my transpilation and mapping gulp task :
gulp.task('es6', function () {
return gulp.src(paths.source, { base: 'app' })
.pipe(plumber())
.pipe(changed(paths.output, { extension: '.js' }))
.pipe(sourcemaps.init())
.pipe(babel(compilerOptions))
.pipe(ngAnnotate({
sourceMap: true,
gulpWarnings: false
}))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(paths.output))
});
Karma-coverage
coverageReporter: {
reporters: [
{
type: 'json',
dir: 'target/coverage/',
subdir: '.',
file: 'coverage-final.json'
}
]
}
and the test:remap gulp task :
gulp.task('test:remap', ['test'], function (done) {
return gulp.src(paths.coverage + '/coverage-final.json')
.pipe(remapIstanbul({
reports: {
'json': paths.coverage + '/coverage.json',
'html': paths.coverage + '/html-remaped/'
},
fail: true,
useAbsolutePaths: true
}));
});
due to the first remap-istanbul issue, I get the following error :
C:\...\sdn-angularjs-seed\node_modules\remap-istanbul\node_modules\istanbul\lib\report\html.js:288
text = structuredText[startLine].text;
^
TypeError: Cannot read property 'text' of undefined
at C:\...\sdn-angularjs-seed\node_modules\remap-istanbul\node_modules\istanbul\lib\report\html.js:288:53
You can see the corresponding code on github.
It could be an error on some mapping generation, or paths ... If you think so, tell me.
karma-coverage + remap-istanbul should work fine

Resources