I got a "framework" created by us using AngularJS. It allows to build questionnaire system and it has many different parameters that control the behavior of framework.
Using this framework we've created 2 projects: projectA and projectB. The difference between these projects are the settings and assets (css, img, ...)
Both projects are stored on the same branch in git and only config file defines the project customization.
I can't think of the best way how these 2 projects can be easily deployed separately from the same code source using Gulp or something other.
Here are some ideas I got for the moment:
1. Have both settings files and images (e.g. logo_A.png and logo_B.png) in the code and choose appropriate during build using Gulp
2. Create folder customizations that will have 2 subfolders A and B with corresponding settings and assets
3. Create separate repository for each project installation scripts (not the code) and these scripts will do all the work
What is the best way in this case?
Finally, the easieast and most understandible solution was to create additional custom folder.
Assets
In addition to normal application files I got now custom folder with 2 subfolders: A and B each of them containing assets (css, img) that correspond only to concrete project.
In gulp I've used yargs module which allows to pass parameters. After reading project name from input I can looks inside custom folder to see if there are resources interesting for me (I've just added custom folder into the resources paths).
var customPath = './custom/' + app.name;
exports.paths = {
web: {
//Resources
styles: ['./app/**/*.css', './app/**/*.scss', customPath + '/**/*.css', customPath + '/**/*.scss'],
...
And the call to build task now looks like this: gulp build --name A.
Configuration
One more thing was done for configuration file of AngularJS that contains constants. I've used gulp-ng-config plugin which allows to build AngularJS configuration (constants) file on fly. In my flow, first I check if custom configuration file exists inside custom folder I use it, if no I'm using default one from application.
var getAppScripts = function() {
return $.eventStream.merge(
gulp.src(config.paths.web.scripts)
.pipe($.jshint())
.pipe($.jshint.reporter('jshint-stylish'))
//.pipe($.eslint())
.pipe($.eslint.format()),
getAppConfig())
.pipe($.angularFilesort());
};
var getAppConfig = function() {
var configFile = config.paths.web.custom + "/app.config.yaml";
if (fs.existsSync(configFile)) {
return gulp.src(configFile)
.pipe($.ngConfig(config.app.name, {
parser: 'yml',
createModule: false
}));
}
else {
return gulp.src(config.paths.web.config);
}
}
Related
I'm putting together a AngularJS+Typescript+VisualStudio project. I want to have a configuration file with constants in it that control different settings (e.g., REST API URLs and environment names). How is this typically done in this kind of project?
I might have a dev config file called app.dev.config.ts like this:
module app.config {
export class ConfigSettings {
static environment(): string { return "dev"; }
static dataApiBaseUrl(): string { return "DevDataService"; }
}
}
and an app.prod.config.ts like this:
module app.config {
export class ConfigSettings {
static environment(): string { return "prd"; }
static dataApiBaseUrl(): string { return "PrdDataService"; }
}
}
Of course this doesn't actually work because these two classes have the same name.
I need to set this up in a way so that I build this only once in my build server, and then can deploy this to a fixed (3) number of environments. Maybe this means that when I go to deploy this to some environment, I have an additional step where I rename a config file. This is what I do for C# projects and their config files.
I've searched around online for this, but all I can find is references to tsconfig.json files.
I found a solution for this.
1) I put together separate config files like env.dev.ts and env.prd.ts in my project. Their contents look like this:
angular.module('compdb') //module name matches my main module
.constant('env', 'prd')
.constant('key1', 'prd value 1')
.constant('key2', 'prd value 2');
2) Visual Studio transpiles these to env.dev.js, etc.
3) In my gulp file, I copy the env.*.js files to my output directory.
4) In my Index.cshtml file, I include env.js. I include this after my scripts that create the compdb angular module
5) When I deploy my code to any environment, I rename the appropriate config file (e.g., env.prd.js) to env.js
In Fusion's Javascript Indexing Stage, we can import Java classes and run them in the javascript such as this :
var imports = new JavaImporter(java.lang.String);
with (imports) {
var name = new String("foo"); ...
}
If we have customized complex Java classes, how to include the compile jar with Fusion so that the class can be imported in Javascript Indexing Stages for use?
And where can we store configuration values for the Javascript Indexing Stage to look up and how to retrieve them?
I'm thinking of something like this:
var imports = new JavaImporter(mycompany.com.custompkg.SomeParser);
with (imports) {
var some_config = ResourceManager.GetString("key");
var sp = new SomeParser(some_config); ...
}
Regards,
Kelvin
Starting in Fusion 4.x The API and Connectors started using a common location for jars i.e. apps/libs . This is a reasonable place to put custom jars but the services must be told about the new jars as well. That's done in two places
/jetty/connectors-classic/webapps/connectors-extra-classpath.txt
./jetty/api/webapps/api-extra-classpath.txt
Also, index documents can get processed by the api service so even if the jar is only used for indexing, register with both classpaths. Finally, bounce the services.
Put the Java class file, as a jar file, in $FUSION_HOME/apps/jetty/api/webapps/api/WEB-INF/lib/.
I used this to access my custom class.
var SomeParser = Java.type('mycompany.com.custompkg.SomeParser');
I'm using VS 2015, ASP.NET 5 (MVC 6) and Gulp to write a SPA with angularjs and supplementary modules. My target framework is dnx451. I've read several best practices which state that the response from Index should have a strict no cache policy set, and all other resources (e.g. js, css, img) should all be heavily cached. In doing so, the browser always downloads the lightweight page and caches the scripts. When publishing, I am trying to have a gulp task which concats/uglifys all my JS files and outputs a single app.min.{version}.js (also for the less -> css file). This gives the benefit of always downloading the latest file version, but keeping them in cache while it is the latest and greatest.
Is there a way to get the Version (from project.json) and the build (from the * portion of project.json) from my gulp task? I am looking for a way to have the file {version} portion of the name match the version/build of the website.
I have seen examples of using process.env in gulp for VS environment variables, but am having trouble putting the pieces together to achieve the desired Version.Build format.
I have tried:
var project = require('./project.json');
gulp.task('js-publish', function(){
project.version; //this give 1.0.0-* (makes sense since its a string)
});
and
gulp.task('js-publish', function(){
process.env.BUILD_VERSION; //which is undefined
});
You want to use the gulp-rename NPM package to rename the file. Add gulp-rename to your package.json file. Here is an example of how it can then be used in your gulpfile.js:
var rename = require("gulp-rename");
// rename via string
gulp.src("./src/main/text/hello.txt")
.pipe(rename("main/text/ciao/goodbye.md"))
.pipe(gulp.dest("./dist")); // ./dist/main/text/ciao/goodbye.md
// rename via function
gulp.src("./src/**/hello.txt")
.pipe(rename(function (path) {
path.dirname += "/ciao";
path.basename += "-goodbye";
path.extname = ".md"
}))
.pipe(gulp.dest("./dist")); // ./dist/main/text/ciao/hello-goodbye.md
// rename via hash
gulp.src("./src/main/text/hello.txt", { base: process.cwd() })
.pipe(rename({
dirname: "main/text/ciao",
basename: "aloha",
prefix: "bonjour-",
suffix: "-hola",
extname: ".md"
}))
.pipe(gulp.dest("./dist")); // ./dist/main/text/ciao/bonjour-aloha-hola.md
I am in to developing a large client side app with very complex views on each modules using Extjs5. I have developed apps in Extjs but they all compile to a single app.js file. So based on the complexity of the views in all the app mockups I am estimating the size of the app will be around 20MB to 25MB even after compiled.
I was thinking to split the modules as separate applications and create a master app with tabs or something, which triggered will be loading individual apps in a iFrame within the master app. But I doubt if the iframe behaviors are altered in different browsers or deprecated in any future browser releases, that will be another big problem.
So is there any way in sencha cmd, which compiles app in separate files based on modules and load them on demand out of the box ?
If not what is the advisable solution I should be going ahead with.
Starting with Sencha Cmd 6.5 you can split your code into multiple files. To achieve this, you have to split your code into exjts packages if it’s not already done:
In the end, you should have a similar folder structure to this:
workspaceDir
|
+->appA
+->appB
+->packages
|
+-> local
|
+->CoreComponents
+->ProcurementModule
+->ForumModule
+->BOMModule
+->ReportModule
In your app.json file you could add/move your packages from requires to uses. As a last step you have to add the new package-loader to the requires array in app.json.
You end up with something like that:
{
// [...]
"uses": [
"ProcurementModule",
"ForumModule",
"BOMModule",
"ReportModule"
],
"requires": [
"CoreComponents",
"package-loader"
]
// [...]
}
Next you need to start your Sencha Cmd build with the additional flag -uses.
If you do this, Sencha Cmd will build your optional packages first and add them to the resource folder in your build output directory.
sencha app build -uses production
It is important, that you don't have any references to classes in optional packages from your main application. Otherwise your build will fail.
Since your optional packages are not loaded automatically on page startup you need to trigger the loading process manually. I do it usually within the routing process of my AppControllers.
Here an example:
Ext.define('MyApp.view.main.MainController', {
extend: 'Ext.app.ViewController',
requires: [
'Ext.Package'
],
routes: {
'forum': {
before: 'loadForum',
action: 'showView'
}
},
loadForum(action) {
if (Ext.Package.isLoaded('ForumModule')) {
action.resume();
} else {
//Loading mask code here [...]
Ext.defer(() => { // it needs some time to show up the loading mask
Ext.Package.load('ForumModule').then(() => {
//Remove loading mask code here [...]
action.resume(); //proceed router process; all package files loaded
});
}, 500);
}
},
showView() {
this.getView().add({xclass: 'ForumModule.view.MainView'});
}
});
More information on this topic:
http://docs.sencha.com/cmd/guides/whats_new_cmd65.html#whats_new_cmd65_-_dynamic_package_loading
I'm trying to generate combined JavaScript and CSS resources into a single file using gulp-concat using something like this:
var concatjs = gulp
.src(['app/js/app.js','app/js/*Controller.js', 'app/js/*Service.js'])
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
I get a concatted file with this, but the order of the javascript files embedded in the combined output file is random - in this case the controllers are showing up before the initial app.js file, which causes problems when trying to load the Angular app that expects app.js before any of the related resources are loaded. Likewise for CSS resources that get combined end up in random order, and again the order is somewhat important - ie. bootstrap needs to load before the theme and any custom style sheets.
How can I set up the concatenation process so that the order remains intact?
Update
So it turns out the ordering above DOES actually work by explicitly specifying the file order in the array of file specs. So in this case the crucial thing is to list app/js/app.js first, then let the rest of the scripts where order doesn't matter in in any order.
The reason I failed to see this behavior (Duh!) is that Gulp Watch was running and the gulpfile.js update wasn't actually reflected in the output. Restarting gulp did update the script. Neophyte error...
Other Thoughts:
Still wondering though - is this the right place to specify build order? It seems you're now stuffing application logic (load order) into the build script, which doesn't feel right. Are there other approaches to address this?
For an angular application like the one in your example (and it's dependency management), I normally use this kind of syntax: gulp.src(['app\js\app.js', 'app\js\**\*.js']).
You can also use just gulp.src('app\js\**\*.js') if your app.js file is the first one in alphabetic order.
I see your point about moving the load file order into the build script: I had the same feeling till I started using gulp-inject for injecting the unminified files references in my index.html at development time and injecting the bundled, minified and versioned ones in the production index file. Using that glob ordering solution across all my development cycle made so sense to me that i don't think to it anymore.
Finally, a possible solution for this 'ordering smell' can be using browserify but to me it is just complicating the architecture for an angular application: in the end, as you said, you just need that one specific file is called before all the other ones.
For my js i use a particular structure/naming convention which helps. I split it up into directories by feature, where each 'feature' is then treated as a separate encapsulated module.
So for my projects i have,
app/js/
- app.js
- app.routes.js
- app.config.js
/core/
- core.js
- core.controllers.js
- core.services.js
/test/
- .spec.js test files for module here
/feature1/
- feature1.js
- feature1.controllers.js
/feature2/
- feature2.js
- feature2.controllers.js
...
So each directory has a file of the same name that simply has the initial module definition in it, which is all that app.js has in it for the whole app. So for feature1.js
angular.module('feature1', [])
and then subsequent files in the module retrieve the module and add things (controllers/services/factories etc) to it.
angular.module('feature1')
.controller(....)
Anyway, i'll get to the point...
As i have a predefined structure and know that a specific file has to go first for each module, i'm able to use the function below to sort everything into order before it gets processed by gulp.
This function depends on npm install file and npm install path
function getModules(src, app, ignore) {
var modules = [];
file.walkSync(src, function(dirPath, dirs, files) {
if(files.length < 1)
return;
var dir = path.basename(dirPath)
module;
if(ignore.indexOf(dir) === -1) {
module = dirPath === src ? app : dir;
files = files.sort(function(a, b) {
return path.basename(a, '.js') === module ? -1 : 1;
})
.filter(function(value) {
return value.indexOf('.') !== 0;
})
.map(function(value) {
return path.join(dirPath, value);
})
modules = modules.concat(files);
}
})
return modules;
}
It walks the directory structure passed to it, takes the files from each directory (or module) and sorts them into the correct order, ensuring that the module definition file is always first. It also ignores any directories that appear in the 'ignore' array and removes any hidden files that begin with '.'
Usage would be,
getModules(src, appName, ignoreDirs);
src is the dir you want to recurse from
appName is the name of your app.js file - so 'app'
ignoreDirs is an array of directory names you'd like to ignore
so
getModules('app/js', 'app', ['test']);
And it returns an array of all the files in your app in the correct order, which you could then use like:
gulp.task('scripts', function() {
var modules = getModules('app/js', 'app', ['test']);
return gulp.src(modules)
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
});