How do I use the "version" property in package.json as the app's directory in grunt? - node.js

I'm managing a project written in angularjs, with the default directory structure, excluding the app directory which uses versioning (ie. "app/0.0.0/", "app/0.1.0/" etc..).
I'm trying to use grunt's package.json file's "version" property to load the correct
directory so I won't have to manually change the app path in gruntfile.js
but for some reason I keep getting "Cannot GET /" when I run "grunt server".
To better explain this, here's a sample of my gruntfile.js:
var yeomanConfig = {
app: 'app/<% pkg.version %>/',
dist: 'dist'
...
grunt.initConfig({
yeoman: yeomanConfig,
pkg: grunt.file.readJSON('package.json'),
...
If I manually change the app property to "app/0.0.0" it works like a charm
so I'm guessing this has something to do with the templating.
Any ideas?
Thank you very much for the help.
Edit: Thank you for the correction Andreas and Matjaz, but this doesn't solve the problem and gives the same error...
This solves the problem for me but without the templating system:
var pkgVersion = grunt.file.readJSON('package.json').version;
// configurable paths
var yeomanConfig = {
app: 'app/'+pkgVersion,
dist: 'dist'
};
It's pretty ugly but it works. Hoping for a proper solution.

The best way to handle above scenario is that, In the grunt.initConfig define the package.json
grunt.initConfig({
pkg: grunt.file.readJSON("package.json")
})
Once above initialized you can use the properties of the package.json throughout the grunt.js file.
<%= pkg.version %>
<%= pkg.homepage %>

To echo data use <%=:
<%= pkg.version %>

I extend the appConfig with the name and version:
var appConfig = {
app: require('./bower.json').appPath || 'app',
name: require('./package.json').name || 'angularapp',
version: require('./package.json').version || '1.0.0',
dist: 'dist'
};
Then you can access the variables like this:
<%= yeoman.name %>
<%= yeoman.version %>
For me a clean solution with an optional fallback.

Related

Can't find node_modules after deployment

This title might be a bit misleading but please bear with me for a while.
I have made a simple Angular2 app on visual studio 2015 and now I have published it on Azure.
Having node_modules in the development environment was perfect but after deploying it shows error saying can't find node_modules.
Here is how I am referring in my development env in index.html-
<!-- Polyfill(s) for older browsers -->
<script src="/node_modules/core-js/client/shim.min.js"></script>
<script src="/node_modules/zone.js/dist/zone.js"></script>
<script src="/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/node_modules/systemjs/dist/system.src.js"></script>
<script src="/systemjs.config.js"></script>
Its also referred in system.config.js-
/**
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
(function(global) {
// map tells the System loader where to look for things
var map = {
'app': '/app', // 'dist',
'#angular': '/node_modules/#angular',
'angular2-in-memory-web-api': '/node_modules/angular2-in-memory-web-api',
'rxjs': '/node_modules/rxjs'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
};
var ngPackageNames = [
'common',
'compiler',
'core',
'forms',
'http',
'platform-browser',
'platform-browser-dynamic',
'router',
'router-deprecated',
'upgrade',
];
// Individual files (~300 requests):
function packIndex(pkgName) {
packages['#angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Bundled (~40 requests):
function packUmd(pkgName) {
packages['#angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
}
// Most environments should use UMD; some (Karma) need the individual index files
var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
// Add package entries for angular packages
ngPackageNames.forEach(setPackageConfig);
// No umd for router yet
packages['#angular/router'] = { main: 'index.js', defaultExtension: 'js' };
var config = {
map: map,
packages: packages
};
System.config(config);
})(this);
The error makes sense as I have a .gitignore file which doesn't let the node_modules to deploy to server.
Can someone please assist as to how I can run it after deploying and what change could be done with the above references in order to make it work.
I have not used SystemJS, but your bounty has enticed me to try answering anyway, since it looks like you still need an answer. :)
After glancing through some SystemJS docs, it looks like your index.html needs to be different for development vs production use. This is what the docs show for development:
<script src="systemjs/dist/system.js"></script>
<script>
SystemJS.import('/js/main.js');
</script>
And this is what they show for production (notice the first line has a different src path):
<script src="systemjs/dist/system-production.js"></script>
<script>
SystemJS.import('/js/main.js');
</script>
More importantly, take note that node_modules is not referenced in either case, nor should it be. If you have your code and configuration set up correctly, SystemJS (like other build tools) will package everything you need without any additional <script> tags. Instead, you should import your shims (and similar) from within your code somewhere. For example, in their Webpack guide (Webpack is a another build tool filling a similar role to SystemJS) the Angular team shows a polyfills.ts file that imports their shims, then they include the polyfills file into the build within their webpack configuration.
I'm sorry I can't offer more specific advice about SystemJS in particular, but hopefully this answer is enough to point you in the right direction.
You either have to deploy node_modules as a part of your package or have a script run npm install for you to get the packages from your package.json
To get the packages in your package.json file do npm install --save package-you-want-to-install
Then you can have your startup script install from the package json by trying the script on this link https://github.com/woloski/nodeonazure-blog/blob/master/articles/startup-task-to-run-npm-in-azure.markdown
One thing you could do is install the packages needed on Azure server via Kudu dashboard.
Go to https://yoursitename.scm.azurewebsites.net
Then Debug console -> CMD
Go to home\site\wwwroot directory
Type npm install
This will install the needed packages for the Angular 2 app to run on Azure server.
Don't use system.config.js
You need to bundle it first. Don't upload node_modules in Azure. To bundle refer below link.
How to bundle an Angular app for production
Once you bundle dist folder will create. You can upload the dist folder in Azure.
npm install your deps on prod env ..
npm i --production

Run a shell command that is inside a project folder from Grunt task

I have a shell command ./node_modules/cordova/bin/cordova which is accessible from the project root.
I also have a set of config files for Grunt which are located in ./config folder.
Now I am trying to run cordova from tasks and want to use it as an alias, so in Gruntfile.js I have it like this:
grunt.initConfig({
buildDir: 'build/interim_builds',
publishDir: 'build/publish',
cordovaCommand: './node_modules/cordova/bin/cordova',
...
})
Then, from a task I run it like this:
mobileApp_create: {
cmd: '<%= cordovaCommand %> create <%= mobileAppProjectDir %>'
}
As a result I get this error:
'.' is not recognized as an internal or external command,
If I replace
cordovaCommand: './node_modules/cordova/bin/cordova'
with
cordovaCommand: 'node_modules/cordova/bin/cordova'
Then I see this error:
'node_modules' is not recognized as an internal or external command,
So, I suppose it can be something with relative paths and how Grunt works with them? Where do I dig to fix this issue as I need to use local installation of cordova, not global.
You could try fully resolving the path at runtime, that way there are no relative paths:
var path = require('path');
module.exports = function(grunt) {
grunt.initConfig({
buildDir: 'build/interim_builds',
publishDir: 'build/publish',
cordovaCommand: path.resolve('./node_modules/cordova/bin/cordova'),
// ...
});
// ...
};

How to replace requireJS config in webpack es6 project

I want to refactor a large requireJS project to use es6 import/export and webpack. In the requireJS requirejs.config call, I use the config section to pass some project specific settings to some views:
requirejs.config({
baseUrl: 'js/cfe/app',
paths: { },
config: {
'views/test/TestView': {
isTest: true
}
})
and in the view:
define(['module'], function(module) {
var t = module.config().isTest
})
How can I accomplish the same behaviour in my webpack setup?
I'm not quite sure if I understand your question correctly, but maybe you can use my answer anyways.
I think you could extract your configuration object to JSON file, use a loader (RAW loader works fine) to include it in your bundle, and then when you need it simply use ES6 import:
import config from 'myconfig.json';

Building Durandal with Grunt (R.js + Text)

I would like to use Grunt to build a Durandal project, because Weyland remains completely undocumented and isn't as standard as Grunt.
To do this, the grunt task needs to pull in all the js and html files during optimization, but I am unable to get RequireJS to inline the html files via the text module.
It looks like weyland copies the text files manually, but I can't figure out what it's doing to get requirejs (or almond, in this case), to actually use them. I have seeen this question, but it requires the text modules to be referenced in the define call, which isn't done in Durandal.
My gruntfile for require uses this config
requirejs: {
build: {
options: {
name: '../lib/require/almond-custom', //to deploy with require.js, use the build's name here instead
insertRequire: ['main'], //needed for almond, not require
baseUrl: 'src/client/app',
out: 'build/main-built.js',
mainConfigFile: 'src/client/app/main.js', //needed for almond, not require
wrap: true, //needed for almond, not require
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout-2.3.0',
'bootstrap': '../lib/bootstrap.min',
'jquery': '../lib/jquery-1.9.1',
'Q' : '../lib/q.min'
},
inlineText: true,
optimize: 'none',
stubModules: ['text']
}
}
}
You might want to give https://npmjs.org/package/grunt-durandal a try. I'm using this as part of a grunt based build process. See https://github.com/RainerAtSpirit/HTMLStarterKitPro for an example.
durandal: {
main: {
src: ['app/**/*.*', 'lib/durandal/**/*.js'],
options: {
name: '../lib/require/almond-custom',
baseUrl: requireConfig.baseUrl,
mainPath: 'app/main',
paths: mixIn({}, requireConfig.paths, { 'almond': '../lib/require/almond-custom.js' }),
exclude: [],
optimize: 'none',
out: 'build/app/main.js'
}
}
},
As a possible alternative to Grunt I would suggest looking at Mimosa. It's not as widely used as Grunt but is well documented and requires a good deal less configuration and if you start with the durandal skeleton everything is configured for you including inlining html.
Durandal also recommends it and tells you how to get started with it: http://durandaljs.com/pages/get-started/
You can run make start to start developing and make dist to have it package everything up for release.

Understanding the mean stack and integrating uglify.js and stylus

I'm just getting started with the MEAN stack (https://github.com/linnovate/mean), so I'm pretty sure my question is going to look very basic to an expert, so my apologies in advance!
While I think it would be a gread addition to what this stack already has to offer, I cannot manage to integrate Uglify.js and stylus
Also someone already asked this, but it would make sense to me to use Jade template for both server and public views, at least for a matter of standardization.
I have tried playing with the grunt file and server.js, renaming some files, but all I managed to achieve so far, is break the original project...
Thanks in advance!
EDIT: Just found a fork of this project which has just added support for jade templates for public views: https://github.com/tutley/mean
This post explains how to integrate Stylus pre-processing to the MEAN stack: http://to-s.tk/integrate-stylus-to-the-mean-stack/
Short version:
Move public/css to a new assets/stylesheets and rename all the .css files to .styl
Install grunt-contrib-stylus through npm's package.json, as both a dev and runtime dependency.
-Configure stylus compilation in your Gruntfile
// ...
grunt.initConfig({
// ...
watch: {
// ...
stylus: {
files: ['assets/stylesheets/**/*.styl'],
tasks: ['stylus']
},
// ...
},
// ...
stylus: {
compile: {
options: {
paths: ['assets/stylesheets/**']
},
files: [{
dest: 'public/css/',
cwd: 'assets/stylesheets/',
src: '*.styl',
ext: '.css',
expand: true
}]
}
},
// ...
});
//...
//Load NPM tasks
// ...
grunt.loadNpmTasks('grunt-contrib-stylus');
// ...
Import views stylus files (or any substylus) in common.styl using #require statements
Remove references to views or other substylesheets in head.jade.
Then all assets/stylesheets/*.styl files should be automatically compiled into public/css/*.css, as long as grunt is running. To trigger a compile without relying on watch, you can run grunt stylus.

Resources