I have been using a Gulp script on my Jekyll project together with browser-sync and some other plugins (to minify/concat JS/Sass and to minify images and svg).
Starting a few days ago (I'm not sure what caused it, using my old gulp scripts doesn't help) it's causing a loop of 2-15 reloads every time I save a HTML or JS file.
This returns in the following in the terminal:
[00:51:47] Finished 'jekyll-build' after 850 ms
[00:51:47] Starting 'jekyll-rebuild'...
[BS] Reloading Browsers...
[00:51:47] Finished 'jekyll-rebuild' after 241 μs
[00:51:47] Starting 'jekyll-build'...
Generating...
done in 0.188 seconds.
Auto-regeneration: disabled. Use --watch to enable.
[00:51:48] Finished 'jekyll-build' after 881 ms
[00:51:48] Starting 'jekyll-rebuild'...
[BS] Reloading Browsers...
[00:51:48] Finished 'jekyll-rebuild' after 480 μs
[00:51:48] Starting 'jekyll-build'...
Generating...
done in 0.251 seconds.
Auto-regeneration: disabled. Use --watch to enable.
[00:51:49] Finished 'jekyll-build' after 826 ms
[00:51:49] Starting 'jekyll-rebuild'...
[BS] Reloading Browsers...
[00:51:49] Finished 'jekyll-rebuild' after 942 μs
My Gulpfile looks like the following. Sorry for pasting so much code in here.
/**
* Build the Jekyll Site
*/
gulp.task('jekyll-build', function (done) {
browserSync.notify(messages.jekyllBuild);
return cp.spawn('jekyll', ['build'], {stdio: 'inherit'})
.on('close', done);
});
/**
* Rebuild Jekyll & do page reload
*/
gulp.task('jekyll-rebuild', ['jekyll-build'], function () {
browserSync.reload();
});
/**
* Wait for jekyll-build, then launch the Server
*/
gulp.task('browser-sync', ['sass', 'jekyll-build', 'jekyll-rebuild', 'imagemin', 'svgmin'], function() {
browserSync({
server: {
baseDir: '_site'
}
});
});
/**
* Compile files from _scss into both _site/css (for live injecting) and site (for future jekyll builds)
*/
gulp.task('sass', function () {
return gulp.src('_scss/main.scss')
.pipe(sass({
includePaths: ['scss'],
onError: browserSync.notify
}))
.pipe(prefix(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], { cascade: true }))
.pipe(gulp.dest('_site/css'))
.pipe(browserSync.reload({stream:true}))
.pipe(gulp.dest('css'))
.pipe(rename({
extname: ".min.css"
}))
.pipe(uglifycss())
.pipe(gulp.dest('css'))
.pipe(gulp.dest('_site/css'));
});
/** optimize images **/
gulp.task('imagemin', function() {
return gulp.src('assets/img/*')
.pipe(imagemin({
progressive: true,
svgoPlugins: [{removeViewBox: false}],
use: [pngquant()]
}))
.pipe(gulp.dest('./_site/assets/img'))
.pipe(browserSync.reload({stream:true}));
});
gulp.task('svgmin', function() {
return gulp.src('assets/svg/*.svg')
.pipe(svgmin())
.pipe(gulp.dest('./_site/assets/svg'));
});
gulp.task('scripts', function() {
return gulp.src([
'***scripts***' //removed for readability
])
.pipe(include())
.pipe(plumber({
errorHandler: function(err){
notify('JS compile error: ' + err);
}
}))
.pipe(concat('main.js'))
.pipe(gulp.dest('javascript'))
.pipe(rename({
extname: ".min.js"
}))
.pipe(uglify())
.pipe(gulp.dest('javascript'))
.pipe(browserSync.reload({stream:true}))
.pipe(notify('JS Compiled'));
});
/** Lint JS **/
gulp.task('lint', function() {
return gulp.src('javascript/app/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
/**
* Watch scss files for changes & recompile
* Watch html/md files, run jekyll & reload BrowserSync
*/
gulp.task('watch', function () {
gulp.watch('_scss/**/**/**/*.scss', ['sass']);
gulp.watch('assets/img/*', ['imagemin']);
gulp.watch('assets/svg/*', ['svgmin']);
gulp.watch('javascript/app/*.js', ['lint', 'scripts']);
gulp.watch(['*.html', '**/*.html', 'javascript/main.js', '_layouts/*.html', '_includes/**/**/*.html'], ['jekyll-rebuild']);
});
/**
* Default task, running just `gulp` will compile the sass,
* compile the jekyll site, launch BrowserSync & watch files.
*/
gulp.task('default', ['browser-sync', 'watch']);
Does anyone see something that could be causing this?
I think the line in your watch function is too broad:
gulp.watch(['*.html', '**/*.html', 'javascript/main.js', '_layouts/*.html', '_includes/**/**/*.html'], ['jekyll-rebuild']);
The second one - '**/*.html' I think is seeing any sub folders, which would include the _site folder, so it sees all the changes there and gets stuck in a loop. You change a file, it regenerates, the _site folder gets dumped, it sees that, regenerates, etc etc.
edit to excluded _site folder
If you have a lot of subfolders and want to include them with **/*.html try excluding the _site directory by adding '!_site/**/*' to the list.
Also, keep in mind that you are specifying .html, that will not pickup any markdown files.
Working on this question has led to this - I think this will be my new watch (I have no reason not to watch all files, other may not want this):
gulp.watch(['**/*.*', '!_site/**/*', '!node_modules/**/*','!.sass-cache/**/*' ], ['jekyll-rebuild']);
the first part seems to watch everything, the second part excludes the site folder and everything in it, then the same for node_modules and .sass-cache.. So far I have not been able to break it, and this is much simpler than what I had:
gulp.watch(['./*', '_layouts/*', '_videos/*', 'order-online/*', '_includes/*', '_posts/*', '_sass/*', 'css/*', 'services/*', '_data/*' ], ['jekyll-rebuild']);
Related
I'm trying to write a gulp file that do the following:
watch the task for any changes.
compile SCSS and minify css and javascript by calling some tasks
Reload the browser vie browserSync
So I came up with following pice of code:
gulp.task('watch', function() {
browserSync({
server: {
baseDir: [paths.base.root]
}
});
gulp.watch(paths.assets.scss, gulp.series('compile:scss'));
gulp.watch(paths.assets.css + '**/*.css', gulp.series('minify:css'));
gulp.watch(paths.assets.js, gulp.series('minify:js'));
gulp.watch(paths.base.html, browserSync.reload);
gulp.watch(paths.assets.js, browserSync.reload);
gulp.watch(paths.assets.css + '**/*.css', browserSync.reload);
gulp.watch(paths.assets.imgs, browserSync.reload);
});
In this pice of code the first three tasks are working but browser only reload one time.
My project structure is as follows:
src
..lib
....someLibrary.js
bundles.js:
"bundles": {
"dist/app-build": {
"includes": [
"[**/*.js]",
"**/*.html!text",
"**/*.css!text"
],
"options": {
"sourceMaps": 'inline'
"inject": true,
"minify": true,
"depCache": true,
"rev": true
}
},
The project builds fine, but when I check app-build.js I don't find a definition for lib/someLibrary.js. I am using typescript for my own project so I assume this has something to do with that, how can I mix regular js files and output from my transpiled TS files into the same app-build bundle?
Update
So I tried to split the 'build-system' gulp task into two tasks: 'build-typescript' which is the same as 'build-system' was before, then I created 'build-libs' which looks like so:
gulp.task('build-libs', function() {
return gulp.src(paths.root + '**/*.js')
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
.pipe(changed(paths.output, {extension: '.js'}))
.pipe(sourcemaps.write('.', { includeContent: false, sourceRoot: '/src' }).on('error', gutil.log))
.pipe(gulp.dest(paths.output));
});
I then added to my dist/app-build bundle config: "lib/someLibrary.min.js"
And now my app-build.js does have the library defined, however when I try to use the library in one of my views using:
<require from="lib/someLibrary.min.js">
I get an error:
Failed to load resource: the server responded with a status of 404 (Static File '/dist/lib/someLibrary.min.html' not found)
What?!?? Why is it looking for html when nowhere is html ever involved in this whole scenario? Why is something that should be easy this hard?
Update2
So apparently 'require' does not work with javascript files. I changed to use the 'script' tag, however it seems these get stripped out when rendered by Aurelia. I am at a loss as to how to get Aurelia to do what I want it to.
Ok so after much frustration and disbelief at how hard something so simple could be, in addition to the changes to the build tasks mentioned above (which includes the javascript library file that has no npm/jspm package into the app-bundle) I created a modified version of this solution which looks as follows:
import { bindable, bindingMode, customElement, noView } from 'aurelia-framework';
#noView()
#customElement('scriptinjector')
export class ScriptInjector {
#bindable public url;
#bindable public isLocal;
#bindable public isAsync;
#bindable({ defaultBindingMode: bindingMode.oneWay }) protected scripttag;
public attached() {
if (this.url) {
this.scripttag = document.createElement('script');
if (this.isAsync) {
this.scripttag.async = true;
}
if (this.isLocal) {
const code = 'System.import(\'' + this.url + '\').then(null, console.error.bind(console));';
this.scripttag.text = code;
} else {
this.scripttag.setAttribute('src', this.url);
}
document.body.appendChild(this.scripttag);
}
}
public detached() {
if (this.scripttag) {
this.scripttag.remove();
}
}
}
To use it, simply add the following tag to the view where you want the script library to be used as follows:
<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>
This will keep the original scriptinjector functionality which allows you to add remote 3rd party libraries to your Aurelia app but it will also allow you to load any local 3rd party libraries that you have bundled with your app.
Hope this helps someone.
I'm using intern.js as a test framework to test dojo modules and it works well.
Now I have to test some non modular legacy code but I can't.
This is an example of a simple file to test:
var Component = function() {
this.itWorks = function() {
return true;
}
};
And this is the test
define([
'intern!object',
'intern/chai!assert',
'intern/order!controls/component',
], function (registerSuite, assert) {
registerSuite({
name: 'test legacy code',
'simple test': function () {
console.log(Component);
}
});
});
The test fails sayng that "Component is not defined".
I've notice that it works only if I write
window.Component = Component
At the bottom of file to test.
I can't modify all the file to test, is it possible to test the file in a different way?
This should work fine. One possible issue is where you're loading component from. The 'controls/component' dependency in 'intern/order!controls/component' is, barring any special loader config, relative to the file doing the loading. That means that if the project is setup like this:
project/
controls/
component.js
tests/
intern.js
componentTest.js
and component is being loaded from componentTest.js, then the dependency should be 'intern/order!../controls/component.js'. (It will actually work without the '../' in this case since controls is a top level directory in the project.)
Another potential issue is that a non-AMD identifier should use the .js suffix. This tells the loader that the thing being loaded is a generic script rather than an AMD module.
Also note that the order plugin is only needed to load multiple legacy files in a specific order. If order doesn't matter, or you're just loading one script, you can just use the script itself '../controls/component.js' as the dependency.
<"/"https://stackoverflow.com/tags" term="legacy" /">
<"/!-- begin snippet: js hide: false console: true babel: false --"/">
"var Component" = function() {
"this.itWorks" = function() {
return=true;
}
};
<"/"!-- end snippet --"/">
I'm a late arrival to the Bower scene. I thought I'd try it with my current Express project. I installed it, and created the .bowercc and bower.json file per instructions. I installed a Bootstrap skin I planned on using, which brought with it jQuery. The thing is, you get tons of files, and I'd like to use just the minified versions of JS, CSS and fonts.
After scowering the net, I found a lot about using gulp or grunt to sift through the files, and pipe them to the /public folder Express provides. My question is: how do you do it properly? How do I get just the files I need there? Or am I better off foregoing bower and just downloading the zip file, picking up the end result and placing in the /public folder?
Looking at the comments, it seems like the answer is yes - manual job is required to get your components distributeables to your public folder. Using gulp will automate it, but basically it'd be a hit-and-miss at first, requiring some fine tuning. In case someone lands on this question, here's the solution I went with:
1) Provide package overrides in the bower.json file to ake sure only the minified files are exposed:
{
"name": "charlie",
"dependencies": {
"bootstrap-material-design": "~0.3.0"
},
"overrides": {
"bootstrap-material-design": {
"main": ["**/dist/js/*.min.js", "**/dist/css/*.min.css", "**/dist/fonts/*"]
},
"jquery": {
"main": "**/dist/jquery.min.js"
}
}
}
2) Use the main-bower-files gulp package to grab those "mains" and distribute them to the final locations. Here's my gulpfile.json (just the bower part:
var bower = require('main-bower-files');
var gulpFilter = require('gulp-filter');
var uglify = require('gulp-uglify');
var minifyCSS = require('gulp-minify-css');
var clean = require('gulp-clean');
var debug = require('gulp-debug');
var getDist = function(vendor) {
var publicDir = 'public';
var dist = vendor ? publicDir + '/vendor' : publicDir;
return {
dir: dist,
css: dist + '/css/',
js: dist + '/js/',
fonts: dist + '/fonts/'
};
};
gulp.task('cleanVendor', function() {
return gulp.src(getDist(true).dir, {read: false})
.pipe(clean());
});
gulp.task('bower', ['cleanVendor'], function() {
var dist = getDist(true);
var jsFilter = gulpFilter('**/*.js');
var cssFilter = gulpFilter('**/*.css');
var fontsFilter = gulpFilter(['**/*.woff*', '**/*.eot', '**/*.svg', '**/*.ttf']);
return gulp.src(bower())
.pipe(fontsFilter)
.pipe(gulp.dest(dist.fonts))
.pipe(fontsFilter.restore())
.pipe(jsFilter)
.pipe(gulp.dest(dist.js))
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe(gulp.dest(dist.css))
.pipe(cssFilter.restore());
});
3) In your HTML file, include /vendor/js/blah.min.js or /vendor/css/blah.min.css
Note: the annoying part was that I had to specify every font extension in the fontsFilter. I tried using '**/fonts/*' but main-bower-files returns a flat list of files, and if you provide the {base: 'mybase'} parameter, it returns a tree, meaning you get the entire tree structure per file - anyone who can come up with a fix, is invited to submit an answer.
I'm trying to figure out how to use browser sync in conjunction with gulp and less to get the browser to automatically update upon changes in less files after compilation. What I've got right now is causing what appears to be a reload in the system with a message "Connected to Browser Sync" but I'm not seeing changes occur in the browser. On a full manual reload with cache disabled I see the expected changes, so the css / less task seems to be working partially but I'm missing something on the browser sync.
Oh, I'm using #import statements in a main .less file to pull in less files for each individual module. Thanks for your time and help!
gulp.task('less', function(){
return gulp.src(basepath + 'styles/emma.less')
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(less())
.pipe(autoprefixer({
browsers: ['last 2 versions']
}))
.pipe(minifyCSS())
.pipe(sourcemaps.write('./'))
.pipe(filesize())
.pipe(gulp.dest( paths.dest + '/css' ))
.pipe(reload({stream: true}));
});
gulp.task('browser-sync', function() {
browserSync({
proxy: 'localhost:8080'
});
});
//dev task to compile things on the fly
gulp.task('dev', ['browser-sync'], function(){
gulp.watch(paths.scripts, ['scripts']);
gulp.watch(paths.less, ['less']);
gulp.watch(paths.templates, ['templates']);
});
A good way to make browserSync work that way is to have a new listener on to the generated files. You compile LESS to CSS,
gulp.task('less', function(){
return gulp.src(basepath + 'styles/emma.less')
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(less())
.pipe(autoprefixer({
browsers: ['last 2 versions']
}))
.pipe(minifyCSS())
.pipe(sourcemaps.write('./'))
.pipe(filesize())
.pipe(gulp.dest( paths.dest + '/css' ));
});
and put a file watcher onto the results, triggering reload:
gulp.task('dev', ['browser-sync'], function(){
gulp.watch(paths.less, ['less']);
gulp.watch(paths.dest + '/css/**/*.css', reload);
});
One reason the original code won't work might be of the lost reference to the source files once they're compiled (that's nothing more than an assumption, though)