How to configure jsLoader in angular ocLazyLoad latest version. - angularjs

Earlier versions of angular oclazyload had an option to configure asyncLoader to use webpack bundle loader as its script loader.
app.config(['$ocLazyLoadProvider', function ($ocLazyLoadProvider) {
$ocLazyLoadProvider.config({
asyncLoader: function (expr, callback) {
var load = require('bundle?lazy!oclazyDir/out/' + expr + '.js');
load(function (file) {
callback(null, file);
});
}
});
}
]);
How to achieve the same with the latest version of angular oclazyload. Replacing asyncLoader with jsLoader also didn't work out.

This may not answer your question completely, but I discovered that there is a separate flavor of oclazyload that is tailored for RequireJS (https://github.com/ocombe/ocLazyLoad/blob/1.0.9/dist/ocLazyLoad.require.js). This wasn't mentioned in the documentation, so it took a while for me to find it..
There is also this helpful answer from the author of oclazyload outlining why RequireJS is unnecessary if you're using oclazyload: https://stackoverflow.com/a/28961833/2449100
I hope this helps!

Related

Wanting To Optionally Add JavaScript code using Gulp

I've got a gulpfile.js that bundles using browserify and I want to be able to optionally add one line to one of my javascript files based on a variable like useMock. Below is my GulpFile.js build step
function bundle (bundler) {
return bundler
.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('./dist'))
.pipe(browserSync.stream());
}
The last line of the file below is the one I want to optionally include.
module.exports = require('angular')
.module('AngularUApp', [
require('angular-ui-router'),
require('angular-sanitize'),
require('../../base'),
require('./home'),
require('./speaker'),
require('./author')
])
.config(enableHtml5Mode)
.name;
enableHtml5Mode.$inject = ['$locationProvider'];
function enableHtml5Mode($locationProvider) {
console.log('enableHtml5Mode');
$locationProvider.html5Mode(true);
}
// I want to optionally include this from my gulpfile.js
require('../mock');
I want to be able to have a production and dev build where the dev includes the extra line and production does not. If there is a better more recommended way to do this, please suggest.
I found the answer myself. Using the browserify api itself from this link:
https://github.com/substack/node-browserify#usage
var combinedArgs = merge(watchify.args, { debug: true });
var b = browserify(baseDir,combinedArgs);
b.add('angu/mock');
var watcher = watchify(b);
I had a problem earlier because I forgot the relative directory from gulp is different than from inside the JavaScript itself.

Gulp angular templatecache root issue

I'm part of a team developing an AngularJS application and right now I'm working on modifying the Gulp build script. Part of my task is prepopulating the template cache (up till now we have been loading the templates as the routes/directives needed them).
The Gulp task is basically:
var templateCache = require('gulp-angular-templatecache');
gulp.task('cache-templates', function(){
var dest = destinationPath,
src = sourcePath;
return gulp.src(src)
.pipe(plumber())
.pipe(templateCache('templates.js', {root: './templates/'}))
.pipe(gulp.dest(dest));
});
The problem I am getting is that gulp removes the "./" from the root. For instance:
$templateCache.put("templates/foo.html","<div>some html</div>");
in stead of
$templateCache.put("./templates/foo.html","<div>some html</div>");
The module is loaded correctly into app.js and declared as a dependency, and if I do put the "./"'s as a prefix manually, after building, everything works fine. So could you please tell me how to force Gulp to include the "./" prefix in my root?
Note: Every other prefix works fine, it just removes the "./". I would prefer it if I could solve this from within the Gulpfile, without having to modify the templateUrl's in my directives and $routeProvider, because the application is rather large and that would only be asking for trouble. Thanks! :)
What you can do is use gulp-replace and replace 'templates/' with './templates/'.
Old Answer
In the options that you pass to template you can provide a base function
.pipe(templateCache('templates.js', {root: './templates/', base: baseFn}))
you can modify the file-path there
var baseFn = function (file) { return './' + file.relative; }

