Gulp 'Open' task doesn't correctly execute - javascript

Below are snippets from my gulpfile and basically the problem I'm experiencing is that open doesn't always open a new browser window whenever 'gulp' is executed from the CLI. For instance if I delete the generated 'dist' folder and execute 'gulp' then the 'dist' will scaffold out with the .html files and assets structure but it will fail to open the site in my browser window...
If I then cancel the gulp task that's currently running and execute it from the CLI again (with the 'dist' folder in place) then gulp will load the site in a new browser window as it should.
How do I set open up so that it executes every time no matter what? I'm thinking it's clashing with the 'clean' task somehow but I'm not quite sure.
Any help would be appreciated.
Clean task:
gulp.task('clean', function() {
gulp.src(['./dist/**/*.*'], { read: true })
.pipe(clean())
});
Open task:
gulp.task('open', function() {
gulp.src(config.startpage)
.pipe(open(config.startpage, { url: 'http://localhost:'+config.http_port }));
});
Default task:
gulp.task('default', ['html', 'scripts', 'styles', 'images', 'open', 'clean'], function() {
server.listen(config.livereload_port);
http.createServer(ecstatic({ root: 'dist/' } )).listen(config.http_port);
// gutil.log(gutil.colors.yellow('HTTP Server running on port:'), gutil.colors.red(config.http_port));
gulp.watch(config.src_sass, ['styles'])._watcher.on('all', livereload);
gulp.watch(config.src_js, ['scripts'])._watcher.on('all', livereload);
gulp.watch(config.src_html, ['html'])._watcher.on('all', livereload);
});
*Config.start_page points to dist/index.html

You have two related issues:
You need to return the streams within your tasks, or gulp won't know that they've completed. If you don't return a stream, return a promise, or use the callback function, gulp assumes the task is synchronous.
This is important, because it completely breaks task dependencies. gulp calls a task, sees that it's synchronous, and then immediately starts the next task.
Simply change your tasks to look like this :
gulp.task('clean', function() {
return gulp.src(['./dist/**/*.*'], { read: true })
.pipe(clean())
});
gulp currently has no way to run non-dependent tasks in a specified order. In your default task, those dependencies are all going to be run simultaneously, unless they depend on each other.
Since I doubt you want to force the clean task to run everytime you run the other tasks, the other solution is to use a 3rd party library to run tasks in sequence. (This is my library, written to solve this exact issue.) Eventually, hopefully, they will have a way to fix this natively.
Note: you still need to fix problem 1 for run-sequence to work.

Related

Running parcel bundler from command line doesn't stop the process

I have a simple JS file that runs parcel bundler:
const Bundler = require('parcel-bundler');
(async () => {
const bundler = new Bundler('./src/index.html', {}); // options omitted for simplicity
await bundler.bundle();
})();
I run it from CLI with:
node ./build.js
While bundler works fine and creates bundled files in the dist folder, the process never exits, but rather remains in the async loop.
I tried adding then callback or using return but none of it helped.
Using process.exit() would of course stop the process but would also limit me from chaining this command in the CI, which is the whole purpose.
What am I doing wrong?
You need to set watch: false in your options to let Parcel know it should not watch but just build it once.
The default option is watch: true, so whenever you change something in your files, Parcel will recognize the change and rebuild your application.

Running gulp task on a module that has dependencies injected via gulp-submodule, that in turn have their own dependencies via gulp-submodule, fails

