How do I use a NodeJS package with RequireJS? - javascript

I would like to use the the node-bencoding package with my current RequireJS project setup, but I have been unable to get it configured.
I have followed these instructions and have ran:
npm install requirejs
npm install node-bencoding
Then in my app.js file I had changed it:
var requirejs = require('requirejs');
// Place third party dependencies in the lib folder
//
// Configure loading modules from the lib directory,
// except 'app' ones,
requirejs.config({
nodeRequire: require,
"baseUrl": "assets/js/lib",
"paths": {
"app": "../app",
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min",
"angularjs": "https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min"
},
});
However when I load the page I get the error:
Error: Module name "requirejs" has not been loaded yet for context: _. Use require([]) http://requirejs.org/docs/errors.html#notloaded
I'm not exactly sure where I should have my node_modules directory. My directory structure is as follows: all my JS files are contained within src/assets/js - there is assets/js/app and assets/js/lib as is the RequireJS convention. Currently I have put my node_modules directory in src/.

Looks like you are trying to use it in a browser. And your application is not server side JavaScript, so RequireJS usage sample in a Node does not apply. In this case you would like to use node only to optimize your scripts.
I recently blogged about Understanding AMD & RequireJS, it might be useful.

Related

Accessing module.exports with a browserified node app

We are trying to Browserify our node app
Sample File (index.js)
module.exports = {
index: () => 'test',
};
Browserify command
browserify src/index.js > dist/bundle.js --node
If we use a file to require and console
console.log(require('src/index')); // { index: [Function: index] }
console.log(require('dist/bundle')); // { }
Our expectation is that bundle.js would export the same as index.js.
Can anyone point us at what we are doing wrong or missing?
Additional Info
~This is not our app, this is a sample to demonstrate the issue
We are currently sending our entire app zipped to AWS Lambda with the entry point src/index.index and the objective is to just send the bundle.js file and be able to to have the entry point bundle.index
bundle.js
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports = {
index: () => 'test',
};
},{}]},{},[1]);
You need to use the --standalone flag. If I reproduce the setup you describe in your question and execute:
$ browserify src/index.js --standalone mylib > dist/bundle.js
Then I can run an interactive Node session on it and use the library in the way you expect it to be used:
$ node
> require("./dist/bundle").index()
'test'
The --standalone flag tells Browserify to wrap your code in a UMD stub which allows loading the bundle as CommonJS module, an AMD module, or as a plain script (i.e. does not use a module system). The argument you pass with --standalone indicates what name your library will take in the "plain script" case. So in the example above, if you were to load the library in a browser without any module system, you'd be able to run index as mylib.index().
You can use serverless for this, pretty easy to configure. No need to use browserify cli for this.
Keep following following official documentations to setup serverless cli.
Installation
AWS - Credentials
Quick Start
Once everything is setup and you are able to deploy your lambda functions to AWS using serverless cli. Follow following steps to setup browserify.
Install browserify as a dev dependecy.
Install serverless-plugin-browserifier as a dev dependency.
Add the plugin to your serverless.yml file and set package.individually to true. (Ref)
plugins:
- serverless-plugin-browserifier
package:
individually: true
Note: Personally tried this and is working.

Bundling Jquery and other modules with webpack

