Grunt compress : How could I only include runtime node module dependencies? - node.js

My application is MEAN stack style. I would like to generate a package including all Nodejs and AngularJs files, so I could just unzip the package and run in other environments.
I use grunt-contrib-compress to compress and generate a zip file. Everything works well, but there are many development node modules are included, such as grunt*. All I need is the runtime node modules which are defined in the package.json. It will dramatically reduce the package size.
I could include the node modules one by one, but is there a good way only include runtime modules while packaging?

OK, I found a solution, which load the package.json and map the runtime dependencies into target folders.
compress: {
main: {
options: {
archive: 'myapp.zip'
},
files: [
{src: ['dist/**','app/**','config/**','server.js'],dest:'.'},
{src: Object.keys(require('./package.json').dependencies).map(function(module){
return "node_modules/" +module+"/**"
}),dest:'.'},
]
}
}

I had exactly the same question today, and after asking and coming up with a very similar solution, I have found your question. Here is my, similar but slightly different approach:
function getDependencies(pkg) {
return Object.keys(pkg.dependencies).map(function(val) { return val + '/**'; });
}
module.exports = function(grunt) {
var pkg = grunt.file.readJSON('package.json');
var config = {
pkg: pkg,
clean: ["public/"],
compress: {
validate: {
options: {
archive: 'public/Lambda.zip'
},
files: [
{ expand: true, cwd: 'src/', src: ['**'], dest: '/' },
{ expand: true, cwd: 'node_modules/', src: getDependencies(pkg), dest: '/node_modules' }
]
}
}
};
grunt.initConfig(config);
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.registerTask('build', ['clean', 'compress']);
}

Related

Nuxt Build Doesn't Include node_modules CSS

Sorry I'm quite new to Nuxt & Webpack. I have a Nuxt project in which everything works fine running yarn dev. But when I build using yarn build -> yarn generate, the .css files I reference in the node_modules directory (dropzone.css, flatpickr.css etc) are never included and break the site. I've tried everything but can't figure out what I'm doing wrong. Can someone point me in the right direction? Currently running Nuxt v2.11.0 with Tailwind.css. This is my nuxt.config.js file which is mostly boilerplate -
require('dotenv').config()
export default {
env: {
baseUrl: process.env.BASE_URL || '/',
apiUrl: process.env.API_URL
},
mode: 'universal',
css: [
'#/assets/css/tailwind.css',
'#/assets/fonts/caslongraphique/webfont.css',
'#/assets/fonts/turbinadobolddry/font.css',
{ src: 'nuxt-dropzone/dropzone.css', lang: 'css' },
{ src: 'vue-agile/dist/VueAgile.css', lang: 'css' },
{ src: 'flatpickr/dist/flatpickr.css', lang: 'css' },
{ src: 'flatpickr/dist/themes/airbnb.css', lang: 'css' }
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~plugins/helpers' },
{ src: '~plugins/vue-moment' },
{ src: '~plugins/vue-agile', mode: 'client' },
{ src: '~plugins/eventBus', mode: 'client' },
{ src: '~plugins/axios', mode: 'client' },
{ src: '~plugins/vuex-persist', mode: 'client' }
],
buildModules: [
// Doc: https://github.com/nuxt-community/nuxt-tailwindcss
'#nuxtjs/tailwindcss',
],
modules: [
'#nuxtjs/axios',
'#nuxtjs/dotenv',
// 'nuxt-client-init-module'
],
build: {
/*
** You can extend webpack config here
*/
extend (config, ctx) {
},
postcss: {
plugins: {
// Disable a plugin by passing false as value
'postcss-url': false,
'postcss-nested': {},
'autoprefixer': true
},
preset: {
// Change the postcss-preset-env settings
autoprefixer: {
grid: true
}
}
},
}
}
It's pretty hard to answer this without having the full project to build and run. I assume you're not using a separate webpack config file when building for production, otherwise you would have added that to the question. You seem to be using the correct syntax in the config file, so I'm guessing your css file paths are not quite right. They kinda look like the old way of doing things, you may want to confirm that they're not out of date. This old-ish github issue goes through the various things you could try, on of them being let nuxt find the "compiled" version of the css automatically for you like this:
css: [
'nuxt-dropzone',
...etc
],
Try removing all of the 3rd party css files and add them back one at a time, after the previous one works.
This example is from the official docs:
export default {
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'#/assets/css/main.css',
// SCSS file in the project
'#/assets/css/main.scss'
]
}

Grunt - Compile Multiple Jade Files using the Pug plugin

