- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Grunt 生成构建。我是 Grunt、javascript 和 nodejs 的新手,所以欢迎任何新观点。
我的 Gruntfile 中的一些任务依赖于插件(例如用于 javascript 缩小的“uglify”),而还有一些其他工作流最适合自己编写 javascript 函数。
我一直遇到需要执行以下操作的情况:(1) 执行一个 javascript 函数 (2) 在该函数之后立即运行一个 grunt 任务 (3) 执行另一个 javascript 函数。它需要按照这个顺序发生。然而,由于 Grunt 只是一个任务调度程序,它最终会运行 (1)、排队 (2)、运行 (3),然后在 (1) 和 (3) 完成后运行 (2) 作为最后一步。
以下是假设的自定义任务的一个非常简单的用例,以更好地解释情况。
grunt.task.registerTask('minifyJS', function() {
jsFilepathMapping = configureUglifiy();
/** note - configureUglify is needed because the minification filepaths
are generated on the fly, I do not know them before the script runs
and more than that, there are so many that it would be really bulky
to create init targets for each single minification file that needs
to be generated.*/
grunt.task.run('uglify');
updateJsScriptTags(jsFilepathMapping); // update the <script> tags in my HTML
});
问题是我需要按照上面显示的顺序运行这些东西。但是,由于 grunt 是一个任务调度程序,因此当此任务运行时会发生以下情况
现在,我明白了为什么会这样。 Grunt 是一个任务调度器——任务正在排队。这是有道理的,而不是提示它。 相反,我想问的是解决这个问题的方法是什么?这样我就可以在使用这种功能和任务组合时实现这种排序?我想这一定非常简单和常见,我只是不知道它是什么!
我意识到的一个选择是将这些函数中的每一个转换为任务本身。然而,这个问题是 configureUglifiy() 返回一个复杂的数据结构,然后 updateJsScriptTags() 使用它。除了使用“选项”属性外,似乎没有在 Grunt 任务之间共享数据的好方法,该属性仅在任务本身内可用。我想我可以这样做,但是,我担心的是这会使事情变得不可读并且......有点危险,因为你现在有这个任务,它依赖于在另一个任务期间修改的数据结构,而且不是立即显而易见,直到您开始深入研究该功能。
我举个例子。哪个对您来说更具可读性?
/**
documentation which defines what the argment filepathMapping is
Furthermore, since the function takes an argument, the context is
immediately clearer just looking at the function declaration.
*/
function updateJsScriptTags(filepathMapping) {
// do stuff ...
for ( key in filepathMapping ) { // oh cool! i know what this arg does, my documentation nicely explains it, and its structure too
// lots of stuff
}
}
...
// and elsewhere in the script, where it's being invoked:
var aMapping = someFunc();
updateJsScriptTags(aMapping);
对比
grunt.task.registerTask('updateJsScriptTags', 'update js tags', function() {
// do stuff.
...
// many lines later:
grunt.options('filepathMapping') // Oh, what is this attribute? Let me go look around the rest of the script to find out where it comes from
}
...
// and ultimately, where it's being invoked.
grunt.task.run('someTask'); // global options param gets modified somewhere in here, but you'd never know it looking at this line of code
grunt.task.run('updateJsScriptTags'); // this task will depend on that modification
我发现这让事情变得更难读,而不是一个简单的函数,它接受要使用的参数,并可以强加一个特定的结构。事情似乎也更容易以另一种方式出现问题,即我在一个任务中修改某些全局参数中的一堆属性,这些属性稍后会在另一个任务中使用。更麻烦的是,属性名称是共享的,是硬编码的。我知道这是一个非常简单的用例,但开始想象一组更复杂的函数,这些函数依赖于可能是复杂数据类型的多个参数,并且这是我关心的地方。
作为一个简短的总结:是否有替代方法来实现函数/插件任务/函数/插件任务的顺序排序,而不求助于将函数本身转换为自定义任务?
最佳答案
So as a quick summary: are there alternatives to achieving a sequential ordering of function/plugin-task/function/plugin-task, without resorting to converting the functions to custom tasks themselves?
简短回答:不,要保持执行顺序,您需要使用 grunt Tasks 而不是普通的 JavaScript 函数来定义顺序。
顺序排序是按每个alias-task的顺序进行的在 taskList
中定义大批。例如当使用 grunt.registerTask
时:
grunt.registerTask('foo', [ 'a', 'b', 'c' ]);
给出上面的伪示例并运行 foo
任务将运行任务 a
首先,其次是任务 b
,依此类推(即任务b
将在任务a
完成之前运行;任务c
将在任务b
完成之前运行)。
然而,这并不意味着不能将纯 JavaScript 函数与 grunt custom Tasks 结合使用。 .
带解决方案的长答案:
There does not seem to be a great way to share data between Grunt tasks...
您可以使用 Object
来存储数据。第一个示例中的伪代码意味着您想要 configureUglifiy
功能:
Uglify
任务Object
生成的数据( configureUglifiy
)本身。updateJsScriptTags
功能。所以,不是返回 Object
来自 configureUglifiy
功能。您可以将其存储在另一个 Object
中,随后在 updateJsScriptTags
中访问功能。
在下面的要点中,请注意 shared
对象,具有名为 jsFilepathMapping
的属性/键.我们将使用这个对象来存储动态生成的数据,这些数据可以在另一个任务中访问。
Gruntfile.js (伪代码)
module.exports = function (grunt) {
'use strict';
var shared = {
jsFilepathMapping: {} // <-- Intentionally empty. The object will
// be defined via `configureUglify` function,
// and consumed by `updateJsScriptTags` Task.
};
grunt.initConfig({
uglify: {
// <-- Intentionally empty, will be dynamically generated.
}
});
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
/**
* Helper function to dynamically configure the uglify task.
*/
function configureUglify() {
// <-- Do stuff here to determine configuration of uglify task.
grunt.config('uglify', config);
// Store object (for referencing later) instead of returning.
shared.jsFilepathMapping = config;
};
/**
* Helper function to update the js script tags in html.
*/
function updateJsScriptTags(filepathMapping) {
// `filepathMapping` object now available in this function.
for ( var key in filepathMapping ) {
console.log(filepathMapping[key])
}
}
//---------------------------------------------------------------------------
// Tasks
//---------------------------------------------------------------------------
grunt.task.registerTask('updateJsScriptTags', 'Updates tags', function () {
// Invoke the function passing in the values which were previously
// ascertained and set via the `configureUglify` function.
updateJsScriptTags(shared.jsFilepathMapping)
});
grunt.task.registerTask('minifyJS', function() {
configureUglify();
grunt.task.run(['uglify']);
});
grunt.loadNpmTasks('grunt-contrib-uglify');
// Define sequential ordering of each Task in the taskList Array.
grunt.registerTask('default', ['minifyJS', 'updateJsScriptTags']);
};
注意 注释为// <-- Do stuff here to determine configuration of uglify task.
将是类似于我提供给您的其他问题的 Gruntfile.js 要点的逻辑 here .
总结
TaskList
来定义顺序排序数组(按照上面的简短回答部分)当一个任务/功能动态获取数据以在其他任务/功能之间共享时,考虑将其存储在 Object
中而不是使用 return
从函数返回值关键字。
尽可能将逻辑分成单独定义的任务,并尽量避免在一个任务中做太多事情。例如,在您在名为 minifyJS
的问题中提供的第一个自定义任务中你试图在一个任务中做两件事。 IE。您正在配置和运行您的 uglify 任务(构成一个任务),并且还更新 JS 脚本标签(构成另一个任务)。理想情况下,这应该是两个独立的不同任务。
伪Gruntfile.js
我提供(以上)它目前没有采纳我在第 2 点和第 4 点中给出的建议。通过一些重构 Gruntfile.js
会更像这样(注意函数不再存在,取而代之的是它们的逻辑已经与调用它们的自定义任务相结合):
Gruntfile.js (伪代码重构)
module.exports = function (grunt) {
'use strict';
var shared = {
jsFilepathMapping: {} // <-- Intentionally empty. The object will
// be defined via `minifyJS` Task,
// and consumed by `updateJsScriptTags` Task.
};
grunt.initConfig({
uglify: {
// <-- Intentionally empty, will be dynamically generated.
}
});
//---------------------------------------------------------------------------
// Tasks
//---------------------------------------------------------------------------
grunt.task.registerTask('updateJsScriptTags', 'Updates tags', function () {
// `filepathMapping` object now available in this task.
for ( var key in shared.jsFilepathMapping ) {
console.log(shared.jsFilepathMapping[key])
}
});
grunt.task.registerTask('minifyJS', function() {
// <-- Do stuff here to determine configuration of uglify task.
// Save object (for referencing later) instead of returning.
shared.jsFilepathMapping = config;
grunt.config('uglify', config);
grunt.task.run(['uglify']);
});
grunt.loadNpmTasks('grunt-contrib-uglify');
// Define sequential ordering of each Task in the taskList Array.
grunt.registerTask('default', ['minifyJS', 'updateJsScriptTags']);
};
关于javascript - 按顺序 Grunt : How to run a function and then a task and then another function,,当功能不能拆分到不同的任务时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47370561/
我是一名优秀的程序员,十分优秀!