Noob here (also couldn't find proper documentation).
So I was trying to implement gulp.js with jekyll. In order to do so, I wanted to concat javascript files into a single bundle. Now I can do that by hand, hard-coding every dependency and piping it through gulp-concat. But, I found out webpack does this thing pretty neatly. (PS: I was following https://ixkaito.github.io/frasco/). So now I installed webpack via npm, and tried to run my site, but it threw uncaught expression error. My directory tree is like this:
-js
----vendor
-------jquery.js
-------anime.js
----other
-------some-other-js-files.js
...
-main.js
Now I want to make bundle.js files using this, so that webpack can automatically detect the correct dependency and import it. Am I supposed to require('jquery') and do the same for all dependency in main.js?
My webpack config is
entry: [
"main.js",
]
Thanks

Error: Can't resolve lodash-mixins in typescript angular2

I'm trying to add custom functionality to extend lodash (note lodash
is npm'ed in). But I keep getting a resolve error.
I've added a new file called lodash-mixins.js to my test project scripts folder e.g: project/frontend/src/web/Scripts/
var _ = require('lodash');
_.mixin({
mixinLoaded function () { console.log("lodash mixins are loaded");}
});
module.exports = _;
Overview Folder Structure (simplified)
project/frontend/src/web
...frontend.web.csproj
...angular-cli.json
project/frontend/src/web/Scripts/
...lodash-mixins.js
project/frontend/src/web/app/
...app.module.ts
I've manually added my "lodash-mixins.js" to the "angular-cli.json"
"apps": [
{
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
etc
"../node_modules/lodash/lodash.min.js",
"../Scripts/lodash-mixins.js", // <<<<< not picking up
"../Scripts/global-error-handler.js",
],
Test by changing existing reference in one of my test.service.ts
from:
"import * as _ from 'lodash';"
to:
"import * as _ from 'lodash-mixins';"
I've rebuilt my c# solution for good measure.
Run in CLI: $ng build --watch
ERROR in project/frontend/src/web/app/test/services/test.service.ts
Module not found: Error: Can't resolve 'lodash-mixins
Any ideas?
You're confusing two different things here.
1) The "scripts" config for Angular CLI tells WebPack to include those JavaScrip files in the output bundle. It doesn't add those as importable modules. They get loaded as if you added <script src="..."> tags to your HTML file (not exactly accurate, but gives the idea).
2) When you import using TypeScript it searches for the module. The reason it's giving the error is because the file isn't in one of the search paths. Had it actually found the file. It would have loaded it twice. Since you've already added it to the "scripts" config option.
JQuery, Lodash, etc.. etc.. can be loaded using modules or just plain global variables. When you add it to the "scripts" config, then I think this tells WebPack to load it in the global browser space.
When you use "import _ from 'lodash'" in TypeScript. You're actually resolving to the "#types/lodash" module which people often install so that TypeScript knows about the interface for lodash. When WebPack bundles everything for the browser it swaps out the #types for the real reference to the lodash instance.
So you have a couple of options.
1) Continue with what you've done. Add TypeScript definition file in the import path for your new module named "lodash-mixin". That module just defines the new interface with the new methods. The import will find that file and use it to compile the TypeScript, but the WebPack bundle will load your JS file in it's place.
2) Remove your "lodash-mixin" from the "scripts" config, then import using a relative path import _ from '../Scripts/lodash-mixins'. This is what I usually do. Note: You might have to add the file extension ".js"
3) Add your "Scripts" folder to your tsconfig.json as one of the type roots. This allows you to just use import _ from 'lodash-mixins'.
4) There is a way (and I forget exactly how), but you can tell TypeScript to alias lodash to your lodash-mixin so that all imports use that type instead. I don't recommend this approach.

How to install and configure Syncfusion JavaScript with Aurelia CLI?