The title might sound a bit vague, but here's an example of what is going wrong. Suppose we have three modules ModuleA, ModuleB, and ModuleC, so that ModuleA depends on ModuleB and ModuleB depends on ModuleC. When we need to run a task against ModuleA, we oftentimes also need to run some tasks against its dependencies - ModuleB and ModuleC and here's where gulp-submodule comes into play. Gulp-submodule let's us define dependencies between tasks of a dependent module and its dependencies so that a task of the dependent module triggers appropriate tasks of its dependencies.
This works pretty fine if we have a flat structure, namely SomeModule depends on a bunch of other modules that have no dependencies of their own. However, once any of those dependencies has its own dependency, the whole ecosystem breaks with an obscure error message that tells that gulp fails to find a certain task.
Here's the demo code. To test this in a local environment, one must have at least gulp installed as a global package and both gulp and gulp-submodule installed as local packages for the project.
module-a.gulpfile.js
const gulp = require("gulp");
require("gulp-submodule")(gulp);
gulp.submodule("module-b", {filepath: "module-b.gulpfile.js"});
gulp.task("default", ["module-b:default"], () => {
console.log("Running task 'default' for module 'module-a'...");
});
module-b.gulpfile.js
const gulp = require("gulp");
require("gulp-submodule")(gulp);
gulp.submodule("module-c", {filepath: "module-c.gulpfile.js"});
gulp.task("default", ["module-c:default"], () => {
console.log("Running task 'default' for module 'module-b'...");
});
module-c.gulpfile.js
const gulp = require("gulp");
gulp.task("default", [], () => {
console.log("Running task 'default' for module 'module-c'...");
});
Once you run task 'default' on module-a.gulpfile.js, you get an output similar to this:
gulp --gulpfile module-a.gulpfile.js
[07:15:27] Using gulpfile module-a.gulpfile.js
[07:15:27] Task 'module-b:module-c:default' is not in your gulpfile
[07:15:27] Please check the documentation for proper gulpfile formatting
As one might notice, gulp is looking for a certain task called 'module-b:module-c:default', although no task with such name is defined or referenced in any of the project files.
This weird non-existing task comes from the way gulp-submodule handles dependencies between modules and tasks. In simple words, it does the following:
First, at this call gulp.submodule("module-b", {filepath: "module-b.gulpfile.js"}) gulp-submodule temporarily replaces the original gulp.task and loads the specified gulpfile as a module.
When the gulpfile is loaded, it gets the modified instance of gulp, where the task method modifies the name of the task submitted as its argument by prepending it with module name and a separator (":" by default).
Later, when gulp runs task 'default' of module 'module-a', it comes across a dependency that we've referenced as "module-b:default", which is exactly the special name constructed for task 'default' of module 'module-b' in step 2.
With more than one level of dependency hierarchy, this straightforward logic breaks, because calling gulp.submodule("module-c", {filepath: "module-c.gulpfile.js"}) from module-b.gulpfile.js results in a gulp.task being wrapped
by gulp-submodule the second time and hence the name of task 'default' for module 'module-c' gets prepended twice: first with 'module-c' and then with 'module-b'.
To fix this quickly, I've submitted a shortcut fix to our private of the original submodule: 5864ae5 (gulp-submodule). This is merely a quick fix and definitely not the best one, but it did the trick for me. I will update this answer, shall I come with a more solid solution to this issue.

Gulp watch task does't exit on Ctrl C

Background
I am having this gulp watch task to handle sass compilation:
import gulp from 'gulp';
import sass from 'gulp-sass';
import concat from 'gulp-concat';
gulp.task("compile-scss", () => {
return gulp.src("assets/scss/**/*.scss")
.pipe(sass({ outputStyle: 'compressed' })
.on("error", sass.logError))
.pipe(concat("style.css"))
.pipe(gulp.dest("dist/css"));
});
gulp.task("watch-scss", ['compile-scss'], () => {
gulp.watch("assets/scss/**/*.scss", ["compile-scss"]);
});
I am then running gulp watch-scss and the process correctly compiles my files and start watching for new changes.
The problem
When I want watching to stop I am pressing Ctrl+C in the terminal and everything looks ok.
But then I make a change in the .scss file and expect it not be handled by the gulp task (should be already stopped). Anyway this change gets handled by the watch task as it seems still running.
Looking at the terminal code you can see where I start gulp watch-scss, where I press Ctrl+C and where task continues executing on change.
Environment details
OS: OS X 10.11 (El Capitan)
gulp version: 3.9.1
node version: 6.2.2
babel-core version: 6.11.4
History
The problem could be related to Node itself. Going into that direction I tried several solutions like terminating the process from within gulp like so:
process.on('SIGINT', function() {
process.exit();
});
It didn't help.
Read lot of info on that topic, but nothing helped. Here are two related questions, which didn't help either:
Stop a gulp watch task?
Terminate gulp-watch task
I can provide more details if needed.
Close the terminal and the session will be terminated. Run gulp again and try if CTRL + C works.

