简体   繁体   English

Gulp - 如何使用gulp-concat控制处理顺序

[英]Gulp - How do I control processing order with gulp-concat

I'm trying to generate combined JavaScript and CSS resources into a single file using gulp-concat using something like this: 我正在尝试使用gulp-concat将组合的JavaScript和CSS资源生成到单个文件中,使用以下内容:

var concatjs = gulp
    .src(['app/js/app.js','app/js/*Controller.js', 'app/js/*Service.js'])
    .pipe(concat('app.js'))
    .pipe(gulp.dest('build'));

I get a concatted file with this, but the order of the javascript files embedded in the combined output file is random - in this case the controllers are showing up before the initial app.js file, which causes problems when trying to load the Angular app that expects app.js before any of the related resources are loaded. 我得到一个带有这个的连接文件,但是组合输出文件中嵌入的javascript文件的顺序是随机的 - 在这种情况下,控制器在初始app.js文件之前显示,这在尝试加载Angular应用程序时会导致问题在加载任何相关资源之前需要app.js。 Likewise for CSS resources that get combined end up in random order, and again the order is somewhat important - ie. 同样地,对于最终以随机顺序组合的CSS资源,并且顺序再次有点重要 - 即。 bootstrap needs to load before the theme and any custom style sheets. bootstrap需要在主题和任何自定义样式表之前加载。

How can I set up the concatenation process so that the order remains intact? 如何设置连接过程以使订单保持不变?

Update So it turns out the ordering above DOES actually work by explicitly specifying the file order in the array of file specs. 更新因此事实证明, DOES上面的排序实际上是通过在文件规范数组中明确指定文件顺序来实现的。 So in this case the crucial thing is to list app/js/app.js first, then let the rest of the scripts where order doesn't matter in in any order. 所以在这种情况下,关键是首先列出app / js / app.js,然后让其余的脚本以任何顺序无关紧要。

The reason I failed to see this behavior (Duh!) is that Gulp Watch was running and the gulpfile.js update wasn't actually reflected in the output. 我没有看到这种行为(Duh!)的原因是Gulp Watch正在运行并且gulpfile.js更新实际上没有反映在输出中。 Restarting gulp did update the script. 重新启动gulp确实更新了脚本。 Neophyte error... 新手错误......

Other Thoughts: Still wondering though - is this the right place to specify build order? 其他想法:但仍然想知道 - 这是指定构建顺序的正确位置吗? It seems you're now stuffing application logic (load order) into the build script, which doesn't feel right. 现在看来你正在将应用程序逻辑(加载顺序)填充到构建脚本中,这感觉不对。 Are there other approaches to address this? 还有其他方法可以解决这个问题吗?