I have a Laravel directory structure and I have my Jade templates in the /resources/assets/jade/ folder.
Inside this folder will have multiple sub-directories which I will need to copy their exact structure to the /public/app/ directory where my app will be served from..
I have also got Typescript files being compiled into the same directory structure so its very important that the directory layout is copied as I have set it up.. I cant seem to do this successfully using the Grunt Pug plugin.. any help greatly appreciated, heres what I have so far:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
pug: {
compile: {
options: {
client: false,
pretty: true,
data: {
debug: false
}
},
files: [{
'public/app/index.html': ['resources/assets/jade/index.jade']
},
{
src: "resources/assets/jade/*.jade",
dest: "public/app",
expand: true,
ext: ".html"
} ]
}
},
});
grunt.loadNpmTasks('grunt-contrib-pug');
grunt.registerTask('default', ['pug'] );
};
Looks like the old grunt-contrib-jade syntax works with PUG although I didnt see it documented anywhere so for dexterity heres what works perfectly:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
pug: {
compile: {
options: {
client: false,
pretty: true
},
files: [ {
cwd: "resources/assets/jade",
src: "**/*.jade",
dest: "public/app",
expand: true,
ext: ".html"
} ]
}
},
});
grunt.loadNpmTasks('grunt-contrib-pug');
grunt.registerTask('default', ['pug'] );
};

Grunt: How to build the files object dynamically

I must be missing something very simple here. I'm trying to write a function task that deals with files. The Grunt API docs mention that you can [Build the files object dynamically], but for some reason I can't get this to work. A simplified version of my Gruntfile.js file looks like this:
module.exports = function(grunt) {
grunt.initConfig({
proj: {
build: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist'
}]
}
}
});
grunt.registerTask('proj', function(){
var files = grunt.config('proj.build.files');
console.log(files);
});
};
I expect the log to show a list of file mappings from the src directory to the dist directory. What actually gets logged is the object proj.build.files from the config, like this:
Running "proj:build" task
[ { expand: true, cwd: 'src', src: [ '**/*.js' ], dest: 'dist' } ]
Done, without errors.
The API docs only talk about this type of configuration in terms of other tasks. I tried looking through the uglify task to see how the file mappings are retrieved, but I couldn't figure it out.
Here is the workaround I found to dynamically build filesets for Grunt tasks:
uglify: {
app: {
files: [{
src: '{<%= _prefixSrc(pkg.target, pkg.resources.js) %>}', // Note the brackets!
dest: '<%= pkg.target %>min/<%= pkg.name %>.min.js'
}]
}
},
_prefixSrc: function(prefix, files) {
return files.map(function(file){
return prefix + file;
});
},
See also this issue/feature request on GitHub and feel free to comment it if you find it useful: https://github.com/gruntjs/grunt/issues/1307
You can use rename function to change file name is files object like below...
build: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist',
rename: function(dest, src) {
/*
rename logic
you will have access to src and dest name and can return desirect name from this function.
*/
return src+123;
}
}]
}

grunt error: cannot find module 'load-grunt-tasks'

When I am using grunt command it is showing me following error:
$ grunt
Loading "Gruntfile.js" tasks...ERROR
>> Error: Cannot find module 'load-grunt-tasks'
Warning: Task "default" not found. Use --force to continue.
Aborted due to warnings.
Execution Time (2015-02-07 18:05:42 UTC)
loading tasks 339ms ███████████████████████████████████████████████ 99%
Total 344ms
I already tried - npm install, npm update commands. It would be great if someone can help me with this. Thanks!
Addding Content of Gruntfile.js
'use strict';
var paths = {
js: ['*.js', 'test/**/*.js', '!test/coverage/**', '!bower_components/**', 'packages/**/*.js', '!packages/**/node_modules/**', '!packages/contrib/**/*.js', '!packages/contrib/**/node_modules/**'],
html: ['packages/**/public/**/views/**', 'packages/**/server/views/**'],
css: ['!bower_components/**', 'packages/**/public/**/css/*.css', '!packages/contrib/**/public/**/css/*.css']
};
module.exports = function(grunt) {
if (process.env.NODE_ENV !== 'production') {
require('time-grunt')(grunt);
}
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
assets: grunt.file.readJSON('config/assets.json'),
clean: ['bower_components/build'],
watch: {
js: {
files: paths.js,
tasks: ['jshint'],
options: {
livereload: true
}
},
html: {
files: paths.html,
options: {
livereload: true,
interval: 500
}
},
css: {
files: paths.css,
tasks: ['csslint'],
options: {
livereload: true
}
}
},
jshint: {
all: {
src: paths.js,
options: {
jshintrc: true
}
}
},
uglify: {
core: {
options: {
mangle: false
},
files: '<%= assets.core.js %>'
}
},
csslint: {
options: {
csslintrc: '.csslintrc'
},
src: paths.css
},
cssmin: {
core: {
files: '<%= assets.core.css %>'
}
},
nodemon: {
dev: {
script: 'server.js',
options: {
args: [],
ignore: ['node_modules/**'],
ext: 'js,html',
nodeArgs: ['--debug'],
delayTime: 1,
cwd: __dirname
}
}
},
concurrent: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
},
mochaTest: {
options: {
reporter: 'spec',
require: [
'server.js',
function() {
require('meanio/lib/core_modules/module/util').preload(__dirname + '/packages/**/server', 'model');
}
]
},
src: ['packages/**/server/tests/**/*.js']
},
env: {
test: {
NODE_ENV: 'test'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
});
//Load NPM tasks
require('load-grunt-tasks')(grunt);
/**
* Default Task
*/
grunt.hook.push('clean', -9999);
grunt.hook.push('concurrent', 9999);
if (process.env.NODE_ENV === 'production') {
grunt.hook.push('cssmin', 100);
grunt.hook.push('uglify', 200);
} else {
grunt.hook.push('jshint', -200);
grunt.hook.push('csslint', 100);
}
//Default task.
grunt.registerTask('default', ['hook']);
//Test task.
grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
// For Heroku users only.
// Docs: https://github.com/linnovate/mean/wiki/Deploying-on-Heroku
grunt.registerTask('heroku:production', ['cssmin', 'uglify']);
};
Try running:
$ npm install
After that, if you run it and the error still persists or if there's another one, then you probably have not installed ruby, compass or both :)
I had the same issue, the problem for me was in my package.json where I didn't actually install the NPM package needed and it was not automatically installed as previously thought. Try doing
npm install --save-dev load-grunt-tasks
If that doesn't work can you provide the package.json file as well so we can get a little more information.
I was having the same issue you were having, it seems as though the gruntfile is missing a required initialization step.
By changing this:
require('load-grunt-tasks')(grunt);
/**
* Default Task
*/
grunt.hook.push('clean', -9999);
to this:
require('load-grunt-tasks')(grunt);
grunt.loadNpmTasks('grunt-hook');
/**
* Default Task
*/
grunt.hook.push('clean', -9999);
Adding the grunt.loadNpmTasks call, I'm able to get past that issue. The problem is, now I'm getting
Task "clean" not found. Use --force to continue.
Looking at the rest of the grunt file, i don't see a register task for clean. If I go to the mean.io docs, it looks like the build is failing. Perhaps this is part of why? I think I asked mean-cli for gulp version, that's probably why. I'll delete and take it from the top :)
I think the problem is related to where the npm dependencies are declared and the way Heroku handles them.
In few words, check if the npm packages are as dev dependencies and move them to the dependencies block, as suggested here: https://stackoverflow.com/a/20687098/532912.

