I'm trying to get a basic build set up using Gulp and browserify, but keep seeing this error when trying to run the default task:
Error: Cannot find module 'src/js/main.js' from '/Users/ben/dev/git/myapp/'
gulpfile.js
var gulp = require('gulp');
var browserify = require('browserify');
var del = require('del');
var source = require('vinyl-source-stream');
var paths = {
main_js: ['src/js/main.js'],
js: ['src/js/*.js']
};
gulp.task('clean', function(done) {
del(['build'], done);
});
gulp.task('js', ['clean'], function() {
browserify(paths.main_js)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./build/'));
});
gulp.task('watch', function() {
gulp.watch(paths.js, ['js']);
});
gulp.task('default', ['watch', 'js']);
main.js
console.log("Hello!")
myapp/
.
├── gulpfile.js
├── node_modules
│ ├── browserify
│ ├── del
│ ├── gulp
│ └── vinyl-source-stream
├── npm-debug.log
├── package.json
└── src
├── css
├── index.html
└── js
└── main.js
I can't understand why it's failing to find main.js. When I run this command from myapp/, it works fine:
$ browserify src/js/main.js > build/bundle.js
Try using "./src/js/main.js" instead of "src/js/main.js" i.e:
var paths = {
main_js: ['./src/js/main.js'],
js: ['src/js/*.js']
};
Related
I have this project structure:
myApp
├── gulpfile.js
├── package.json
└── source
└── scripts
├── modules
│ └── utils.js
├── background.js
└── data.json
My browserify task:
gulp.task('browserify', function () {
return gulp.src(['./source/scripts/**/*.js'])
.pipe($.browserify({
debug: true,//for source maps
standalone: pkg['export-symbol']
}))
.on('error', function(err){
console.log(err.message);
this.emit('end');
})
.pipe(gulp.dest('./build/scripts/'));
});
My sample utils.js:
const data = require('../data.json');
const utils = (function () {
const output = function () {
console.log(data);
};
return {
output: output,
};
}());
module.exports = utils;
If I try to build it with the current directory structure, I get this error:
module "../data.json" not found from "/dev/myApp/source/scripts/fake_4d8cf8a4.js"
I can only build it, if I put data.json inside the modules directory AND inside the scripts directory, ie. it only works if I duplicate the file:
myApp
├── gulpfile.js
├── package.json
└── source
└── scripts
├── modules
│ ├── utils.js
│ └── data.json
├── background.js
└── data.json
Obviously this is not okay... what am I doing wrong?
Thank you
I'm inferring from your use of gulp.src to pass files to $.browerify that you are using a Gulp plugin, probably gulp-browserify. It is generally not recommended to use a plugin to invoke Browserify from Gulp. The recommended way to do it is to just call Browserify directly. Indeed, Gulp's blacklist of plugins states:
"gulp-browserify": "use the browserify module directly",
I've replicated your directory structure and put some reasonable values for the files for which you did not provide contents (data.json, background.js) and indeed, I get the same error you get when I try to run the Gulp code you show. However, if I switch to calling Browserify directly, I do not get any error. Here is the code I have:
const gulp = require("gulp");
const browserify = require("browserify");
const source = require('vinyl-source-stream');
gulp.task('browserify', function () {
return browserify({
entries: ["./source/scripts/background.js",
"./source/scripts/modules/utils.js"],
debug: true,//for source maps
standalone: "foo",
})
.bundle()
.pipe(source('bundle.js')) // This sets the name of the output file.
.pipe(gulp.dest('./build/scripts/'));
});
You use gulp.src(['./source/scripts/**/*.js']) in your code, which means that Browserify will take all your .js files as entries into the bundle.
So I've put two entries in my code above, which manually replicates the pattern you use with the plugin. However, while Browserify does not produce an error with this setup, I suspect you don't actually want to have multiple entries. Typically, we pass one entry point to Browserify and let it trace the require calls to figure what it needs to pull.
I am trying to copy files from one folder to another folder using Gulp:
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
]).pipe(gulp.dest('./public/assets/css/'));
});
The above code is copying one.css & two.css to the public/assets/css folder.
And if I use gulp.src('./source/css/*.css') it will copy all CSS files to the public/assets/css folder which is not what I want.
How do I select multiple files and keep the folder structure?
To achieve this please specify base.
¶ base - Specify the folder relative to the cwd. Default is where the glob begins. This is used to determine the file names when saving in .dest()
In your case it would be:
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
], {base: './source/'})
.pipe(gulp.dest('./public/assets/'));
});
Folder structure:
.
├── gulpfile.js
├── source
│ ├── css
│ └── other
│ └── css
└── public
└── assets
I use gulp-flatten and use this configuration:
var gulp = require('gulp'),
gulpFlatten = require('gulp-flatten');
var routeSources = {
dist: './public/',
app: './app/',
html_views: {
path: 'app/views/**/*.*',
dist: 'public/views/'
}
};
gulp.task('copy-html-views', task_Copy_html_views);
function task_Copy_html_views() {
return gulp.src([routeSources.html_views.path])
.pipe(gulpFlatten({ includeParents: 1 }))
.pipe(gulp.dest(routeSources.html_views.dist));
}
And there you can see the documentation about gulp-flatten: Link
gulp.task('move-css',function(){
return gulp
.src([ 'source/**'], { base: './' })
.pipe(gulp.dest('./public/assets/css/'));
});
Your own code didn't include the entire dir tree of source 'source/**' and the base {base:'./'} when calling to gulp.src which caused the function to fail.
The other parts where fine.
gulp.task('move-css',function(){
return gulp.src([
'./source/css/one.css',
'./source/other/css/two.css'
]).pipe(gulp.dest('./public/assets/css/'));
});
I am trying to set my project up to use karma/jasmine. This project also uses knockoutjs (shouldn't really matter) and requirejs (really matters). The project structure is a little different from the norm and that's what is giving me issues. I am running this using karma start from the command line.
I tried to follow the karma requirejs setup instructions which I feel got me most of the way there. I can set it up to load the test/spec files correctly or the src files correctly but not both. In its current state, I get the following message:
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:9876/base/app/test/components/home-pageSpec.js
If I change the baseUrl in test-main.js (generated by karma init) from '/base/app' to '/base'it works just fine until I have a relatively address require.
home.js working (no relative require):
define(['jquery'], function ($) {
function HomeViewModel()
{
this.name = 'myName';
}
return {viewModel: HomeViewModel};
});
home.js not working (relative require):
define(['jquery', 'js/services/someService'], function ($, someService) {
function HomeViewModel()
{
this.name = 'myName';
}
return {viewModel: HomeViewModel};
});
Which gives the following error GET http://localhost:9876/base/js/services/programService.js. This is because the resource is really at (or should be at) http://localhost:9876/base/app/js/services/programService.js
.
├── app
│ ├── bower_modules ...
│ ├── components
│ │ ├── home
│ │ │ └── home.js
│ ├── index.html
│ ├── js
│ │ ├── lib ...
│ │ ├── services
│ │ │ └── someService.js
│ │ ├── require.config.js
│ │ ├── router.js
│ │ └── startup.js
├── bower.json
├── gulpfile.js
├── karma.conf.js
├── node_modules ...
├── package.json
├── test
│ └── components
│ └── home-pageSpec.js
└── test-main.js
Please tell me how to fix the relative path stuff please.
karma.conf.js:
// Karma configuration
// Generated on Wed Apr 15 2015 10:07:13 GMT-0400 (Eastern Daylight Time)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
'test-main.js',
//{pattern: 'app/bower_modules/jquery/dist/jquery.js', included: false},
{pattern: 'app/bower_modules/**/*.js', included: false},
{pattern: 'app/js/lib/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false},
{pattern: 'app/components/**/*.js', included: false},
{pattern: 'app/js/services/**/*.js', included: false}
],
// list of files to exclude
exclude: [
'app/bower_modules/**/tests/*',
'app/bower_modules/**/spec/*',
'app/bower_modules/**/meteor/test.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_DEBUG,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
test-main.js:
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
var pathToModule = function(path) {
console.log(path + "********");
var p = path.replace(/^\/base\//, '').replace(/\.js$/, '');
console.log(p + "********");
return p;
};
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(pathToModule(file));
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
paths: {
"jquery": "app/bower_modules/jquery/dist/jquery",
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
home-pageSpec.js:
define(['app/components/home/home'], function(homePage) {
var HomePageViewModel = homePage.viewModel;
describe('Home page view model', function() {
it('should supply a friendly message which changes when acted upon', function() {
expect(1).toEqual(1);
});
});
});
I have a conventional recommended Intern directory structure:
MyProject
├── node_modules
│ ├── intern-geezer
│ │ ├── client.html
├── src
│ ├── myFunction.js
├── tests
│ ├── intern.js
│ ├── unit
│ │ ├── ps.js
with a very simple config:
useLoader: {
'host-node': 'dojo/dojo',
'host-browser': 'node_modules/dojo/dojo.js'
},
loader: {
packages: []
},
suites: [ 'tests/unit/ps' ]
and tests:
define(function (require) {
var tdd = require('intern!tdd');
var assert = require('intern/chai!assert');
// Global function to test, not an AMD module
var parseF = require('src/myFunction.js');
var he = require('tests/he');
tdd.suite('My tests', function() {
//etc
});
});
````
but when I open the browser client the loader is looking for the test suite inside the intern-geezer directory:
I am not setting a baseUrl in the config (or in the browser URL). I didn't have this trouble going through the regular (non-geezer) intern tutorial. Since the baseUrl defaults to two directories up from client.html I don't see what I'm doing wrong. Thanks for any help. (Yes, I will need geezer for ancient IE. No, I do not want to rewrite the function I'm testing as an AMD module.)
The Intern loader doesn't know how to get to your tests because they haven't been registered as a package. When using the recommended directory structure, you'll want to also set up the recommended loader configuration so that Intern knows where to find your code and tests.
loader: {
packages: [
{ name: 'app', location: 'src/' },
{ name: 'tests', location: 'tests/' }
]
}
Then, update your tests to correctly find the code you need to test.
// Global function to test, not an AMD module
var parseF = require('app/myFunction.js');
Now, Intern should be able to correctly find the code and tests.
I'm struggling to make gulp-watch behave as I desire. This small project is tooling to build HTML5 emails templates from Jade+SASS, in a repeatable way. The directory structure is as such:
.
├── Gulpfile.coffee
├── Gulpfile.js
├── build
│ ├── hello-world.html
│ └── styles
│ └── ink.css
├── node_modules
│ ├── ...snip...
├── package.json
└── source
├── hello-world.jade
├── layouts
│ └── default.jade
└── styles
└── ink.scss
My wish list is thus:
Build all templates when styles or templates change. This is what I can't do
Don't have a seaerate "cold" start, always use the gulp incremental build. (This seems to work)
Live reload would reload the browser, that'd be cool. (This too)
The Gulpfile, in CoffeeScript notation for brevity is included below, it's predominantly based on the documentation Incremental rebuilding, including operating on full file sets.
gulp = require 'gulp'
inlineCss = require 'gulp-inline-css'
jade = require 'gulp-jade'
marked = require 'gulp-marked'
plumber = require 'gulp-plumber'
rename = require 'gulp-rename'
sass = require 'gulp-sass'
cached = require 'gulp-cached'
util = require 'gulp-util'
watch = require 'gulp-watch'
webserver = require 'gulp-webserver'
styleGlob = "source/styles/*.scss"
templateAndLayouysGlob = "source/**/*.jade"
templateGlob = "source/*.jade"
styleChangeHandler = (event) ->
if event.type is "deleted"
delete cached.caches.scripts[event.path]
templateChangeHandler = (event) ->
if event.type is "deleted"
delete cached.caches.templates[event.path]
gulp.task "styleWatcher", ->
gulp.src(styleGlob)
.pipe(cached('styles'))
.pipe(watch(styleGlob))
.pipe(sass())
.pipe(gulp.dest("build/styles"))
.on('error', util.log)
gulp.task "templateWatcher", ->
gulp.src(templateGlob)
.pipe(cached('templates'))
.pipe(watch(templateGlob))
.pipe(jade(pretty: true))
.pipe(inlineCss())
.pipe(gulp.dest("build/"))
.on('error', util.log)
gulp.task 'webserver', ->
buildPath = 'build/'
gulp.src(buildPath)
.pipe(webserver({
livereload: true,
directoryListing: {
enable: true,
path: buildPath
},
open: true
}))
gulp.task "watch", ->
styleWatcher = gulp.watch(styleGlob, ["styleWatcher"])
styleWatcher.on 'change', styleChangeHandler
templateWatcher = gulp.watch(templateGlob, ["templateWatcher"])
templateWatcher.on 'change', templateChangeHandler
# I would expect this to fire when something in build/styles/*.css
# is updated by the style watcher?
templateStyleWatcher = gulp.watch('build/styles/*.css', ["templateWatcher"])
templateStyleWatcher.on 'change', templateChangeHandler
gulp.task "default", ["styleWatcher", "templateWatcher", "watch", "webserver"]
If it were possible, and I'd written this watcher in GNU Make or similar, I would have had the option to express that build/, and rely on the tooling to rebuild those files if the ones upon which they depend are out of date.
I've seen that there are a number of gulp-<something about inlining> plugins, but none of them make clear whether they support this conditional recompilation by watching paths that were imported for changes (I doubt it).
Given my background in systems programming, I may well be approaching Javascript build tooling in a completely incorrect way.