For an angular application like the one in your example (and it's dependency management), I normally use this kind of syntax: gulp.src(['app\\js\\app.js', 'app\\js\\**\\*.js']) . 对于像您的示例中的角度应用程序(以及它的依赖关系管理),我通常使用这种语法: gulp.src(['app\\js\\app.js', 'app\\js\\**\\*.js'])

You can also use just gulp.src('app\\js\\**\\*.js') if your app.js file is the first one in alphabetic order. 如果你的app.js文件是第一个按字母顺序排列的文件,你也可以使用gulp.src('app\\js\\**\\*.js')

I see your point about moving the load file order into the build script: I had the same feeling till I started using gulp-inject for injecting the unminified files references in my index.html at development time and injecting the bundled, minified and versioned ones in the production index file. 我看到了关于将加载文件顺序移动到构建脚本中的观点:我有同样的感觉,直到我开始使用gulp -inject在开发时注入index.html中的未分隔文件引用并注入捆绑,缩小和版本化的文件在生产索引文件中。 Using that glob ordering solution across all my development cycle made so sense to me that i don't think to it anymore. 在我的所有开发周期中使用该glob排序解决方案对我来说非常有意义,我不再考虑它了。

Finally, a possible solution for this 'ordering smell' can be using browserify but to me it is just complicating the architecture for an angular application: in the end, as you said, you just need that one specific file is called before all the other ones. 最后,这种“排序气味”的可能解决方案可能是使用browserify,但对我而言,它只是使角度应用程序的架构变得复杂:最后,正如您所说,您只需要在所有其他文件之前调用一个特定文件那些。

For my js i use a particular structure/naming convention which helps. 对于我的js,我使用特定的结构/命名约定,这有助于。 I split it up into directories by feature, where each 'feature' is then treated as a separate encapsulated module. 我按功能将其拆分为目录,然后将每个“功能”视为单独的封装模块。

So for my projects i have, 所以对于我的项目,

app/js/

    - app.js
    - app.routes.js
    - app.config.js

    /core/

        - core.js
        - core.controllers.js
        - core.services.js

        /test/

           - .spec.js test files for module here

    /feature1/

        - feature1.js
        - feature1.controllers.js

    /feature2/

        - feature2.js
        - feature2.controllers.js

    ...

So each directory has a file of the same name that simply has the initial module definition in it, which is all that app.js has in it for the whole app. 因此,每个目录都有一个同名的文件,其中只包含初始模块定义,这就是app.js为整个应用程序提供的所有内容。 So for feature1.js 因此对于feature1.js

angular.module('feature1', [])

and then subsequent files in the module retrieve the module and add things (controllers/services/factories etc) to it. 然后模块中的后续文件检索模块并向其添加内容(控制器/服务/工厂等)。

angular.module('feature1')
       .controller(....)


Anyway, i'll get to the point... 无论如何,我会明白......

As i have a predefined structure and know that a specific file has to go first for each module, i'm able to use the function below to sort everything into order before it gets processed by gulp. 由于我有一个预定义的结构,并且知道每个模块必须首先使用特定文件,因此我可以使用下面的函数在gulp处理之前将所有内容按顺序排序。

This function depends on npm install file and npm install path 此功能取决于npm install filenpm install path

function getModules(src, app, ignore) {

    var modules = [];

    file.walkSync(src, function(dirPath, dirs, files) {

        if(files.length < 1)
            return;

        var dir = path.basename(dirPath)
            module;

        if(ignore.indexOf(dir) === -1) {
            module = dirPath === src ? app : dir;

            files = files.sort(function(a, b) {
                return path.basename(a, '.js') === module ? -1 : 1;
            })
            .filter(function(value) {
                return value.indexOf('.') !== 0;
            })
            .map(function(value) {
                return path.join(dirPath, value);
            })

            modules = modules.concat(files);
        }
    })

    return modules;
}

It walks the directory structure passed to it, takes the files from each directory (or module) and sorts them into the correct order, ensuring that the module definition file is always first. 它遍历传递给它的目录结构,从每个目录(或模块)获取文件并将它们排序到正确的顺序,确保模块定义文件始终是第一个。 It also ignores any directories that appear in the 'ignore' array and removes any hidden files that begin with '.' 它还会忽略“ignore”数组中出现的任何目录,并删除任何以“。”开头的隐藏文件。

Usage would be, 用法是,

getModules(src, appName, ignoreDirs);
  • src is the dir you want to recurse from src是你要递归的目录
  • appName is the name of your app.js file - so 'app' appName是app.js文件的名称 - 所以'app'
  • ignoreDirs is an array of directory names you'd like to ignore ignoreDirs是您要忽略的目录名数组

so 所以

getModules('app/js', 'app', ['test']);

And it returns an array of all the files in your app in the correct order, which you could then use like: 它会以正确的顺序返回应用程序中所有文件的数组,然后您可以使用它们:

gulp.task('scripts', function() {
    var modules = getModules('app/js', 'app', ['test']);

    return gulp.src(modules)
               .pipe(concat('app.js'))
               .pipe(gulp.dest('build'));
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM