Exit with error after a task loaded by gulp-tasks failed - error-handling

I am working with magento2-frontools and try to solve this issue:
https://github.com/SnowdogApps/magento2-frontools/issues/231
The problem is, that gulp styles should have a non-zero exit code in case of errors, but it exits with 0.
The gulp file looks like this:
// Tasks loading
require('gulp-task-loader')({
dir : 'task',
plugins: plugins,
configs: config
});
And the styles.js task like this:
'use strict';
module.exports = function() { // eslint-disable-line func-names
// Global variables
const gulp = this.gulp,
plugins = this.opts.plugins,
config = this.opts.configs,
themes = plugins.getThemes(),
streams = plugins.mergeStream();
// Generate all necessary symlinks before styles compilation, but ony if not a part of tasks pipeline
if (!plugins.util.env.pipeline) {
plugins.runSequence('inheritance');
}
// Loop through themes to compile scss or less depending on your config.json
themes.forEach(name => {
streams.add(require('../helper/scss')(gulp, plugins, config, name));
});
return streams;
};
(it can all be found on GitHub)
If have seen this approach to solve the problem:
.once("error", function () {
this.once("finish", () => process.exit(1));
})
But where can I add that code?

Just the --ci flag has to be used.

Related

Run Gulp task before build in VS Code

I have a new empty .NET Core project. Can I automatically run Gulp tasks before a build in VS Code?
I can run the styles task manually by doing VS Code package manager -> Tasks: Run Task -> gulp -> gulp: styles, but when I do build it does not run.
/// <binding beforebuild="styles"></binding>
var gulp = require('gulp');
var gulpless = require('gulp-less');
gulp.task('styles', function () {
var srcfile = 'styles/Styles.less';
var dest = 'wwwroot';
return gulp
.src(srcfile)
.pipe(gulpless())
.pipe(gulp.dest(dest));
});
I got this code from some tutorials online and everything works except the first line.
Is this supposed to work in VS Code or is this only a luxury of Visual Studio?
//In this case we’re adding the a task before other task.
gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
// ...
})
//And in this case we’re adding for example the browserSync task.
gulp.task('watch', ['browserSync'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Other watchers
})
//We’ll also want to make sure sass runs before watch so the CSS will already be the latest whenever we run a Gulp command.
gulp.task('watch', ['browserSync', 'sass'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Other watchers
});
Read this document : Gulp for Beginners

Ignoring a new file with vue's dev server

I'm using the pre-build-webpack plugin to merge several json files into 1 json array every time I start my app (npm run serve or npm run build), but the problem is that it gets caught in an infinite webpack compile loop in when I start the development server. I managed to find a solution to the problem by using the watch-ignore-webpack-plugin plugin, which initially seemed to have resolved the issue - webpack will now compile everything twice (it seems) and then it's good to go and I can access my local server. But the problem now is that when I visit localhost:8080 there's nothing. The screen's blank and there's nothing being console.log()ed, so I don't know what to do anymore.
If anyone's seen anything like this or know how to fix it, please let me know. If you require any additional info, also let me know.
Versions:
vue: 2.6.10 (as seen in package.json)
vue-cli: 3.11.0 (running vue -V in cmd)
pre-build-webpack: 0.1.0
watch-ignore-webpack-plugin: 1.0.0
webpack-log: 3.0.1
vue.config.js (with everything irrelevant removed):
const WebpackPreBuildPlugin = require('pre-build-webpack');
const WatchIgnorePlugin = require('watch-ignore-webpack-plugin');
module.exports = {
configureWebpack: {
plugins: [
new WebpackPreBuildPlugin(() => {
const fs = require('fs');
const glob = require('glob');
const log = require('webpack-log')({ name: 'ATTENTION!' });
const output = [];
const exclude = [];
glob('./src/components/mods/**/*.json', (err, paths) => {
paths.forEach(path => {
const content = JSON.parse(fs.readFileSync(path, 'utf-8'));
const pathSplit = path.split('/');
const modFolderName = pathSplit[pathSplit.length - 2]
if(!output.filter(val => val.id === content.id)[0]) {
if(exclude.indexOf(modFolderName) === -1) {
output.push(content);
} else {
log.warn(`SKIPPING CONTENTS OF "${modFolderName}"`);
}
} else {
log.error(`MOD WITH ID "${content.id}" ALREADY EXISTS!`);
process.exit(0);
}
});
// If I take out this line, the infinite loop doesn't occur, but then, of
// course, I don't get my merged json file either.
fs.writeFileSync('./src/config/modules/layoutConfig.json', JSON.stringify(output));
});
}),
// Neither of the blow paths work.
new WatchIgnorePlugin([/\layoutConfig.json$/]),
// new WatchIgnorePlugin(['./src/config/modules/layoutConfig.json']),
]
}
};

How to change content of VuePress page via Plugin

I am trying to set up a plugin to change the content of a VuePress markdown file on the dev server and production build. According to documentation, I should be able to use the _content and _strippedContent that is available to me with the extendPageData
The following code is what I have set up in a plugin to do this.
module.exports = (options = {}, context) => ({
extendPageData($page) {
const {
_filePath, // file's absolute path
_computed, // access the client global computed mixins at build time, e.g _computed.$localePath.
_content, // file's raw content string
_strippedContent, // file's content string without frontmatter
key, // page's unique hash key
frontmatter, // page's frontmatter object
regularPath, // current page's default link (follow the file hierarchy)
path, // current page's real link (use regularPath when permalink does not exist)
} = $page
$page._content = "replaced"
$page._strippedContent = "replaced"
}
})
The best I can tell is that this code should work as it updates the $page._content however it is not showing testing but rather the original content.
I know that I am getting into this code as I can console.log from the file and it shows in the console.
I fear that $page._content is immutable and wonder if there is a way to do this kind of content swapping during dev or build
The information in those page objects is used after the markdown has been compiled and during the Vue component rendering. The content is more there for reference and modifying it won't have the effect you are after.
This tripped me up as well.
All the markdown files are processed for inoformation, but then the actual compilation occurs through webpack. The general flow is:
.md -> markdown-loader -> vue-loader -> ...
My recommendation and what I have done is to create a custom webpack loader to modify the content before it goes through the VuePress markdown loader. I used this approach to run my markdown files through Nunjucks for templating pre-markdown compilation. It's increadibly easy to do this after you figure out the correct approach :) Here is a working approach:
config.js:
chainWebpack: config => {
config.module
.rule('md')
.test(/\.md$/)
.use(path.resolve(__dirname, './nunjucks'))
.loader(path.resolve(__dirname, './nunjucks'))
.end()
},
And then a simple loader can look like this(abridged):
module.exports = function(source) {
const rendered = nunjucks.renderString(source, config)
return rendered
}
I think that You should do this with use of extendMarkdown https://v1.vuepress.vuejs.org/config/#markdown-extendmarkdown.
Try like this
// index.js
module.exports = () => ({
name: 'vuepress-plugin-foo-bar',
extendMarkdown: md => {
const render = md.render;
md.render = (...args) => {
// original content
const html = render.call(md, ...args);
return 'new content';
};
},
});
You can to modify your .vuepress/config.js. For example, if you want to replace '---my text---' with 'MY TEXT' (with uppercase, for example) in all yours files markdown, you have to add the next code to .vuepress/config.js, into chainWebpack section where I use a regex expression:
// File: .vuepress/config.js
module.exports = {
...,
chainWebpack: config => {
// Each loader in the chain applies transformations to the processed resource:
config.module
.rule('md')
.test(/\.md$/)
.use("string-replace-loader")
.loader("string-replace-loader")
.options({
multiple: [{
search: '---(.*?)---',
replace: (match, p1, offset, string, groups) => `<div><p class="myclass">${p1.toUpperCase()}</p></div>`,
flags: 'ig'
},
{
search: ' ... ',
replace: (match, p1, p2, ..., pn, offset, string) => ` ... `,
flags: 'ig'
}
],
}, )
.end()
},
};

How to cache .mp4 files in Safari with workbox-webpack-plugin?

