Maybe I did not understand something (most likely it is), but I still could not complete the following task:

There is a directory / src / js In it (without any nested directories) are .js files corresponding to different pages. The name of each of them starts with the name of the page (ie, for a single script of the services.php page, there will be a services.js script) Almost all of these scripts use jQuery. Therefore, to restore order in the final version, it was necessary to add one file ( jquery.min.js ) to the beginning of each file from the input stream ( ./src/js/ .js *). It was not possible to do this. So how can this (add an arbitrary file or several to the beginning of each output) be implemented without having to manually describe the addresses of each source file and a whole mountain of unknown tricks related to this?

PS: a somewhat similar question in CSS: There is an office, specially prepared (unnecessary trash is removed, etc.) bootstrap.min.css The project is done using LESS (foo, well, okay). That is, first all the necessary .less files are compiled, then minified, giving candy to the output.

The problem is that css file in LESS is not so simple: a. if you connect it as css ( @import (css) "address"; ), then in the final CSS file there will be just a link to it (that is, the CSS import of the corresponding file will be assigned ) b. if you connect it as less ( @import (less) "blablabla"; ), then errors begin to pour, because it is not only not LESS, so also minimized. There was an idea to screen all this, enclosing the entire contents of the renamed bootstrap.min.less into ~ "css-code, which is not checked by the preprocessor at all, but is immediately splashed into the output file" , however, this was not possible, due to the abundance in the mentioned as single and double quotes.

Therefore, a similar question: how to each of the received css files (one css file is obtained per page with the exception of bootstrap), put the contents of some file ( bootstrap.min.css ) at the beginning?

  • You did not think to combine all files into one and switch on all pages, no one canceled caching in browsers ... - Alexey Lemesh
  • In fact, you don't need to glue anything together. All you need to do is plug in jquery with a separate <script ... > just above your scripts on those pages where you really need it. What you are trying to do is a monstrous crutch. - Dmitriy Simushev February
  • @DmitriySimushev, At the moment it is done this way: it connects via 2 js and CSS files ( jquery.min.js and everything_for current pages_in_single.min.js , and also, bootstrap.min.js and all_for_current_systems_in_minom.css ). By the way, why is the crutch in an attempt to merge all the scripts for the current page together? -Tk, this is in this case only a single jquery, and sometimes, third-party scripts with a dozen or two (moreover, for each of the pages - in different ways), which turns into some kind of terrible dump :( However, moment with a monstrous crutch, I will consider - mastersam
  • @AlEX crutch in merging all libraries (even unused) into one script. This leads to a situation where you load a huge pack of JS code for each page, and caching at the HTTP level works only page by page, i.e. you cannot cache jQuery only. In general, there are convenient tools (like browserify) that allow you to merge only those scripts that are really needed. However, in this case, you will most likely have to adapt your entire JS code. - Dmitriy Simushev
  • @AlEX will now prepare a detailed response) - Dmitriy Simushev

2 answers 2

Small lyrical digression

The approach with combining all the necessary JS libraries into one file together with the scripts using them has both advantages and disadvantages.

Benefits of combining:

  • You do not need to write the tag <script> in the HTML code of the pages.
  • You do not need to worry that some library has been updated / added / deleted and you forgot to change / add / delete the corresponding <script> .
  • Browsers have restrictions on the number of simultaneously open connections. Therefore, if you really have a lot of libraries, then downloading one large file may be more efficient than a lot of small ones. This is due to the overhead of opening / reusing connections.

The disadvantages of this approach are quite obvious:

  • You cannot use caching of individual libraries at the level of HTTP requests.
  • You cannot use CDN to download third-party libraries.
  • You need a layer of assembly, which will deal with the "gluing" libraries.
  • You need to remember that when adding a dependency to your JS code, you will need to edit the build scripts (of course, if you do not use Browserify or analogs).

In general, there is nothing terrible in gluing libraries, but only if you glue the necessary for a particular library page, and not all at once.

To solve such a problem, tools such as Browserify (which, by the way, integrates well with Gulp) are very often used. Such tools can analyze your code, and generate an assembly that includes only the necessary libraries and modules for its work. The only problem is that to use Browserify you will most likely have to change your approach to writing JavaScript code.


Now for your specific problem.

In the gulp ecosystem there are a large number of various plug-ins. One such plugin is gulp-header . This plugin allows you to insert arbitrary content at the beginning of each file in the stream. And you can use this plugin, for example, like this:

 var fs = require('fs'), gulp = require('gulp'), header = require('gulp-header'); gulp.task('default', function() { return gulp.src('./src/*.js') .pipe(header(fs.readFileSync('./libs/jquery.js') + "\n")) .pipe(gulp.dest('./dist')); }); 

    Something like this ...

     gulp.task('build', function() { var fs = require('fs'); fs.readdir('/src/', function(err, items) { console.log(items); for (var i=0; i<items.length; i++) { if(/^(.*)\.js$/.test(items[i])) { gulp.src(['jquery.min.js', items[i]])... и т.д. } } }); }); 

    But in my opinion, splitting together is not the best option ...

    • It will not work properly in combination with other gulp tasks. You do not use the reverse function (as well as other means) to indicate that the default task is complete. - Dmitriy Simushev
    • @ Dmitriy-simushev, where did you see my "task" default ? - Alexey Lemesh
    • I am sorry, I meant build . Everything else from the comment above is fair. - Dmitriy Simushev