I have a demo NPM framework structured as the following:
./src/child.coffee
module.exports = class Child
./src/parent.coffee
Child = require "./child"
module.exports = class Parent
./gulp.js
require('coffee-script/register');
require('./gulpfile.coffee');
./gulp.coffee
gulp = require "gulp"
util = require "gulp-util"
coffee = require "gulp-coffee"
browserify = require "gulp-browserify"
gulp.task "build", ->
gulp.src("./src/**/*.coffee")
.pipe(coffee().on("error", util.log))
.pipe(gulp.dest("./lib/"))
Everything works great if I run gulp build. However, I'm trying to introduce Browserify by adding the following to the build task:
gulp.task "build", ->
gulp.src("./src/**/*.coffee")
.pipe(coffee().on("error", util.log))
.pipe(browserify())
.pipe(gulp.dest("./lib/"))
With that in place the relative requires within the framework fail:
events.js:85
throw er; // Unhandled 'error' event
^ Error: module "./child" not found from "/Users/kevin/Desktop/demo/src/fake_d1543b04.js" at notFound
(/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/index.js:803:15)
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/index.js:754:23
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/browser-resolve/index.js:185:24
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:36:22
at load
(/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:54:43)
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:60:22
at
/Users/kevin/Desktop/demo/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:16:47
at FSReqWrap.oncomplete (fs.js:95:15)
How does one properly setup relative requires within a framework and have it work with gulp and coffeescript? Changing the require to be for a dependency from the package.json (i.e. Lodash = require "lodash") allows gulp to build. Furthermore changing from coffeescript to regular javascript also fixes the problem.
The problem is likely the .coffee extension. You need to instruct browserify to look for that extension. See opts.extensions. I don't know how you'd do that with gulp-browserify, but you're better off not using it anyway (it's blacklisted by gulp, if that matters to you, and I believe it's unmaintained).
Related
I recently npm installed the node module react-calendar-timeline .
After implementing it one of my components, I ran gulp to build.
gulp threw an error:
events.js:141
throw er; // Unhandled 'error' event
^
SyntaxError:
/var/www/monitor/node_modules/react-calendar-timeline/modules/lib/Timeline.scss:1
$item-color: white;
^
ParseError: Unexpected token
My gulpfile file for this component looks like this:
var gulp = require('gulp');
var browserify = require('gulp-browserify');
var concat = require('gulp-concat');
var babel = require('gulp-babel');
gulp.task('browserify', function() {
gulp.src('js/ScheduleMain.js')
.pipe(browserify({transform:'babelify'}))
.pipe(concat('ScheduleMain.js'))
.pipe(gulp.dest('static/dist/js'));
It seems as though I am not able to handle the .scss file of the module I have installed. What is the proper way to handle this?
It could be an issue related more to gulp-browserify than your build script.
Keep in mind that gulp-browserify is long dead, in fact it's been more than an year since the last update; this is from it's npm page:
NOTE: THIS PLUGIN IS NO LONGER MAINTAINED , checkout the recipes by gulp team for reference on using browserify with gulp.
Browserify natively supports streming and with just a pair of plugins you can trasform that stream to be gulp compatible, I suggest you to take a look at gulp's examples folder, more specifically to this example using browserify.
By the way, what's the point in running gulp-concat when in your stream theres only one file?
I can't get bundles to work in the optimized build, I'm trying to load some external pre-built bundle (not included in the require build process output).
In requirejs.config:
paths: {
'mymodules': '../lib/test-bundle/test-bundle'
},
bundles: {
'mymodules': ['mymodule1', 'mymodule2']
}
test-bundle content is:
console.log("defining modules...");
define('mymodule1', ['jquery'], function($) {
console.log('within mymodule1', $.fn.jquery);
return {
test: 'module1'
};
});
define('mymodule2', ['jquery'], function($) {
console.log('within mymodule2', $.fn.jquery);
return {
test: 'module2'
};
});
In the build config paths for mymodules, mymodule1 and mymodule2 are set to empty: (or the build process fail), I'm not using the modules option in the build config to generate bundles.
If I use the sources as they are everything is working fine, as expected.
In the built version (but not optimized) test-bundle is loaded and "defining modules" printed, then timeout loading mymodule2:
Error: Failed to load root module (viewmodels/shell). Details: Load timeout for modules: mymodule2(…)
Uncaught Error: Failed to load root module (viewmodels/shell). Details: Load timeout for modules: mymodule2
http://requirejs.org/docs/errors.html#timeout
In the built and optimized version there's one more error:
Uncaught ReferenceError: define is not defined
like if test-bundle is loaded before requirejs implement define().
What I'm missing or doing wrong?
edit
I've created a branch with the test above to install and build (nodejs npm and probably grunt-cli are required on the system)
git clone https://github.com/xenogenesi/HTMLStarterKitPro
cd HTMLStarterKitPro
git checkout test-bundle
# nodejs npm required on the system (maybe grunt-cli)
npm install # required only once to install node modules
grunt build-only # create a build/ directory and the content
php -S localhost:8888 # to publish the sources as they are
# browse to http://localhost:8888
php -S localhost:7777 -t build # to publish the built versions
# browse to http://localhost:7777 for built but not optimized
# browse to http://localhost:7777/index2.html for built optimized
(see this commit for all files modified to add the test-bundle)
You can only use one define per file. If you want to use anyway, there is a bundle configuration option that you can say that a module is inside an already bundled file as yours.
As it states:
bundle config is for pointing multiple module IDs to a bundle's module ID.
So, apparently even being require.js itself, the loader once included in the optimized version is or at least behave in a different way.
One simple way to get it working is to not include any loader and keep using require to kickstart:
Gruntfile.js:
- name: 'requireLib',
+ name: false,
index2.html:
- <script src="app/main-built.js"></script>
+ <script src="lib/require/require.js" data-main="app/main-built"></script>
Still, if somebody know how to include the loader and get pre-built external bundles (multiple modules in one file) working, I'd like to know and will accept as answer.
I'd like to avoid the complex relative path issue described here by using one of the recommended solutions. I've come across three similar libraries:
rekuire
node-rfr aka Require from Root
requirish
I've tried all three and all are failing with "module not found" or a similar error which makes me believe I'm doing something fundamentally wrong. I'm relatively inexperienced with npm/node. I'm only using node in the browser using browserify to bundle my app into a single JS file.
Here's my extremely simple hello world example:
Structure:
lib/Bob.js
app.js
Bob.js
function Bob() {
return "I am bob";
}
module.exports = Bob;
app.js
var Bob = require('./lib/Bob.js');
console.log(Bob());
Bundling into a single JS:
browserify app.js -o bundle.js
Chrome's console successfully outputs "I am Bob".
Now if I try and of the libraries, let's say requirish:
REQUIRISH:
npm install requirish
app.js changes
'use strict';
require('requirish')._(module);
var Bob = require('lib/Bob');
console.log(Bob());
Bundling changes
browserify -t requirish app.js > bundle.js
I get the following error:
Error: Cannot find module '/lib/Bob' from '/Users/ngb/projects/MyApp/src/main/resources/public/js/hello'
at /Users/ngb/.nvm/v0.10.30/lib/node_modules/browserify/node_modules/resolve/lib/async.js:42:25
RFR:
'use strict';
var rfr = require('rfr');
var Bob = rfr('lib/Bob');
console.log(Bob());
Building
browserify app.js -o bundle.js -d
Chrome's console outputs the following error:
Uncaught Error: Cannot find module 'lib/Bob'
The Browserify can find module by parse string "require".
If you want to use both side client and server, use rfr for server side and browserify-rfr for browserify's transform.
In my opinion, the "rfr" is the best because this module does not override original require.
------- Notice! Additional Information,
As today browserify-rfr version leaves my local file path to bundle.js. This may cause another problem, so I chose requirish. Since the requirish changes behavior of original require by pushing a new path to module.paths, you always notice that and alert your coworker!
thanks!
https://www.npmjs.com/package/requirish
The Browserify docs section on external requires shows how to make a module within a bundle available to the global environment:
browserify -r through -r duplexer -r ./my-file.js:my-module > bundle.js
But I'm having trouble configuring this to work with Grunt-Browserify.
The -r flag seems to correspond to the require option in Grunt-Browserify, but the docs description for this option doesn't make any mention of external requires or exporting a require() function.
In my Gruntfile, I've tried setting the require option to the module I need to expose (which is already in the bundle, by the way):
options: {
require: ['./dev/js/foomod.js'],
}
And then in my page script, I try to require() the module as shown in the docs:
<script>
var Foomod = require('./foomod.js');
Foomod.init({foo: 'bar'});
</script>
But that logs the error require is not defined.
My goal is to call the module's init() method as shown so that I can pass in runtime data without putting it in a window global.
Using browserify version 5.11.1 and grunt-browserify version 3.0.1, I have managed to get similar setup to work:
options:{
preBundleCB: function (b) {
b.require("./dev/js/foomod.js",{expose: 'foomod'});
}
}
I am writing some extensions to lodash. The code related to this question can be download from here. The structure is that code is located in /shared/modules/myExtensions.js. Currently, my code is very basic and looks like this:
'use strict';
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
My code will grow in complexity. For that reason, I want to setup unit tests from the start on this. Right now, my tests are located at /shared/tests/myExtensions.tests.js. That file looks like this:
'use strict';
describe('myModule', function() {
it('should work', function() {
expect(true).toBe(true);
});
});
This test always asserts to true. I'm trying to execute this Jasmine test via grunt. When I execute the this via Grunt, I get an error. The error confuses me because the grunt-jasmine-node module is defined in my package.json file. I've also checked that it got downloaded when I ran npm install. Either way, here is the error:
>> Local Npm module "grunt-jasmine-node" not found. Is it installed?
Running "jasmine:testShared" (jasmine) task
Testing jasmine specs via PhantomJS
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\g.js:1
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\usr-local.js:1
>> ReferenceError: Can't find variable: module at
>> ..\..\C:\Tests\jasmine\node_modules\glob\glob.js:37
>> Error caught from PhantomJS. More info can be found by opening the Spec Runner in a browser.
Warning: SyntaxError: Parse error Use --force to continue.
Aborted due to warnings.
This is so frustrating. My code can be downloaded from here. I've been working on this for 2 days now. If I don't get it done today, I'll have to go back to .NET. Can someone please help me get this resolved? I really want to keep moving in this direction. I believe this is just something really small.
grunt-jasmine-node is not defined in your package.json as Andy pointed out.
You can define and install it using the command npm-install --save grunt-jasmine-node that will fix that error.
This issue might be related https://github.com/gruntjs/grunt/issues/232.
Also you might want to seperate your dev dependencies and normal dependencies.
npm install --save-dev module includes the module in 'devDependencies' config, and
npm install --save module includes the module in dependencies config, in package.json.
I hope this will fix your problem, i am looking for that 500 bounty.
Edit
Edit:
Also it appears to me that you are mixing your client libraries with the server sides.
Namely you include vendor path like this:
File: tasks/options/jasmine.js
options: {
specs: "shared/tests/unit/**.tests.js",
// server libs
vendor: "node_modules/**/*.js",
// should be browser libs
// vendor: "shared/libs/lodash/dist/lodash.js",
}
All your node_modules folder gets included inside the browser.
Really what you should be doing is define your libraries in shared/libs
and use that path for the vendor option.
You can use bower to automatically install them.
And finally your actual code,
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
This is again server side code, that gets loaded into the browser.
You should write this for the browser.