How do I configure Syncfusion JavaScript for use with Aurelia via Aurelia CLI?
Here is how Syncfusion JavaScript configured when used with jspm (via http://aurelia-ui-toolkits.github.io/demo-syncfusion/#/installation):
Open config.js and add a couple of path mappings:
paths: {
"*": "src/*",
"github:*": "jspm_packages/github/*",
"npm:*": "jspm_packages/npm/*",
"common/ej.*": "jspm_packages/github/syncfusion/JavaScript-Widgets#14.1.0.41/scripts/ej/common/ej.*.js", <----
"datavisualization/ej.*": "jspm_packages/github/syncfusion/JavaScript-Widgets#14.1.0.41/scripts/ej/datavisualization/ej.*.js", <----
"ej.*": "jspm_packages/github/syncfusion/JavaScript-Widgets#14.1.0.41/scripts/ej/web/ej.*.js", <----
"syncfusion-javascript/*": "jspm_packages/github/syncfusion/JavaScript-Widgets#14.1.0.41/*" <----
},
"map": {
"aurelia-bootstrapper": "npm:aurelia-bootstrapper#1.0.0-beta.1",
"aurelia-fetch-client": "npm:aurelia-fetch-client#1.0.0-beta.1",
"aurelia-framework": "npm:aurelia-framework#1.0.0-beta.1.0.2",
"jquery": "npm:jquery#2.2.3", <----
"jquery.min": "npm:jquery#2.2.3", <----
"jquery-easing": "npm:jquery.easing#1.3.2", <----
"jquery-validation": "npm:jquery-validation#1.15.0", <----
"jquery-validation-unobtrusive": "npm:jquery-validation-unobtrusive#3.2.6", <----
"jsrender": "npm:jsrender#0.9.75", <----
}
Check out the Aurelia CLI documentation on how to add libraries to your project.
Your basic steps will probably be to install the package via npm:
npm install syncfusion-javascript --save
That will add the package to your project.json file and have it downloaded.
Next you're going to want to configure your aurelia.json file. Because SyncFusion is not modular, and is really just a library of files, there is no way to just reference a package and have it bundled. What you'll have to do is create a package for each of the packages you're using.
Or, alternate solution, create your own javascript "main" file that references all the modules in the package you want, and set that as the "main" in the package description
{
"name": "syncfusion-javascript",
"path": "../node_modules/syncfusion-javascript",
"main": "syncFusionCustomMain"
}
Your syncFusionCustomMain.js file would import the files from the node_modules folder, and then export the functions to be referenced appropriately.
Sorry this is kind of bad news for you. This package is just not loader friendly, and as of right now, the CLI doesn't have support for just defining paths (since everything gets bundled, it needs to have everything be explicit at compile time).

Working project structure that uses grunt.js to combine JavaScript files using RequireJS?

I have some projects that use RequireJS to load individual JavaScript modules in the browser, but I haven't optimized them yet. In both development and production, the app makes a separate request for each JavaScript file, and now I would like to fix that using Grunt.
I have tried to put together a simple project structure to no avail, so I'm wondering if someone can provide a working example for me. My goals are the following:
In development mode, everything works in the browser by issuing a separate request for each required module. No grunt tasks or concatenation are required in development mode.
When I'm ready, I can run a grunt task to optimize (combine) all of the JavaScript files using r.js and test that out locally. Once I'm convinced the optimized application runs correctly, I can deploy it.
Here's a sample structure for the sake of this conversation:
grunt-requirejs-example/
grunt.js
main.js (application entry point)
index.html (references main.js)
lib/ (stuff that main.js depends on)
a.js
b.js
requirejs/
require.js
text.js
build/ (optimized app goes here)
node_modules/ (necessary grunt tasks live here)
Specifically, I'm looking for a working project structure that I can start from. My main questions are:
If this project structure is flawed, what do you recommend?
What exactly needs to be in my grunt.js file, especially to get the r.js optimizer working?
If all of this isn't worth the work and there's a way to use the grunt watch task to automatically build everything in development mode every time I save a file, then I'm all ears. I want to avoid anything that slows down the loop from making a change to seeing it in the browser.
I use the grunt-contrib-requirejs task to build project based on require.js. Install it inside your project directory with:
npm install grunt-contrib-requirejs --save-dev
BTW: --save-dev will add the package to your development dependencies in your package.json. If you're not using a package.json in your project, ignore it.
Load the task in your grunt file with:
grunt.loadNpmTasks('grunt-contrib-requirejs');
And add the configuration to your grunt.initConfig
requirejs: {
production: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
out: "path/to/optimized.js"
}
}
}
Now you're able to build your require.js stuff into a single file that will be minimized with uglifyjs by running grunt requirejs
You can bundle a set of different tasks into some sort of main task, by adding this to your grunt file
grunt.registerTask('default', ['lint', 'requirejs']);
With this, you can simply type grunt and grunt will automatically run the default task with the two 'subtasks': lint and requirejs.
If you need a special production task: define it like the above
grunt.registerTask('production', ['lint', 'requirejs', 'less', 'copy']);
and run it with
grunt production
If you need different behaviors for 'production' and 'development' inside i.e. the requirejs task, you can use so called targets. In the configuration example above it's already defined as production. You can add another target if you need (BTW, you can define a global config for all targets by adding a options object on the same level)
requirejs: {
// global config
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js"
},
production: {
// overwrites the default config above
options: {
out: "path/to/production.js"
}
},
development: {
// overwrites the default config above
options: {
out: "path/to/development.js",
optimize: none // no minification
}
}
}
Now you can run them both at the same time with grunt requirejs or individually with grunt requirejs:production, or you define them in the different tasks with:
grunt.registerTask('production', ['lint', 'requirejs:production']);
grunt.registerTask('development', ['lint', 'requirejs:development']);
Now to answer your questions:
I would definitely use a subfolder in your project. In my case I use a 'src' folder for development that is build into a 'htdocs' folder for production. The project layout I prefere is:
project/
src/
js/
libs/
jquery.js
...
appname/
a.js
b.js
...
main.js // require.js starter
index.html
...
build/
... //some tmp folder for the build process
htdocs/
... // production build
node_modules/
...
.gitignore
grunt.js
package.json
see above
You can do so, but I wouldn't recommend to add requirejs to the watch task, it's a resource hungry task and it will slow down your machine noticeable.
Last but not least: Be very cautious when playing around with r.js. Especially when you want to optimize the whole project with r.js by adding a modules directive to your config. R.js will delete the output directory without asking. If it happens that it is accidentally configured to be your system root, r.js will erase your HDD. Be warned, I erased my whole htdocs folder permanently some time ago while setting up my grunt task... Always add keepBuildDir:true to your options when playing around with the r.js config.

Categories