My browserify workflow (from coffee to js, with browserify-shim and coffeeify) is like this:
I have 2 main files, app.coffee and _app.coffee, respectively for frontend and backend. Both files located in resources/coffee/front and resources/coffee/back (respectively). I'm trying to include browserify task in laravel elixir so the result file will be on public/js/app.js and public/js/_app.js and can be revision to the build folder later.
So far, I have tried to extend the elixir by creating a browserify.js file in elixir's node_modules ingredients folder. The content is:
var gulp = require('gulp');
var browserify = require('browserify');
var watchify = require('watchify');
var source = require('vinyl-source-stream');
var logger = require('../../../gulp/util/bundleLogger');
var errors = require('../../../gulp/util/handleErrors');
var config = require('../../../gulp/config').browserify;
elixir.extend('browserify', function(callback) {
var bundleQueue = config.bundleConfigs.length;
var browserifyThis = function(bundleConfig) {
var bundler = browserify({
cache: {},
packageCache: {},
fullPaths: true,
entries: bundleConfig.entries,
extensions: config.extensions,
debug: config.debug
});
var bundle = function() {
logger.start(bundleConfig.outputName);
return bundler
.bundle()
.on('error', errors)
.pipe(source(bundleConfig.outputName))
.pipe(gulp.dest(bundleConfig.dest))
.on('end', finished);
}
if (global.isWatching) {
bundler = watchify(bundler);
bundler.on('update', bundle);
}
var finished = function() {
logger.end(bundleConfig.outputName);
if (bundleQueue) {
bundleQueue--;
if (bundleQueue === 0) {
callback();
}
}
}
return bundle();
};
config.bundleConfigs.forEach(browserifyThis);
});
Config for browserify is:
browserify: {
debug: true,
extensions: ['.coffee'],
watch: './resources/assets/coffee/{front,back}/**/*.coffee',
bundleConfigs: [
{
entries: './resources/assets/coffee/front/app.coffee',
dest: './public/js',
outputName: 'app.js'
},
{
entries: './resources/assets/coffee/back/app.coffee',
dest: './public/js',
outputName: '_app.js'
}]
}
Then in my gulp elixir task, I do this:
var gulp = require('gulp');
var elixir = require('laravel-elixir');
gulp.task('elixir', function() {
return elixir(function(mix) {
mix.sass('app.scss').browserify().version(['.public/css/app.css', './public/js/app.js', '.public/js/_app.js']);
});
});
This does not work because the callback function is not included in elixir (originally it is gulp's). Even if it is, the elixir watch will not listen to my original .coffee files (I'm trying to watch the entire coffee file located in resources/coffee/**/*.coffee).
So what I have thought as a solution is to re-run the entire elixir procedure if the file changed, like:
gulp.task('default', function() {
runSequence('coffeelint', 'browserify', 'elixir', 'images', 'watch');
});
and my watch task:
gulp.task('watch', function() {
gulp.watch(config.browserify.watch, ['coffeelint', 'default']);
gulp.watch(config.images.src, ['images']);
});
But the error is that, it says that sass() function in elixir cannot be linked to browserify(). Any idea how to do this?
Laravel elixir comes bundle with browserify so no need to do a require of browserify what you can do is
elixir(function(mix) {
mix.browserify(['main.js'],
'output directory',
'base-directory-if-different-from-public-folder');
});
You can't combine them, but you can run both.
//gulp.js in the root folder
var elixir = require('laravel-elixir');
var browserify = require('browserify');
elixir(function(mix) {
mix.sass(['app.scss'], 'public/css');
});
elixir(function(mix) {
mix.browserify(['app.js'], 'public/js');
});
Related
I dont know why i am receiving this error AssertionError [ERR_ASSERTION]: Task function must be specified GULP (node js , keystone js ). What causes this error ? anyone can help ?. I am using keystone app and sass compilation?. gulp file that will restart keystonejs app and compile sass. Is this regarding on the gulp version my goal version in my package.json is "gulp": "^4.0.2",.
My Gulp file
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var jshintReporter = require('jshint-stylish');
var watch = require('gulp-watch');
var sass = require('gulp-sass');
var shell = require('gulp-shell')
var bs = require('browser-sync').create();
var paths = {
'src':['./models/**/*.js','./routes/**/*.js', 'keystone.js', 'package.json'],
'style': {
all: './public/styles/**/*.scss',
output: './public/styles/'
}
};
// gulp lint
gulp.task('lint', function(){
gulp.src(paths.src)
.pipe(jshint())
.pipe(jshint.reporter(jshintReporter));
});
// gulp watcher for lint
gulp.task('watch:lint', function () {
gulp.src(paths.src)
.pipe(watch())
.pipe(jshint())
.pipe(jshint.reporter(jshintReporter));
});
gulp.task('sass', function(){
gulp.src(paths.style.all)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(paths.style.output))
.pipe(bs.stream());
});
gulp.task('watch:sass', function () {
gulp.watch(paths.style.all, ['sass']);
});
gulp.task('browser-sync', function(){
bs.init({
proxy: 'http://localhost:3000',
port: '4000'
});
});
gulp.task('runKeystone', shell.task('node keystone.js'));
gulp.task('watch', ['watch:sass', 'watch:lint']);
gulp.task('default', ['watch', 'runKeystone', 'browser-sync']);
I've got a Gulp task using browserify and watchify. As you can see I've got four files. modules.js uses the class from overlay-model.js.
But browserify doens't keep the order I'm passing. Instead of that browserify puts the files in alphabetical order so it first uses modules.js.
I'll tried looking for a solution gulp sort doens't seem to work and I can't find a browserify-ish solution.
Anyone knows something about this?
var gulp = require('gulp');
var gutil = require('gulp-util');
var c = gutil.colors;
var sort = require('gulp-sort');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var watchify = require('watchify');
var babel = require('babelify');
function compile(watch) {
var bundler = watchify(browserify([
'./assets/js/overlay-model.js',
'./assets/js/slider.js',
'./assets/js/words.js',
'./assets/js/modules.js'
], {
debug: true
})
.transform(babel.configure({
presets: ['es2015']
})));
function rebundle() {
bundler.bundle()
.on('error', function(err) { console.error(err); this.emit('end'); })
.pipe(source('build.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./public'));
}
if (watch) {
gutil.log(`${c.cyan('scripts')}: watching`);
bundler.on('update', function() {
gutil.log(`${c.cyan('scripts')}: processing`);
rebundle();
});
}
rebundle();
}
function watch() {
return compile(true);
};
gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });
gulp.task('scripts', ['watch']);
I think typically you'll have just one entry point (modules.js in your case) that'll use require(...) to load other modules in order you want.
// modules.js
require('./overlay-model');
require('./slider');
require('./modules');
Then use browserify like:
browserify('./assets/js/modules.js', ...);
In my gulp file to inject bower components I have this bad style code duplication. But I do not have any ideas how to get rid of it.
Generally speaking we cannot say just bower_components/**/*.js because we don't want to import all files, plus for production we want to import just .min files. Again. I cannot guaranty that every package I use have .js and .min.js files. So just *.js and *.min.js may not work.
gulp.task('inject', () => {
let sources = gulp.src([
// jquery
'public/bower_components/jquery/dist/jquery.js',
// bootstrap
'public/bower_components/bootstrap/dist/js/bootstrap.js',
'public/bower_components/bootstrap/dist/css/bootstrap.css',
// angular
'public/bower_components/angular/angular.js',
'public/bower_components/angular/angular-csp.css',
// angular route
'public/bower_components/angular-route/angular-route.js',
],{read: false});
let min_sources = gulp.src([
// jquery
'public/bower_components/jquery/dist/jquery.min.js',
// bootstrap
'public/bower_components/bootstrap/dist/js/bootstrap.min.js',
'public/bower_components/bootstrap/dist/css/bootstrap.min.css',
// angular
'public/bower_components/angular/angular.min.js',
'public/bower_components/angular/angular-csp.css',
// angular route
'public/bower_components/angular-route/angular-route.min.js',
],{read: false});
return gulp.src('public/build/index.html')
.pipe(gulpif(!argv.production, inject(sources, {relative: true})))
.pipe(gulpif(argv.production, inject(min_sources, {relative: true})))
.pipe(gulp.dest('public/build/'));
});
But this code duplication isn't solution. I think. How can I improve this part, besides to move this two array in bower.js file ?
Maybe you can use config.js. Use var config = require('../config'); to read the variables in config.js so you can separate file paths and task.
If you want to separate .js and .min.js , you can use
'src' : [
'src/**/*.js',
'!src/**/*.min.js',
]
For example below I concat .min.js / .js files and uglify it, and also concate .css files and use cssnano() to compress it. In the end vendor task will output vendor.bundle.js and vendor.bundle.css
config.js:
'use strict';
module.exports = {
'vendor': {
'scripts': {
'src': [
'bower_components/jquery/dist/jquery.min.js',
'bower_components/lodash/dist/lodash.min.js',
// Moment
'bower_components/moment/min/moment.min.js',
'bower_components/moment/locale/zh-tw.js',
// Ionic & Angular
'bower_components/ionic/js/ionic.bundle.min.js',
'bower_components/ngCordova/dist/ng-cordova.min.js'
// ...
],
'dest': 'www/js',
'output': 'vendor.bundle.js'
},
'styles': {
'src': [
// Mobiscroll
'bower_external/mobiscroll/css/mobiscroll.custom-2.17.0.min.css',
],
'dest': 'www/css',
'output': 'vendor.bundle.css'
}
}
}
}
vendor.js
'use strict';
var config = require('../config');
var gulp = require('gulp');
var gulpif = require('gulp-if');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var postcss = require('gulp-postcss');
var cssnano = require('cssnano');
var handleErrors = require('../util/handleErrors');
var browserSync = require('browser-sync');
var pkg = require('../../package.json');
gulp.task('vendorScripts', function () {
return gulp.src(config.vendor.scripts.src)
.pipe(concat(config.vendor.scripts.output))
.pipe(uglify())
.pipe(gulp.dest(config.vendor.scripts.dest));
});
gulp.task('vendorStyles', function () {
return gulp.src(config.vendor.styles.src)
.pipe(concat(config.vendor.styles.output))
.pipe(postcss([ cssnano() ]))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(config.vendor.styles.dest));
});
gulp.task('vendor', ['vendorScripts', 'vendorStyles']);
Below is my current Gulpfile.js and when I'm attempting to run gulp minify I'm getting the error, "Task 'minify' is not in your gulpfile". However, I'm able to run gulp sass with no issues. I also have each module installed with npm.
module.exports = function(gulp) {
'use strict'
var sass = require('gulp-sass');
var browserSync = require('browser-sync');
var cssnano = require('gulp-cssnano');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
gulp.task('sass', function() {
return gulp.src('app/scss/**/*.scss')
.pipe(sass())
.pipe(gulp.dest('app/css'))
.pipe(browserSync.reload({
stream: true
}))
});
gulp.task('minify', function() {
return gulp.src('app/css/**/*.css')
.pipe(cssnano())
.pipe(concat('style.min.css'))
.pipe(gulp.dest('app/css/min'))
.pipe(browserSync.reload({
stream: true
}))
});
gulp.task('watch', ['browserSync', 'sass', 'cssnano'], function() {
gulp.watch('app/scss/**/*.scss', ['sass']);
gulp.watch('app/*.html', browserSync.reload);
gulp.watch('app/js/**/*.js', browserSync.reload);
});
gulp.task('browserSync', function() {
browserSync({
server: {
baseDir: 'app/'
},
})
})
}
You should not treat the gulpfile.js as a node module and drop the following part
module.exports = function(gulp) {
(don't forget to remove the closing curly (}) at the end of the gulpfile.js)
Then, you should require gulp
var gulp = require('gulp');
That should make it run smoothly.
Why it does run your gulp sass, I don't know. I just created a simple test file in a fresh directory, and it didn't recognise the sass task for me. Maybe you installedgulp, sass or both globally at some point (e.g. earlier project).
I have the following gulpfile
var gulp = require('gulp');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var coffee = require('gulp-coffee');
var cache = require('gulp-cached');
var path = require('path');
var dist = './Test/public/';
var assets = './Test/assets/';
var paths = {
coffee: ['./**/*.coffee']
};
var coffeeTask = function () {
console.log('coffeeTask');
return gulp.src(paths.coffee, { cwd: assets + '**' })
.pipe(cache('coffee'))
.pipe(coffee({ bare: true }))
.pipe(rename({
extname: ".coffee.js"
}))
.pipe(gulp.dest(dist));
};
gulp.task('clean', function() {
return gulp.src(dist)
.pipe(clean());
});
gulp.task('coffee', ['clean'], coffeeTask);
gulp.task('coffee-watch', coffeeTask);
gulp.task('build', ['clean', 'coffee']);
gulp.task('watch', ['build'], function() {
var w = gulp.watch(paths.coffee, ['coffee-watch']);
w.on('change', function(evt) {
console.log(evt);
});
});
gulp.task('default', ['build']);
The key point of this configuration is use the same tasks for deploy and watch processes (read "build" and "watch" tasks).
The problem is that watch task doesn't catche any new coffee files. Edited or removed coffee files are processed well. According the following issue it should works. What the reason is?
Solved by using gulp-watch module:
watch(paths.coffee, function(evt) {
gulp.start('coffee-watch');
});
The question no is how to remove in dist folder deleted file in assets folder?