Grunt CriticalCss not generating critical css but 'grunt critical' command working in Magento2.4 - gruntjs

I installed grunt-critical into a Magento2.4 project and would like to generate critical CSS but it's not rendering CSS into the critical.css file.
I created this task in dev\tools\grunt\tasks\critical.js
module.exports = function (grunt) {
'use strict';
grunt.registerTask("critical", function () {
grunt.initConfig({
critical: {
test: {
options: {
width: 1300,
height: 900
},
src: 'index.php',
dest: 'pub\static\frontend\<Vendor>\<theme>\css\critical.css'
}
}
});
});
};
in CMD it's showing results and I don't know what step I'm missing for generating critical CSS.
I followed this grunt-critical steps to generate critical css.
E:\wamp64\www\dist>grunt critical
Running "critical" task
Done.
Execution Time (2022-07-18 17:31:49 UTC+5:30)
loading tasks 65ms ██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 97%
critical 2ms ███████ 3%
Total 67ms

Related

Grunt refuses to create a custom.min.css file

I'm currently learning how to use PostCSS with Grunt in one of my classes. Asked my professor if they could help me, they said the Gruntfile.js looked fine, but maybe the issue was my file name being lowercase. I changed it to Gruntfile.js and am receiving the same error. It is automatically supposed to create the custom.min.css, but due to the error (located below), it does not. I contacted my professor, but it seems that we've hit a dead-end.
Every time I create the JS file for Grunt, save it in the correct folder, and I run grunt in my Command Prompt, I receive the following error:
C:\Users\name\Desktop\grunt-boilerplate>
Loading "Gruntfile.js" tasks...ERROR
SyntaxError: Invalid or unexpected token
Warning: Task "default" not found. Use --force to continue.
Aborted due to warnings.
My JS coding looks like this:
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
postcss: {
options: {
processors: [
require('pixrem')(), // add fallbacks for rem units
require('autoprefixer')({
browsers: 'last 2 versions'
}), // add vendor prefixes
require('cssnano')() // minify the result
]
},
dist: {
src: 'css/custom.css',
dest: 'css/custom.min.css',
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-postcss');
// Default task(s).
grunt.registerTask('default', ['postcss']);
};
What am I doing wrong?
Error loading "Gruntfile.js" tasks
As for the error in the terminal, it seems like you're missing this line at the start of the file:
module.exports = function (grunt) {
See: https://gruntjs.com/getting-started#an-example-gruntfile
Now about the first problem.
Packages
First of all, check the correct installation of all your node modules.
Open your terminal
cd to your project root, where the package.json is located
Do npm install
Do npm install autoprefixer grunt grunt-postcss pixrem cssnano --save-dev
Autoprefixer usage
You are probably using the autoprefixer plugin in a wrong way: you need to move the browsers option into your package.json file:
Gruntfile.js
...
processors: [
require('pixrem')(),
// No autoprefixer 'browsers' option
require('autoprefixer')(),
require('cssnano')()
]
...
package.json
{
...
// 'browserslist' option at the end of the file just above the last curly brace
'browserslist': [
'last 4 versions',
'> 0.5%'
]
}
See: https://github.com/browserslist/browserslist#browserslist-
Changing dist property
You could try changing your dist syntax using files property:
...
dist: {
// src: 'css/custom.css',
// dest: 'css/custom.min.css',
files: {
'css/custom.min.css': 'css/custom.css'
}
}
...
Summary
The whole Gruntfile.js should look something like that:
module.exports = function (grunt) {
grunt.initConfig({
// This is probably a leftover from the example Gruntfile.js
// pkg: grunt.file.readJSON('package.json'),
postcss: {
options: {
processors: [
require('pixrem')(),
// No autoprefixer 'browsers' option
require('autoprefixer')(),
require('cssnano')()
]
},
dist: {
// src: 'css/custom.css',
// dest: 'css/custom.min.css',
files: {
'css/custom.min.css': 'css/custom.css'
}
}
}
});
grunt.loadNpmTasks('grunt-postcss');
grunt.registerTask('default', ['postcss']);
};

How do I generate sourcemaps for Uglified files using Grunt?

I have a Grunt project that uses both Browserify and Uglify. Here are the core bits of it:
browserify: {
myapp: {
options: {
transform: ['babelify'],
browserifyOptions: {
debug: true
},
},
src: 'src/index.js',
dest: 'build/myapp.js'
}
},
uglify: {
options: {
sourceMap: true,
banner: bannerContent
},
target: {
src: 'build/myapp.js',
dest: 'build/myapp.min.js'
}
},
It seems to generate a myapp.min.js.map file but it no longer has the raw sources in the source-map that existed prior to the Browserification.
Here's what the resultant source-map file contains:
{
"version":3,
"sources":[
"myapp.js"
],
"names":[
...
...
...
],
"mappings":".........",
"file":"myapp.min.js"
}
I've tried using the uglifyify transform for Browserify but that does not seem to generate as small files as the Uglify task.
I've also bumped all my dependencies to the latest but I haven't been able to resolve this issue.
grunt-contrib-uglify has a sourceMapIn option that allows you to specify the location of an input source map file from an earlier compilation - which in your scenario is the browserify task.
However, whilst setting browserifyOptions: { debug: true } in your browserify task does generate an inline source map in the resultant .js file (i.e. in build/myapp.js), the crux of the problem is twofold:
We don't have an external source map file that we can configure the sourceMapIn option of the subsequent grunt-contrib-uglify task to utilize.
grunt-browserify doesn't provide a feature to create an external .map file, it only creates them inline (see here)
To address the aforementioned issue consider utilizing grunt-extract-sourcemap to extract the inline source map from build/myapp.js (i.e. from the output file generated by your browserify task) after it has been produced.
Gruntfile.js
The following gist shows how your Gruntfile.js should be configured:
module.exports = function (grunt) {
grunt.initConfig({
browserify: {
myapp: {
options: {
transform: ['babelify'],
browserifyOptions: {
debug: true
},
},
src: 'src/index.js',
dest: 'build/myapp.js'
}
},
extract_sourcemap: {
myapp: {
files: {
'build': ['build/myapp.js']
}
}
},
uglify: {
options: {
sourceMap: true,
sourceMapIn: 'build/myapp.js.map'
},
target: {
src: 'build/myapp.js',
dest: 'build/myapp.min.js'
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-extract-sourcemap');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Note the order of the tasks in your task list is important.
grunt.registerTask('default', ['browserify', 'extract_sourcemap', 'uglify']);
};
Explanation
First the browserify task is invoked which outputs a new file (i.e. build/myapp.js) containing your bundled JavaScript and an "inlined" source map info. If you were to inspect the content of build/myapp.js at this stage it includes something like the following at the end:
//# sourceMappingURL=data:application/json;charset=utf-8;base64, ...
Next the extract_sourcemap task is invoked. This essentially extracts the "inlined" source map info from build/myapp.js and writes it to a new file named myapp.js.map which is saved in your build directory.
The original "inlined" source map info in build/myapp.js is replaced with a link to the newly generated source map file, i.e. myapp.js.map. If you inspect the content of build/myapp.js you'll now notice the following at the end of the file instead:
//# sourceMappingURL=myapp.js.map
Lastly the uglify task is invoked. Notice how its sourceMapIn option is configured to read build/myapp.js.map, i.e the source map file we generated at step 2.
This task creates your desired build/myapp.min.js file containing; your minified JS, and a link to a newly generated source map file build/myapp.min.js.map.
Note The final resultant file (i.e. build/myapp.min.js) now correctly maps back to the original src/index.js file and any file(s) that index.js itself may have import'ed or require()'d

Grunt only running one task

This is my first time trying to set up Grunt. I'm seeing that only one out of two defined tasks is running at a time. If I switch the default task from 'watch' to 'sass', only the sass task will run (and vice versa). So that makes me think the code for both tasks is correct, but maybe some other configuration setting or registerTask type function is needed.
Is there anything wrong with my Gruntfile.js that would cause this issue?
Gruntfile.JS
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// --- SASS
sass:{
dist:{
options:{
style:'expanded',
sourcemap:'none',
},
files:{
'style.css':'SCSS/style.scss'
}
}
},
// --- WATCH
watch:{
css:{
files: '**/*.scss',
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
// grunt.registerTask('default',['sass']);
grunt.registerTask('default',['watch']);
}
watch: {
css: {
files: '**/*.scss',
tasks: ['sass'],
},
},
That's it, just add the sass task to watch and whenever the files change, the task will be run.
Alternatively, don't register watch as a task at all! You can set sass as the default grunt task, and simply type grunt watch to kick off the watch task.
Now if you're using something like the Nuget package in VS I understand registering watch, but if that's the case I suggest trying out Powershell, at least for the ease of installing new packages, node modules, getting a debug message for JS errors, etc.

grunt-contrib-less not working (no errors but no output css)

I have a less compile grunt task where relative path to less files from grunt installed folder is raw/less/source_map/
here is the grunt file.
Gruntfile: (EDIT: changed to #Yogesh Khatri's code still same issue)
module.exports = function(grunt) {
grunt.initConfig({
less: {
files: { "raw/less/source_map/style.css" : "raw/less/source_map/style.less" }
},
watch: {
js: {
files: ['raw/less/source_map/style.less'],
tasks: ['default'],
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['less']);
};
on running it the command line displays
^CMacPro:grunt sagiavinashvarma$ grunt watch
Running "watch" task
Waiting...
>> File "raw/less/source_map/style.less" changed.
Running "less:files" (less) task
Done, without errors.
Completed in 1.862s at Tue Dec 09 2014 15:03:37 GMT+0530 (IST) - Waiting...
but there is no style.css output. I have written the simplest grunt task without any options.
can anyone point out whats wrong with this.
Edit:
I got the problem. It isn't working because less task need a specific target to work.
Try to change the code like this
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
files: { "raw/less/source_map/style.css" : "raw/less/source_map/style.less" }
}
},
watch: {
js: {
files: ['raw/less/source_map/style.less'],
tasks: ['default'],
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['less']);
};
I got the error by running grunt --verbose which shows lot more information about the tasks. It gave me the output like
Verifying property less.files exists in config...OK
File: [no files]
Options: report="min", banner=""
>> Destination not written because no source files were provided.
of which searching led me to this :- grunt-contrib-less cannot find source files even though path is correct

Grunt - livereload only uglified script.js?

GruntJS newbie here. I currently have my gruntfile.js using the watch task to look for changes to any .js files in my js/components/ folder and uglify those scripts into a single script.js file.
The issue that I'm having is that these changes cause a full page reload.
Is it possible to only reload the script.js file without also reloading the HTML/CSS? The effect I'm after is the same effect I'm currently getting with SASS/CSS files like so:
watch : {
options: { livereload: true },
sass: {
options: {
livereload: false
},
files: ['css/sass/*.scss'],
tasks: ['compass:dev']
},
css: {
files: ['css/*.css']
}
}
This reloads only my CSS without reloading the entire page, which makes for a much smoother workflow. Is it possible to do the same for JS? If not, why not? My current JS workflow configuration looks like this:
grunt.initConfig({
uglify: {
my_target: {
files: {
'js/script.js' : ['js/components/*.js']
}
}
},
watch : {
options: { livereload: true },
scripts: {
files: ['js/components/*.js'],
tasks: ['uglify']
}
}
});
After reading around I finally wound up on the livereload.js Github page. Under the developer's rundown of the project's current status, "Live JS reloading" is the one remaining to-do item. So it's a planned feature, but not yet implemented. The last commit on the project was 7 months back, so I'm not sure when/if we can anticipate this update.

Resources