Loading relative templateUrl

I've been trying to find the best way to create a modular, scalable angular application. I really like the structure of projects like angular-boilerplate, angular-app, where all the related files are grouped together by feature for partials and directives.
project
|-- partial
| |-- partial.js
| |-- partial.html
| |-- partial.css
| |-- partial.spec.js
However, in all these examples, the template URL is loaded relative to the base url, not relative to the current file:
angular.module('account', [])
.config(function($stateProvider) {
$stateProvider.state('account', {
url: '/account',
templateUrl: 'main/account/account.tpl.html', // this is not very modular
controller: 'AccountCtrl',
});
})
This is not very modular, and could become difficult to maintain in large projects. I would need to remember to change the templateUrl path every time I moved any of these modules. It would be nice if there was some way to load the template relative to the current file like:
templateUrl: './account.tpl.html'
Is there any way to do something like this in angular?
The best way to do this now is using a module loader like browserify, webpack, or typescript. There are plenty of others as well. Since requires can be made from the relative location of the file, and the added bonus of being able to import templates via transforms or loaders like partialify, you don't even have to use template urls anymore. Just simply inline the Template via a require.
My old answered is still available below:
I wrote a post on exactly this subject and spoke on it at our local Angular Meetup. Most of us are now using it in production.
It is quite simple as long as your file structure is represented effectively in your modules. Here is a quick preview of the solution. Full article link follows.
var module = angular.module('myApp.things', []);
var all = angular.module('myApp.things.all', [
'myApp.things',
'things.someThing',
'things.someOtherThing',
'things.someOtherOtherThing',
]);
module.paths = {
root: '/path/to/this/thing/',
partials: '/path/to/this/thing/partials/',
sub: '/path/to/this/thing/sub/',
};
module.constant('THINGS_ROOT', module.paths.root);
module.constant('THINGS_PARTIALS', module.paths.partials);
module.constant('THINGS_SUB', module.paths.sub);
module.config(function(stateHelperProvider, THINGS_PARTIALS) {
stateHelperProvider.setNestedState({
name: 'things',
url: '/things',
templateUrl: THINGS_PARTIALS + 'things.html',
});
});
And then any sub modules or "relative" modules look like this:
var module = angular.module('things.someThing', ['myApp.things']);
var parent = angular.module('myApp.things');
module.paths = {
root: parent.paths.sub + '/someThing/',
sub: parent.paths.sub + '/someThing/sub/',
partials: parent.paths.sub + '/someThing/module/partials/',
};
module.constant('SOMETHING_ROOT', module.paths.root);
module.constant('SOMETHING_PARTIALS', module.paths.partials);
module.constant('SOMETHING_SUB', module.paths.sub);
module.config(function(stateHelperProvider, SOMETHING_PARTIALS) {
stateHelperProvider.setNestedState({
name: 'things.someThing',
url: "/someThing",
templateUrl: SOMETHING_PARTIALS + 'someThing.html',
});
});
Hope this helps!
Full Article: Relative AngularJS Modules
Cheers!
I think you'll eventually find that maintaining the paths relative to the js file will be harder, if even possible. When it comes time to ship, you are most likely going to want to concatenate all of your javascript files to one file, in which case you are going to want the templates to be relative to the baseUrl. Also, if you are fetching the templates via ajax, which Angular does by default unless you pre-package them in the $templateCache, you are definitely going to want them relative to the baseUrl, so the server knows where to find them once your js file has already been sent to the browser.
Perhaps the reason that you don't like having them relative to the baseUrl in development is because you aren't running a server locally? If that's the case, I would change that. It will make your life much easier, especially if you are going to work with routes. I would check out Grunt, it has a very simple server that you can run locally to mimic a production setup called Grunt Connect. You could also checkout a project like Yeoman, which provides a pre-packaged front end development environment using Grunt, so you don't have to spend a lot of time getting setup. The Angular Seed project is a good example of a Grunt setup for local development as well.
I've been chewing on this issue for a while now. I use gulp to package up my templates for production, but I was struggling to find a solution that I was happy with for development.
This is where I ended up. The snippet below allows any url to be rewired as you see fit.
angular.module('rm').config(function($httpProvider) {
//this map can be defined however you like
//one option is to loop through script tags and create it automatically
var templateMap = {
"relative.tpl.html":"/full/path/to/relative.tpl.html",
etc...
};
//register an http interceptor to transform your template urls
$httpProvider.interceptors.push(function () {
return {
'request': function (config) {
var url = config.url;
config.url = templateMap[url] || url;
return config;
}
};
});
});
Currenly it is possible to do what you want using systemJs modules loader.
import usersTemplate from './users.tpl';
var directive = {
templateUrl: usersTemplate.name
}
You can check good example here https://github.com/swimlane-contrib/angular1-systemjs-seed
I had been using templateUrl: './templateFile.tpl.html but updated something and it broke. So I threw this in there.
I've been using this in my Gruntfile.js html2js object:
html2js: {
/**
* These are the templates from `src/app`.
*/
app: {
options: {
base: '<%= conf.app %>',
rename: function( templateName ) {
return templateName.substr( templateName.lastIndexOf('/') );
}
},
src: [ '<%= conf.app %>/**/{,*/}<%= conf.templatePattern %>' ],
dest: '.tmp/templates/templates-app.js'
}
}
I know this can lead to conflicts, but that is a smaller problem to me than having to edit /path/to/modules/widgets/wigdetName/widgetTemplate.tpl.html in every file, every time, I include it in another project.

Load JavaScript and CSS files in folders in AngularJS

I have an AngularJS application and in the future, some developers in other teams will develop modules that will be installed as parts of it. So I defined the folder structure as below.
www/
index.html
app.js
modules/
modulesA/ -- will be copied when module A was installed
moduleA.js
moduleA.css
moduleA.partial.html
modulesB/ -- will be copied when module B was installed
moduleB.js
moduleB.css
moduleB.partial.html
Now I have a problem. When user installed module A, how to let AngularJS (and the application) load JS and CSS under its folder? Is there any library can load JS and CSS by folder so that I can put the code in index.html likes
<script src="/modules/**/*.js"></script>
<link src="/modules/**/*.css"/>
Otherwise, I have to add some placesholders in index.html and change the content when user installed a module, something like
<script src="/app.js"></script>
<!-- $$_JS_$$ -->
<link src="/app.css"/>
<!-- $$_CSS_$$ -->
AngularJS doesn't support what you want, but you could take a look at build tools such as Grunt or Gulp that let you "build" your application for you. In your case, these tools can look for CSS files and concatenate them into one single file. This way your index.html does not have to change if you ever add new modules.
GruntJS: http://gruntjs.com/
GulpJS: http://gulpjs.com/
Personally I use GulpJS, since it seems to be much faster & I found it easier to configure:
Included my configuration file below.
For example, the task "styles" will compile every css file it finds in the folders I specified, concatenate them, and drop them in the distribution folder.
Since there is an initial learning curve on how to use these tools, you can always integrate gulp or grunt at your own pace. For now you could let it build your css files & later expand it by concatenating JS as well and do various other tasks. In my opinion, its worth learning as it saves you so much time & effort.
var gulp = require("gulp");
var concat = require("gulp-concat");
var html2js = require("gulp-ng-html2js");
var sass = require("gulp-sass");
var clean = require("gulp-clean");
var streamqueue = require("streamqueue");
var ngDepOrder = require("gulp-ng-deporder");
var paths = {
"dist": "../server/staffing/static/",
"vendor": ['vendor/underscore/underscore.js',
'vendor/angular/angular.min.js',
'vendor/angular-route/angular-route.min.js',
'vendor/restangular/dist/restangular.min.js',
'vendor/angular-animate/angular-animate.min.js',
'vendor/angular-bootstrap/ui-bootstrap-0.7.0.min.js',
'vendor/angular-bootstrap/ui-bootstrap-tpls-0.7.0.min.js',
'vendor/angular-ui-router/release/angular-ui-router.min.js',
'vendor/angular-bootstrap-colorpicker/js/bootstrap-colorpicker-module.js',
'vendor/momentjs/min/moment.min.js'],
"scripts": ['app/**/*.js'],
"fonts": ['app-data/fonts/*.*'],
"templates": ['app/**/*.html'],
"styles": ['app/**/*.scss','vendor/angular-bootstrap-colorpicker/css/*.css']
}
gulp.task("watch", function () {
gulp.watch('app/**/*.js', ['scripts']);
gulp.watch('app/**/*.html', ['scripts'])
gulp.watch('app/**/*.scss', ['styles']);
})
gulp.task("default", ["clean"], function () {
gulp.start("scripts", "vendor", "styles", "fonts");
})
gulp.task("clean", function () {
return gulp.src(paths.dist, {read: false})
.pipe(clean({force: true}));
})
gulp.task("vendor", function () {
gulp.src(paths.vendor)
.pipe(concat("vendor.js"))
.pipe(gulp.dest(paths.dist + "js/"));
});
gulp.task("scripts", function () {
var stream = streamqueue({objectMode: true});
stream.queue(gulp.src(paths.scripts)
.pipe(ngDepOrder()));
stream.queue(gulp.src(paths.templates)
.pipe(html2js({moduleName: "templates"})));
return stream.done()
.pipe(concat("app.js"))
.pipe(gulp.dest(paths.dist + "js/"))
});
gulp.task("styles", function () {
gulp.src(paths.styles)
.pipe(sass())
.pipe(concat("staffing.css"))
.pipe(gulp.dest(paths.dist + "css/"))
})
gulp.task("fonts", function () {
gulp.src(paths.fonts).
pipe(gulp.dest(paths.dist + "fonts/"))
})
Check out the angular generator for Slush, it does what I think you want using gulp-bower-files and gulp-inject. You specify your app dependencies using bower, and these are collected and injected by gulp using gulp-inject, which then injects in your index.html the proper link/src/style tags that look very much like your own examples above. Modules' JS and CSS is also collected, minimized, concatenated and injected as well. It also compiles partials and injects those into $templateCache.
I have used it to automatically include dependencies from sub-folder modules/views using a project layout similar to yours.
Note that all your vendor dependencies will need to be bower packages that specify their dist files using the 'main' attribute in bower.json. Some packages do not do this properly, but it's easy to fork the package and add them yourself then point bower at your updated repo.

Handle resource versioning with require.js

We are planning on versioning our key resources at build time by appending a version to the filename (e.g. main-v1_1.js)
We are learning how to use require.js to manage our resource loading. I would like to be able to specify a postfix in the require.js configuration that will be appended to the resources being loaded.
var version = "1_1"; //inserted at build time
requirejs.config(
{
postfix: "_" + version //is there something like this?
}
);
require([main]...); //would load main_1_1.js
Suggestions? Thoughts? Better ways to handle this situation?
Thank you.
Sounds like this would be suited to the map configuration option.
requirejs.config({
map: {
'some/newmodule': {
'foo': 'foo1.2'
},
'some/oldmodule': {
'foo': 'foo1.0'
}
}
});
When 'some/newmodule' does require('foo') it will get the foo1.2.js
file, and when 'some/oldmodule' does require('foo') it will get the
foo1.0.js file. This feature only works well for scripts that are real
AMD modules that call define() and register as anonymous modules.
We ended up using the urlArgs parameter to append a version querystring.
http://requirejs.org/docs/api.html#config-urlArgs

Resources