- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 grunt-unused 删除多个子目录中所有未使用的图像链接。 .为清楚起见,这是我的文件夹结构:
|-- dist
| |-- site-1
| | |—-index.html
| | |—-style.css
| | |—-app.js
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg
| | |—-image4.jpg
| |-- site-2
| | |—-index.html
| | |—-style.css
| | |—-app.js
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg
| | |—-image4.jpg
| |-- site-3
| | |—-index.html
| | |—-style.css
| | |—-app.js
| | |—-image1.jpg
| | |—-image2.jpg
| | |—-image3.jpg
| | |—-image4.jpg
我写了一个“forEach”函数来定位这些子文件夹,然后引用每个文件夹,类似于 this post但它不适用于未使用的任务。它不会遍历每个目录,并且控制台会在非常短的时间内检测到没有未使用的文件,就像它实际上没有做任何事情一样。
我哪里错了?
grunt.registerTask('prodOutput', function () {
// read all subdirectories of dist/ folder, excluding the assets folder
grunt.file.expand('dist/*', '!dist/assets/**').forEach(function (dir) {
//get the current unused config
var unusedConfig = grunt.config.get('unused') || {};
//set options for grunt-unused, including the folder variable 'dir' as the reference of where to look
unusedConfig[dir] = {
option: {
reference: dir + '/',
directory: ['**/*.css', '**/*.html', '**/*.js'],
remove: false, // set to true to delete unused files from project
reportOutput: 'report.txt', // set to false to disable file output
fail: false // set to true to make the task fail when unused files are found
}
};
grunt.config.set('unused', unusedConfig);
});
grunt.task.run('unused');
});
最佳答案
正如我之前在评论中提到的...主要问题是您正在动态配置多个 Targets在您的 forEach
函数中运行任务之前,但是 grunt-unused不支持多目标配置。
此外,grunt-unused
期望包含对其他文件的引用/链接的文件(即 index.html
)与它所在的文件位于不同的目录/文件夹中引用(例如图像、css 等),但是您帖子中提供的文件夹结构是扁平化的。
快速浏览其他 grunt 插件后,似乎没有一款能满足您的要求。我认为您可以实现此目的的唯一方法是编写您自己的自定义任务/插件来处理此问题。
为此,您可以执行以下操作:
创建一个单独的 Javascript 模块,导出 Registered MutliTask .将文件命名为 delete-unused.js
并将其保存到名为 tasks
的目录中,该目录与 Gruntfile.js
位于同一顶级目录中.
目录结构
你的目录结构应该是这样的:
.
├── dist
│ ├── site-1
│ ├── site-2
│ ├── ...
│ └── assets
│
├── Gruntfile.js
│
├── node_modules
│ └── ...
│
├── package.json
│
└── tasks
└── delete-unused.js
删除-unused.js
module.exports = function(grunt) {
'use strict';
// Requirements
var fs = require('fs');
var path = require('path');
grunt.registerMultiTask('unused', 'Delete unused assets', function() {
// Default options. These are used when no options are
// provided via the initConfig({...}) papaparse task.
var options = this.options({
reportOutput: false,
remove: false
});
var reportTxt = '';
// Loop over each src directory path provided via the configs src array.
this.data.src.forEach(function(dir) {
// Log if the directory src path provided cannot be found.
if (!grunt.file.isDir(dir)) {
grunt.fail.warn('Directory not found: '.yellow + dir.yellow);
}
// Append a forward slash If the directory path provided
// in the src Array does not end with one.
if (dir.slice(-1) !== '/') {
dir += '/';
}
// Generate the globbin pattern (only one level deep !).
var glob = [dir, '*'].join('');
// Create an Array of all top level folders (e.g. site-*)
// in the dist directory and exclude the assets directory.
var dirs = grunt.file.expand(glob).map(function(dir) {
return dir;
});
// Loop over each directory.
dirs.forEach(function(dir) {
// Add the folders to exclude here.
if (dir === './dist/assets') {
return;
}
// Log status and update report
grunt.log.write('\nProcessing folder ' + dir);
reportTxt += '\nProcessing folder ' + dir;
// Empty Array to be populated with unused asset references.
var unused = [];
// Define the path to index.html
var pathToHtml = [dir, '/', 'index.html'].join('');
// Create Array of file names and filepaths (exclude index.html)
var assets = grunt.file.expand([dir + '/**/*.*', '!index.html'])
.map(function(file) {
return {
fpath: file,
fname: path.basename(file)
};
});
// Log/Report missing 'index.html' and return early.
if (!grunt.file.exists(pathToHtml)) {
grunt.log.write('\n >> Cannot find index.html in ' + dir + '/\n');
reportTxt += '\n >> Cannot find index.html in ' + dir + '/\n';
return;
}
// Read the contents of index.html.
var html = fs.readFileSync(pathToHtml, {
encoding: 'utf8'
});
// Loop over each file asset to find if linked in index.html
assets.forEach(function(asset) {
// Backslash-escape the dot [.] in filename for RegExp object.
var escapedFilename = asset.fname.replace('.', '\\.');
// Dynamically create a RegExp object to search for instances
// of the asset filename in the contents of index.html.
// This ensures the reference is an actual linked asset and
// not plain text written elsewhere in the document.
//
// For an explanation of this Regular Expression visit:
// https://regex101.com/r/XZpldm/4/
var regex = new RegExp("(?:href=|src=|url\\()(?:[\",']?)(.*"
+ escapedFilename + ")[\",',\\)]+?", "g");
// Search index.html using the regex
if (html.search(regex) === -1 && asset.fname !== 'index.html') {
unused.push(asset); // <-- Not found so add to list.
}
});
// Log status and update report
grunt.log.write('\n ' + unused.length + ' unused assets found:\n');
reportTxt += '\n ' + unused.length + ' unused assets found:\n';
//Delete the unused asset files.
unused.forEach(function(asset) {
if (options.remove) {
grunt.file.delete(asset.fpath);
// Log status and update report
grunt.log.write(' deleted: ' + asset.fpath + '\n');
reportTxt += ' deleted: ' + asset.fpath + '\n';
} else {
// Log status and update report
grunt.log.write(' ' + asset.fpath + '\n');
reportTxt += ' ' + asset.fpath + '\n';
}
});
});
if (options.reportOutput) {
grunt.file.write(options.reportOutput, reportTxt);
}
});
});
};
Gruntfile.js
按如下方式配置您的 Gruntfile.js
。
module.exports = function(grunt) {
'use strict';
grunt.initConfig({
// ...
unused: {
options: {
reportOutput: 'report.txt',
remove: true
},
dist: {
src: ['./dist/']
}
}
});
// Load the custom multiTask named `unused` - which is defined
// in `delete-unused.js` stored in the directory named `tasks`.
grunt.loadTasks('./tasks');
// Register and add unused to the default Task.
grunt.registerTask('default', [
// ...
'unused',
// ...
]);
// Or add it to another named Task.
grunt.registerTask('foobar', [
// ...
'unused',
// ...
]);
};
注意事项
grunt-unused
插件不再使用,因此您可以通过 CLi 工具运行以下命令来卸载它:$ npm un -D grunt-unused
delete-unused.js
自定义模块在 Gruntfile.js
中提供了类似的配置,但选项少于 grunt-unused< 中的选项
。配置中的 src
数组接受要处理的文件夹的路径(即 ./dist/
)。而不是 glob 模式 - glob 模式是在 grunt-unused.js
中生成的。
reportOutput
和 remove
的默认选项在 grunt-unused.js
中设置为 false
>。当您第一次运行任务时,我建议您首先在 Gruntfile.js
配置中将 remove
选项设置为 false
。这将简单地将未使用的 Assets 记录到控制台,并允许您检查它是否满足您的要求。显然,将 remove
选项设置为 true
将在重新运行时删除任何未使用的 Assets 。
我注意到您在帖子中提供了 glob 模式 '!dist/assets/**'
以排除 assets
文件夹被处理。不是通过 src
配置传递要排除的 glob 模式,而是在 delete-unused.js
中进行硬编码。您会在以下行中看到它:
// Add the folders to exclude here.
if (dir === './dist/assets') {
return;
}
如果 dist
文件夹中有您想要排除的其他目录,您需要将它们添加到那里:例如:
// Add the folders to exclude here.
if (dir === './dist/assets'
|| dir === './dist/foo'
|| dir === './dist/quux') {
return;
}
此解决方案仅检查在 site-*
文件夹中找到的 Assets 是否在相应的 index.html
中被链接/引用,而不检查它们是否在任何 .css
文件中被引用。
delete-unused.js
使用正则表达式来查找 Assets 是否实际链接到 index.html
并且不是在其他地方编写的纯文本文档(例如在一段文本中)。可以找到使用的自定义正则表达式的解释 here .
希望对您有所帮助!
关于npm - grunt unused - 循环目录中的子文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43915803/
我安装了 grunt 和 grunt cli,但仍然出现命令未找到错误 { "name": "angulartdd", "version": "1.0.0", "description":
我有一个使用“grunt-contrib-watch”和“grunt-exec”的 Grunt.js 文件,这是因为我想以一种独特的方式使用 handlebars 预编译器的一些自定义功能。 代码:
我正忙于尝试完成我正在运行的部署脚本。它可能有一半的时间有效,而且令人沮丧,因为我使用的大部分代码都不是我写的。我真的希望有一个我可以执行的较低级别的解决方法。 基本上发生的事情是我正在尝试执行 5
我想像在文档中定义的那样将参数传递给grunt-shell: module.exports = function(grunt) { // Configure Grunt grunt.initConfi
背景 我正在使用 Yeoman webapp 来搭建我的前端。 在 gruntfile 中,他们使用 grunt-rev 和 grunt-usemin Grunt-rev 将“修改”我的 Assets
我已经设置了grunt-eslint在我的 gruntfile.js 中,但是当我运行“grunt eslint”时,什么也没有发生。该任务看似即将开始,但 15 分钟后却停滞不前。 我的所有其他任务
我最近开始使用 grunt 做 JS 项目。 我有一个名为“grunt-contrib-jasmine”的插件用于 Jasmine 测试。我工作得很好,但我无法在浏览器中通过 specrunner 运
谁能告诉我这里做错了什么(我是 grunt 的新手)一个大学给我提供了一个基本的 gruntfile 设置 我已经安装了 node、js 和 grunt,但我不知道如何安装各种包(uglify、con
我正在尝试使用 grunt-contrib-watch和 grunt-rsync将任何文件更改上传到我的开发服务器。这是我的设置: var path = require('path'); module
尝试使用grunt-kill创建一个任务来终止我的 server-scorm 任务,并最终终止所有相关任务。这些说明非常短,因为它假设我知道有关 PID 文件的所有信息(我不知道,不是开发人员的错误)
我要么脑子一片空白,要么本该更复杂。 我正在尝试从 Grunt 任务运行 grunt-init,如下所示: grunt.registerTask('init', 'Scaffold various a
我有一个从玩家发射的射弹预制件,当它与“边界”碰撞时,它应该摧毁自己,当它击中“咕噜声”时,它应该摧毁自己和咕噜声。但是,当它碰到边界时,它会破坏自身和边界的对撞机。我创建了一个自定义标签脚本,允许我
module.exports = function(grunt){ grunt.initConfig({ pkg: grunt.file.readJSON('package.json'),
我已经加入了一个非营利性开源项目,想帮点忙,但我对 Grunt 不熟悉。我做了一些研究,但无法弄清楚为什么配置不起作用。 这是我正在尝试使用的插件。它允许应用多个后处理器,但我现在只需要 Autopr
下面的代码读取app/modules/中的每个子目录js的内容(例如app/modules/module1/js/, app/modules/module2/js/, aso.) 此脚本在不使用最后一
我正在尝试使用 grunt-exec 运行一个 javascript 测试运行程序,并传入一个已部署的链接变量。 我尝试通过使用 exec:setLink 设置环境变量 grunt.option('l
当我使用 grunt-contrib-watch 更改我的 js 文件时,我试图让 Grunt 重新加载它们。这是我的 Gruntfile: module.exports = function(gru
所以我的意思是: grunt.registerTask('default', ['default']); // CLI: grunt grunt.registerTask('serve', ['ser
我想创建一个通用的顶级 Gruntfile.js,配置为监视较少的文件更改。当less文件发生变化时,我想将其编译为css,然后在浏览器中实时加载css文件。我的功能正常,但我必须为每个项目复制 Gr
我正在使用 grunt-xmlpoke 更新 xml 文件。 xml 文件的路径作为参数提供。问题是文件部分中的第一个 WebConfigPath (键)被视为字符串。它更新了我的 xml 文件的本地
我是一名优秀的程序员,十分优秀!