I'm having exactly the same issue reported at https://github.com/GoogleChrome/workbox/issues/1663 which describes an issue that occurs exclusively in Safari where mp4 videos are not rendered after being cached by the service worker.
I'm using workbox-webpack-plugin, so the instructions provided in the comment https://github.com/GoogleChrome/workbox/issues/1663#issuecomment-448755945 will not work in my case. I'm not being able to require workbox-range-requests plugin in my webpack config file and pass it to the runtime caching options because I believe this package is intended for browser usage only. My workbox config is precaching .mp4 assets and uses a network first strategy for runtime caching.
How can I setup workbox-range-requests with workbox-webpack-plugin?
EDIT: Following Jeff's answer below, I've adjusted my webpack config to the following:
new WorkboxPlugin.InjectManifest({
swSrc: serviceWorkerSrcPath,
swDest: serviceWorkerBuildPath,
importsDirectory: 'sw',
})
The build produces the following service worker:
importScripts("/_build/sw/precache-manifest.8a0be820b796b153c97ba206d9753bdb.js", "https://storage.googleapis.com/workbox-cdn/releases/3.6.2/workbox-sw.js");
workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
workbox.routing.registerRoute(
/.*\.mp4/,
new workbox.strategies.CacheFirst({
cacheName: 'videos',
plugins: [
new workbox.cacheableResponse.Plugin({ statuses: [200] }),
new workbox.rangeRequests.Plugin(),
],
}),
);
If forgot to mention previously, but I've also added crossOrigin="anonymous" attribute to the video elements.
EDIT:
Repro that demonstrates it does not work as expected on Safari: https://github.com/acostalima/workbox-range-requests-mp4-demo
There's specific guidance for this use case in the "Serve cached audio and video" recipe in the Workbox documentation.
You can continue using the workbox-webpack-plugin, but I'd suggest using it in InjectManifest mode, which will give you control over the top-level service worker file. That will in turn make it possible to follow the recipe.
This documentation has guidance on configuring workbox-webpack-plugin in InjectManifest mode.
I had the same issue with Safari and managed to resolve it by removing my video from the precahe list self.__precacheManifest and instead by adding it in the service worker's install handler:
self.addEventListener('install', (event) => {
const urls = [/* videoUrl */];
const cacheName = 'videos';
event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(urls)));
});
Looking at the logs, it seemed that otherwise only the precache was used to respond to the request for the video resource and not the router.
Although the docs say that adding mp4s to the precache cache and then configuring the range plugin to handle precache mp4s is supposed to work, in practice, it wasn't. Removing mp4s from the precache and configuring your own video cache with the range plugin did the trick for me. Don't forget to add the crossorigin="anonymous" tag to your videos!
Here's how I did it (webpack 5, workbox 6):
// src/service-worker.js
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { cacheNames } from 'workbox-core';
import { precacheAndRoute } from 'workbox-precaching';
import { RangeRequestsPlugin } from 'workbox-range-requests';
import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
const allEntries = self.__WB_MANIFEST; // Injected by WorkboxWebpackPlugin at compile time
const videoEntries = allEntries.filter((entry) => entry.url.endsWith('.mp4'));
const restEntries = allEntries.filter((entry) => !entry.url.endsWith('.mp4'));
precacheAndRoute(restEntries);
const videoCacheName = `${cacheNames.prefix}-videos-${cacheNames.suffix}`;
self.addEventListener('install', (event) => {
const allVideosAddedToCache = caches.open(videoCacheName).then((videoCache) => {
const videoUrls = videoEntries.map((entry) => entry.url);
return videoCache.addAll(videoUrls);
});
event.waitUntil(allVideosAddedToCache);
});
registerRoute(
(route) => route.url.pathname.endsWith('.mp4'),
new CacheFirst({
cacheName: videoCacheName,
plugins: [new CacheableResponsePlugin({ statuses: [200] }), new RangeRequestsPlugin()],
})
);
// webpack.config.js
plugins: [
new WorkboxWebpackPlugin.InjectManifest({
swSrc: 'src/service-worker.js',
}),
]
// index.tsx
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js');
});
}

React native require relative path file

I am trying React Native iOS and I was trying to setup project environments. I create a file called config.js so later I can just
import config from 'env'
to load the variables based on different environments. The following is the config.js file
let configFile = 'dev.js'
if (NODE_ENV === 'production') {
configFile = 'prod.js'
}
export default require('./env/' + configFile)
Somehow this won't work. the error message is:
Requiring unknown module "./env/dev.js". If you are sure the module is there, try restarting the packager or running "npm install"
When I changed my code to the following it would not give me errors. But it is not what I wanted to do.
export default require('./env/dev.js')
So does anyone know why is that?
Firstly, require calls are not dynamic. They are statically analyzed and bundled. So you would want something like this
let prodConfig = require('./env/prod.js');
let devConfig = require('./env/dev.js');
let config;
if (process.env.NODE_ENV === 'production') {
config = prodConfig;
}else {
config = devConfig;
}
export default config;