I have a legacy asp.net + durandal.js app that is using weyland as a build optimizer. We are trying to upgrade to grunt to use something newer, but I can't get it to generate minified js build file correctly. I have the following weyland-config file:
exports.config = function(weyland) {
weyland.build('main')
.task.jshint({
include:'App/**/*.js'
})
.task.uglifyjs({
include: ['App/**/*.js', 'Scripts/durandal/**/*.js'],
exclude: ['App/main-built.js']
})
.task.rjs({
include:['App/**/*.{js,html}', 'Scripts/durandal/**/*.js'],
loaderPluginExtensionMaps:{
'.html':'text'
},
rjs:{
name:'../Scripts/almond-custom',
insertRequire:['main'],
baseUrl : 'App',
wrap:true,
paths : {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
'knockout': 'empty:',
'bootstrap': 'empty:',
'jquery': 'empty:'
},
inlineText: true,
optimize : 'none',
pragmas: {
build: true
},
stubModules : ['text'],
keepBuildDir: true,
out:'App/main-built.js'
}
});
}
I've been trying to create gruntfile according to this and this and this is what I have:
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
jshint: {
include: 'App/**/*.js'
},
durandal: {
main: {
src: [
"App/**/*.*",
"Scripts/durandal/**/*.js"
],
options: {
name: '../Scripts/almond-custom',
baseUrl: './App/',
mainPath: "App/main",
paths: {
'jquery': '../Scripts/jquery-3.6.0',
'text': '../Scripts/text',
'knockout': '../Scripts/knockout-3.4.1',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions',
},
exclude: [],
optimize: 'none',
out: "App/main.js"
}
}
},
uglify: {
build: {
src: 'App/main.js',
dest: 'App/main-built.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks("grunt-durandal");
// Default task(s).
grunt.registerTask('default', ['durandal', 'uglify']);
};
But when I try to run grunt I get the following error:
Error: TypeError: Cannot read property 'normalize' of undefined
>> at Module.<anonymous> (APP_PATH\node_modules\requirejs\bin\r.js:1218:36)
If I try to only run uglify I get incorrectly minified file (by incorrectly I mean that the application throws errors when trying to use it). Does anybody know how to correctly port it over from weyland to grunt?
Related
I receive this errors via grunt-sftp-deploy --verbose
I'm just started with grunt, just need to upload the watch css generated via sass to a certain point on a server.
Registering "grunt-sftp-deploy" local Npm module tasks.
Reading
***************\public\grunt\node_modules\grunt-sftp-deploy\package.json...OK
Parsing
***************\grunt\node_modules\grunt-sftp-deploy\package.json...OK
Loading "sftp-deploy.js" tasks...OK
+ sftp-deploy
Loading "Gruntfile.js" tasks...OK
+ default
Running tasks: sftp-deploy
Running "sftp-deploy" task
Running "sftp-deploy:build" (sftp-deploy) task
Verifying property sftp-deploy.build exists in config...OK
Files: ../css -> /server/path
**Warning: .ftppass seems to be missing or incomplete Used --force, continuing.**
>> Concurrency : 4
Connection :: connect
**>> Error: Timed out while waiting for handshake
Fatal error: Connection :: error**
So then the gruntfile.js looks like that
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
'sftp-deploy': {
build: {
auth: {
host: 'XXX.XXX.XXX.XXX',
port: 22,
authKey: 'key1'
},
cache: 'sftpCache.json',
src: '../css',
dest: '/server/path',
exclusions: [
],
serverSep: '/',
concurrency: 4,
progress: true
}
},
sass: {
dist: {
options: {
style: 'expanded',
noCache: true
},
files: [{
expand: true,
cwd: '../sass/pages',
src: ["**/*.scss"],
dest: '../css',
ext: ".css"
}]
}
},
watch: {
options: {
nospawn: true,
nocache: true,
livereload: true
},
sass: {
files: ['../sass/**/*.scss'],
tasks: ['sass']
},
sftp: {
files: ['../css/**/*.css'],
tasks: ['sftp-deploy']
}
}
});
grunt.loadNpmTasks('grunt-sftp-deploy');
grunt.registerTask('default', ['watch']);
};
Sass is right but i can't find why is not uploading the file to the server.
Then my question is:
What i'm missing?
Which is the path in where is supposed to be the .ftppass.json?
Right now is the same place as the gruntfile.js but i'm having problems with it as well and i'm suspecting that is not right. but there is no room to set up the .ftppass.json in the sftp-deploy gruntfile.js settings.
How do i set up the path correctly?
.ftppass.json
{
"key1": {
"username": "username",
"password": "pass"
}
}
It is just .ftppass WITHOUT the .json in the end. Placing it in the same directory as your Gruntfile.js will do it
I have a React app that I am transforming, uglifying and browserfying via Grunt. My grunt file looks like this...
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
dist: {
files: {
'./Scripts/build/App.js': ['./Scripts/src/**/*.js']
},
options: {
browserifyOptions: {
debug: true
},
transform: [ require('grunt-react').browserify ],
ignore: './Scripts/src/**/*-test.js'
}
}
},
uglify: {
my_target: {
files: {
'./Scripts/build/App-min.js': ['./Scripts/build/App.js']
}
}
},
watch: {
scripts: {
files: ['./Scripts/src/**/*.js'],
tasks: ['browserify', 'uglify'],
options: {
spawn: false
},
},
},
})
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
}
You will notice the ignore property of the browserify task is telling it to ignore any file with -test.js in the filename, the reason being that my tests are stored in folders directly next to the file I am testing (as seems to be the convention when looking at the React Flux examples) and I don't want the test files being bundled in to my app.js file. Can anyone tell me if I am doing this wrong because so far it doesnt seem to be working at all? The test files get bundled into app.js and then I get console errors about jest not being defined.
Did a bit of lateral Googling and found a post on stack Here
It seems that you can add files to the src array and if you prefix them with a '!' it marks them as ignored files.
My now working grunt file....
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
dist: {
files: {
'./Scripts/build/App.js': ['./Scripts/src/**/*.js', '!./Scripts/src/**/*-test.js']
},
options: {
browserifyOptions: {
debug: true
},
transform: [ require('grunt-react').browserify ]
}
}
},
uglify: {
my_target: {
files: {
'./Scripts/build/App-min.js': ['./Scripts/build/App.js']
}
}
},
jest: {
options: {
coverage: true,
testPathPattern: /.*-test.js/
}
},
watch: {
scripts: {
files: ['./Scripts/src/**/*.js'],
tasks: ['browserify', 'uglify'],
options: {
spawn: false
},
},
},
})
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-jest');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
}
I am trying to get grunt to reload the browser when it compiles the typescript. It is correctly watching the files and compiling them but I can not figure out how to reload the browser. I tried setting livereload: true in various places with no luck. I left the various livereload sections I tried below. i tried them one at a time and all together.
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-typescript');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-livereload');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-open');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
server: {
options: {
port: 8181,
livereload: true,
}
}
},
typescript: {
base: {
src: ['js/src/**/*.ts'],
dest: 'js/main.js',
options: {
module: 'amd',
target: 'es5',
livereload: true
}
}
},
watch: {
files: 'js/src/**/*.ts',
tasks: ['typescript'],
options: {
livereload: true,
}
},
open: {
dev: {
path: 'http://localhost:8181/index.html',
app: 'chrome'
}
}
});
grunt.registerTask('default', ['typescript', 'connect', 'open', 'watch']);
};
Make sure that you're following the instructions for including the live reload script as documented here. An example would be to include this script at the end of the body (assuming the default port):
<script src="//localhost:35729/livereload.js"></script>
I am kinda new to grunt and want to use it with Jekyll and some LESS-compiling.
My problem now is, I already have fully functioning LESS-comipiling with live reload and watch task and can build my jekyll site through grunt, but how do I run something like the jekyll serve or grunt-connect and grunt watch simultaneously?
I want a grunt task that provides the watching of my LESS-files etc, builds the jekyll site and then runs a small web server with grunt-connect or whatever.
My Gruntfile.js so far:
'use strict';
module.exports = function (grunt) {
grunt.initConfig({
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: [
'Gruntfile.js',
'js/*.js',
'!js/scripts.min.js'
]
},
less: {
dist: {
files: {
'css/styles.min.css': [
'less/app.less'
]
},
options: {
compress: true,
// LESS source map
// To enable, set sourceMap to true and update sourceMapRootpath based on your install
sourceMap: false,
sourceMapFilename: 'css/styles.min.css.map',
sourceMapRootpath: '/'
}
},
dev: {
files: {
'css/styles.min.css': [
'less/app.less'
]
},
options: {
compress: false,
// LESS source map
// To enable, set sourceMap to true and update sourceMapRootpath based on your install
sourceMap: true,
sourceMapFilename: 'css/styles.min.css.map',
sourceMapRootpath: '/'
}
}
},
uglify: {
dist: {
files: {
'js/scripts.min.js': [
'vendor/bootstrap/js/transition.js',
'vendor/bootstrap/js/alert.js',
'vendor/bootstrap/js/button.js',
'vendor/bootstrap/js/carousel.js',
'vendor/bootstrap/js/collapse.js',
'vendor/bootstrap/js/dropdown.js',
'vendor/bootstrap/js/modal.js',
'vendor/bootstrap/js/tooltip.js',
'vendor/bootstrap/js/popover.js',
'vendor/bootstrap/js/scrollspy.js',
'vendor/bootstrap/js/tab.js',
'vendor/bootstrap/js/affix.js',
'vendor/*.js',
'js/_*.js'
]
},
options: {
// JS source map: to enable, uncomment the lines below and update sourceMappingURL based on your install
// sourceMap: 'assets/js/scripts.min.js.map',
// sourceMappingURL: '/app/themes/roots/assets/js/scripts.min.js.map'
}
}
},
watch: {
less: {
files: [
'less/*.less',
'less/bootstrap/*.less'
],
tasks: ['less:dev']
},
js: {
files: [
'<%= jshint.all %>'
],
tasks: ['jshint', 'uglify']
},
livereload: {
// Browser live reloading
// https://github.com/gruntjs/grunt-contrib-watch#live-reloading
options: {
livereload: true
},
files: [
'_site/*'
]
}
},
clean: {
dist: [
'css/styles.min.css',
'css/styles.min.css.map',
'js/scripts.min.js',
'_site/*'
]
},
jekyll: { // Task
options: { // Universal options
bundleExec: true,
src : '<%= app %>'
},
dist: { // Target
options: { // Target options
dest: '<%= dist %>',
config: '_config.yml'
}
},
serve: { // Another target
options: {
serve: true,
drafts: true
}
}
},
connect: {
server: {
options: {
keepalive: true
}
}
}
});
// Load tasks
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-jekyll');
grunt.loadNpmTasks('grunt-contrib-connect');
// Register tasks
grunt.registerTask('default', [
'clean',
'less:dist',
'uglify',
'jekyll:dist'
]);
grunt.registerTask('dev', [
'watch'
]);
};
You need to tell connect what directory to serve up in the configuration using the "base" option, in this case it would be the static _site directory. You can also change the port to whatever you want, but you end up navigating to localhost:9009 with my example
connect: {
server: {
options: {
livereload: true,
base: '_site/',
port: 9009
}
}
}
You will also want to add a watch task for when you change your html templates. Something like this would work.
watch: {
html: {
files: ['**/*.html', '!_site/**/*.html'],
tasks: ['jekyll:dist']
}
}
Then create a "serve" task like Wallace suggested.
// Start web server
grunt.registerTask('serve', [
'jekyll:dist',
'connect:server',
'watch'
]);
Lastly run "grunt serve" in the command line and navigate to localhost with the port you specified.
As commented by #jiggy
The key change is to not set keepalive to true. Keepalive will block
all subsequent tasks from running. So long as connect is followed by
watch the server won't terminate.
I spent 2 days desperately trying every gruntfile-configuration I could find on the internet. Never worked. Then I found this https://stackoverflow.com/a/24765175/1541141.
Use grunt-contrib-connect, NOT grunt-connect. grunt-connect is blocking...
Hope it helps.
I think the heart of your solution is to create a new task or edit an existing task, like so:
// Start web server
grunt.registerTask('serve', [
'jekyll:dist',
'connect:livereload',
'watch'
]);
...which you would run with a $ grunt serve. less, jshint, uglify and connect are already included under watch.
I have recently discovered grunt as it is used within an opensource project I have started to work on. Having not worked with grunt before I am struggling to see how it works, or in my case doesn't.
The grunt file is supplied by the project and I assume it works for everyone else. I have installed grunt and the necessary grunt modules have all installed in the "Node_modules" directory.
When running the grunt file the first process performs a number of concatenations and this seems to work fine. The concatenated files are created.
All of the other steps do not seem to execute. The files they are intended to create are not created. There is no error message displayed on the console when grunt is executed.
I'm stumped - anyone have any clues what might be the problem.
The grunt file is :
/*global module:false*/
module.exports = function(grunt) {
// Project configuration...
grunt.initConfig({
manifest: grunt.file.readJSON('chrome/manifest.json'),
concat: {
dist: {
src: ['chrome/js/requester/**/*.js'],
dest: 'chrome/js/requester.js'
},
requester_html: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/footer.html'
],
dest: 'chrome/requester.html'
},
requester_tester: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/footer.html',
'chrome/html/requester/tester.html'
],
dest: 'chrome/tester.html'
}
},
mindirect: {
dist: {
src: ['chrome/js/requester.js'],
dest: 'chrome/js/requester.min.js'
}
},
watch: {
requester_templates: {
files: ['chrome/html/requester/templates/*'],
tasks: ['handlebars'],
options: {
livereload: true
}
},
requester_js: {
files: ['chrome/js/requester/**/*.js'],
tasks: ['concat:dist'],
options: {
livereload: true
}
},
requester_html: {
files: ['chrome/html/requester/*', 'chrome/html/requester/modals/*', 'chrome/html/requester/loggers/*'],
tasks: ['concat:requester_html', 'concat:requester_tester'],
options: {
livereload: true
}
},
requester_css: {
files: ['chrome/css/**/*.scss'],
tasks: ['sass'],
options: {
livereload: true
}
}
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true
}
},
handlebars: {
compile: {
options: {
partialsUseNamespace: true,
namespace: 'Handlebars.templates',
processPartialName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
},
processName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
}
},
files: {
"chrome/html/requester/templates.js": "chrome/html/requester/templates/*"
}
}
},
sass: {
dist: {
files: {
'chrome/css/requester/styles.css': 'chrome/css/requester/styles.scss'
}
}
},
compress: {
main: {
options: {
archive: 'releases/v<%= manifest.version %>.zip'
},
files: [
{src: ['chrome/**', '!chrome/tests/**', '!chrome/manifest_key.json', '!chrome/tester.html'], dest: '/'}, // includes files in path and its subdirs
]
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-handlebars');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mindirect');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compress');
// Default task.
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
};
The output from the console is as follows :
Running "jshint:globals" (jshint) task
>> 0 files lint free.
Running "concat:dist" (concat) task
File "chrome/js/requester.js" created.
Running "concat:requester_html" (concat) task
File "chrome/requester.html" created.
Running "concat:requester_tester" (concat) task
File "chrome/tester.html" created.
Done, without errors.
Given that the tasks are defined like this:
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
the output you show is what you'd expect if you are running grunt without a task name. It runs the jshint and concat tasks.
If you want to run the tasks associated with package, then you have to run grunt package to run those tasks.
It looks like I did not understand "tasks" within grunt.
Instead of executing "grunt" which runs the "default" tasks, I had to execute "grunt package" which runs the tasks that I was interested in.
As Louis said, you have to specify the right task to run.
But you can also create or modify the tasks you have in order to make it simpler. In your example you may include package in the default task. Because concat task is already executed inside package, you may just replace it in the default task:
grunt.registerTask('default', ['jshint', 'package']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
and, in order to build your site, just type
grunt
both jshint and package tasks will be executed