How to copy compiled jade files to a destination folder using grunt

For a single page app that I'm working on, I have the following structure:
dist
css
js
lib
partials
index.html
src
css
js
lib
views
partials
index.jade
Directory dist will be used by the express server to serve the project. I have trivial grunt tasks (using grunt-contrib-clean, grunt-contrib-copy) for cleaning dist and copying src/css, src/js, src/lib to dist.
The problem lies with src/views. This directory contains jade files which need to be compiled to html files. After compilation I want them in dist (index.html in the dist root, partials as subdir).
At the moment I am using the grunt-contrib-jade task to compile and copy the jade files. I want to copy them to dist, since I don't want to add the compiled html files to source control. But now this is not really workable, since you have to specify every jade file (now there are only a few, but that will grow):
jade: {
compile: {
options: {
pretty: true
},
files: {
// TODO make one line
'dist/index.html': ['src/views/index.jade'],
'dist/partials/banner.html': ['src/views/partials/banner.jade'],
'dist/partials/dashboard.html': ['src/views/partials/dashboard.jade'],
'dist/partials/navbar.html': ['src/views/partials/navbar.jade'],
'dist/partials/transfer.html': ['src/views/partials/transfer.jade']
}
}
},
Is there any way to use the grunt-contrib-jade task (or another one) with a directory filter? Like this:
jade: {
compile: {
options: {
pretty: true
},
dir: {
'dist': ['src/views']
}
}
}
Little clarification from Grunt wiki - expand mapping:
grunt.file.expandMapping(patterns, dest [, options])
Note that while this method may be used to programmatically generate a files array for a multi task, the declarative syntax for doing this described in the "Building the files object dynamically" section of the Configuring tasks guide is preferred.
Assuming the above, configuration will look like this:
files: [ {
expand: true,
src: "**/*.jade",
dest: "dist/",
cwd: "src/views",
ext: '.html'
} ];
Same result with declarative configuration.
I ended up upgrading to grunt 0.4 (which causes some other problems, but that I'll be able to handle).
With grunt version 0.4 it is possible to use grunt.file.expandMapping:
jade: {
compile: {
options: {
pretty: true
},
files: grunt.file.expandMapping(['**/*.jade'], 'dist/', {
cwd: 'src/views',
rename: function(destBase, destPath) {
return destBase + destPath.replace(/\.jade$/, '.html');
}
})
}
},
If you want to change only the extension of the files from .jade to .html, another option would be using the flatten and ext parameters like so:
jade: {
compile: {
options: {
data: { debug: false, title: 'My awesome application' }
},
files: grunt.file.expandMapping(['**/*.jade'], '<%= yeoman.dist %>/views', {
cwd: '<%= yeoman.app %>/views',
flatten: true,
ext: '.html'
})
}
}
Or even better (as explained here):
jade: {
compile: {
options: {
data: { debug: false, title: 'My awesome application' },
pretty: true
},
files: [
{
expand: true,
cwd: '<%= yeoman.app %>/views',
src: ['**/*.jade'],
dest: '<%= yeoman.dist %>/views',
ext: '.html'
}
]}
}
Thanks.

Resources