Browser sync for Angular SPA

I'm using browser sync with an Angular SPA. Serving the site looks like this:
gulp.task('serve', function() {
browserSync.init(null, {
server: {
baseDir: './',
middleware: [historyApiFallback()]
}
});
});
This works fine. The use of historyApiFallback (npm module) means browser sync doesn't freak out when going to a new URL path when all it needs to do is continue serving the index.html.
The problem I have is with watching files. I've tried this:
gulp.task('watch', function() {
watch('./src/scss/**/*.scss', function() {
runSequence('build-css', browserSync.reload);
});
});
The watch task does work because the build-css task triggers fine. Then the console logs Reloading Browsers... and just hangs. The browser never gets the CSS injection or reload. What am I doing wrong here?
Note that I'm using gulp-watch not the native gulp watch purposely.
I recommend you to use the lite-server. It is a simple customized wrapper around BrowserSync to make it easy to serve SPAs(you don't even have to configure the history api).
You can use it by simple adding an entry in the scripts object in your package.json and running the following command: npm run dev.
"scripts": {
"dev": "lite-server"
},
The module will automatically watch for changes of your files and keep then sync. So it will work with your gulp, because it will update your browser after the build-css task is executed(because the output files will change).
I am currently using it with angular 1, angular 2 and vue.js and worked fine with all.

After modularizing an AngularJS app, how do you include the entire project in the index.html without having to type a ton of <script> tags

I've been learning Angular for awhile now and am looking into the best ways to modularize the application. I think my understanding of that is going pretty well, but I've looked around for awhile and can't seem to get a good answer as to how all of these .js files get included inside of the index.html without just manually typing out a bunch of tags. I've been looking into Grunt/Gulp and get how those are combining the entire app into one .js file, but for development I'm guessing you don't want to have to re-run grunt or gulp every time you want to update the app.
There are many different options: gulp, grunt, or webpack seem to be the most popular. I tend to use webpack the most these days.
A good setup will typically run a local node server, which will refresh the browser automatically every time you make a change to a file.
There are many yeoman generators that will set this all up for you, or you can find simple examples on github.
The basic idea is to
concatenate all your js files (in proper order so the module definitions go before controllers/services)
minify if for production
copy to a fixed path
include this single js file in your html
during development have your grunt/gulp script watch for changes in js files and re-run the above steps so you don't have to run the grunt/gulp task manually.
Now if you are using gulp here is how you would typically handle above steps
gulp.task('process-js', function () {
return gulp.src(jsFiles, {base: './'})
.pipe(gulpif(isProd, concat('all.min.js'), concat('all.js')))
.pipe(gulpif(isProd, uglify({mangle: true, preserveComments: 'some'})))
.pipe(gulp.dest(deployFolder + '/static/js'))
});
where jsFiles is an array of files/folders that contain your angular app js files
var jsFiles = [
'!static/js/**/*.js',
'!static/js/plugin/**/*.*',
'app/index/**/*module.js',
'app/index/**/*config.js',
'app/index/**/*ctrl.js'
];
Note: use ! prefix to exclude certain files/folders from processing.
isProd is just a flag that indicates whether you are preparing for production or development.
During development I also use BrowserSync to watch any changes to my js files and re-run the gulp task to prepare all.js. It also refreshes the page in browser automatically.
gulp.task('run', function () {
browserSync({
server: {
baseDir: deployFolder
},
open: true,
browser: ['google chrome'],
files: deployFolder + '/**/*',
watchOptions: {
debounceDelay: 2000
}
});
gulp.watch(jsFiles, ['process-js']);
});
gulp.task('default', function () {
runSequence(
'clean',
'run'
);
});
Gulp/Grunt to concat all your angular files.
Create 2 tasks :
a dev build task
concat to one file BUT don't uglify.
a distribution/production task which is the same as dev one but this one uglify the concatenated file.

Categories

Resources