I have a backbone app with over 50 small JavaScript files. Now I want to put all those in one single file, but it should still be readable, so:
Is there a tool for combining JavaScript files without minifying or uglyfying them?
cat (standard on UNIX-like systems).
cat foo.js bar.js > combined.js
You may run into problems if you have any scripts that do not end with a new line while depending on semi-colon insertion for that line.
Related
In site optimization and after testing its speed on pingdom and others it says to combine external JavaScript files. How can I combine them?
Here are the following files which it says to combine, but I have no idea how to combine them.
There are 2 JavaScript files served from mc.yandex.ru. They should be combined into as few files as possible.
https://mc.yandex.ru/metrika/tag.js
https://mc.yandex.ru/watch/47716165/1?wmode=7&p ... 0%26%20Reviews%20in%20UAE%20%7C%20YallaMotor.com
There are 2 JavaScript files served from static.adsafeprotected.com. They should be combined into as few files as possible.
https://static.adsafeprotected.com/sca.17.4.95.js
https://static.adsafeprotected.com/skeleton.js
There are 2 JavaScript files served from www.gstatic.com. They should be combined into as few files as possible.
https://www.gstatic.com/firebasejs/4.10.1/firebase-app.js
https://www.gstatic.com/firebasejs/4.10.1/firebase-messaging.js
How can I combine them into one file?
Combine Javascript files
JavaScript can be combined by using predecessors. Gulp is one of the processor.
If using gulp, there is a package called gulp concat, it should be imported first, and we can simply concat multiple JavaScript files into one. So script file will be one.
See this question about gulp: Using Gulp to Concatenate and Uglify files .
Steps are very simple
1) Import the gulp
2) Add the files
3) Add the destination in the .dest().
But you should download the js files, and add it to your local path.
I have a directory like below:
/folder/b.js
/folder/jQuery.js
/folder/a.js
/folder/sub/c.js
I want to minify all these js files in one js file in order:
jQuery.js -> a.js -> b.js -> c.js
Q:
1.How can I do it via grunt-contrib-uglify?(In fact, there are lots of files, it is impractical to specify all source filepaths individually)
2.btw, How can I get unminified files when debug and get minified single file when release and no need to change script tag in html(and how to write the script tag)?
Good questions!
1) Uglify will reorder the functions in the destination file so that function definitions are on top and function execution on bottom but it seems that it will preserve the order of the function executions.
This means that the function jQuery runs to define its global functions will be put first if you make sure jQuery is mentioned first in Uglify's config in the Gruntfile.
I use this config:
uglify: {
options: {
sourceMap: true
},
build: {
files: {
'public/all.min.js': ['public/js/vendor/jquery-1.10.2.min.js', 'public/js/*.js'],
}
}
}
2) I don't think there is one definite way to accomplish this. It depends on what web framework, templating framework and what kind of requirements you have. I use express + jade and in my main jade layout I have:
if process.env.NODE_ENV === 'production'
script(src='/all.min.js')
else
script(src='/js/vendor/jquery-1.10.2.min.js')
script(src='/js/someScript.js')
script(src='/js/otherScript.js')
In my package.json I have:
"scripts": {
"postinstall": "grunt"
},
This means that when I run npm install on deploy (on Heroku) grunt is run to minify/concat files and when the app is started with NODE_ENV=production the minified client side javascript is used. Locally I get served the original client side javascripts for easy debugging.
The two downsides are:
I have to keep the two lists of script files in sync (in the Gruntfile and in the layout.js) I solve this by using *.js in the Gruntfile but this may not suite everyone. You could put the list of javascripts in the Gruntfile and create a jade-template from this but it seems overkill for most projects.
If you don't trust your Grunt config you basically have to test running the application using NODE_ENV=production locally to verify that the minification worked the way you intended.
This can be done using the following Grunt tasks:
https://github.com/gruntjs/grunt-contrib-concat concatenates
files
https://github.com/gruntjs/grunt-contrib-uglify minifies
concatenated files
EDIT
I usually run all my files through a Grunt concatenation task using grunt-contrib-concat. Then I have another task to uglify the concatenated file using grunt-contrib-uglify.
You're probably not going to like this, but the best way is to define your js source files as AMD modules and use Requirejs to manage the order in which they load. The grunt-contrib-requirejs task will recurse your dependency tree and concatenate the js files in the necessary order into one big js file. You will then use uglify (actually r.js has uglify built-in) to minify the big file.
https://github.com/danheberden/yeoman-generator-requirejs has a good example gruntfile and template js files to work from.
EDIT
I've recently started using CommonJS modules instead of AMD since it's much closer to the ES6 module spec. You can achieve the same results (1 big complied+concatenated js file) by running commonjs modules through Browserify. There are plugins for both grunt and gulp to manage the task for you.
EDIT
I'd like to add that if your site is written using ES6 that Rollup is the best new concatenating package. In addition to bundling your files, it will also perform tree shaking, removing parts of libraries you use if included via an import statement. This reduces your codebase to just what you need without the bloat of code you'll never use.
I don't think you can do this with the uglify task alone, but you have a multitude of choices which might lead to your desired outcome.
A possible workflow would be first concatenating (grunt-contrib-concat) the files in order into one single file, and put this concatenated file through uglify. You can either define the order for concat in your Gruntfile, or you use on of those plugins:
First one would be https://github.com/yeoman/grunt-usemin, where you can specify the order in your HTML file, put some comments around your script block. The Google guys made it and it's pretty sweet to use.
Second one would be https://github.com/trek/grunt-neuter, where you can define some dependencies with require, but without the bulk of require.js. It requires changes in your JS code, so might not like it. I'd go with option one.
I ran into the same issue. A quick fix is just to change the filenames - I used 1.jquery.min.js, 2.bootstrap.min.js, etc.
This might be only remotely related to your question but I wanted something similar. Only my order was important in the following way:
I was loading all vendor files (angular, jquery, and their respective related plugins) with a wildcard (['vendor/**/*.js']). But some plugins had names that made them load before angular and jquery. A solution is to manually load them first.
['vendor/angular.js', 'vendor/jquery.js', 'vendor/**/*.js]
Luckily angular and jquery handle being loaded twice well enough. Edit: Although it's not really the best practice to load such large libraries twice, causing your minified file unnecessary bloat. (thanks #Kano for pointing this out!)
Another issue was client-js the order was important in a way that it required the main app file to be loaded last, after all its dependencies have been loaded. Solution to that was to exclude and then include:
['app/**/*.js', '!app/app.js', 'app/app.js']
This prevents app.js from being loaded along with all the other files, and only then includes it at the end.
Looks like the second part of your question is still unanswered. But let me try one by one.
Firstly you can join and uglify a large number of js files into one as explained by the concat answer earlier. It should also be possible to use https://github.com/gruntjs/grunt-contrib-uglify because it does seem to have wildcards. You may have to experiment with 'expand = true' option and wildcards. That takes care of your first question.
For the second part, say you joined and uglified into big-ugly.js
Now in your html you can add following directives:
<!-- build:js:dist big-ugly.js -->
<script src="js1.js"></script>
<script src="js2.js"></script>
<!-- etc etc -->
<script src="js100.js"></script>
<!-- /build -->
And then pass it through the grunt html preprocessor at https://www.npmjs.com/package/grunt-processhtml as part of your grunt jobs.
This preprocessor will replace the entire block with
<script src="big-ugly.js"></script>
Which means that the html file with be semantically equivalent - before and after the grunt jobs; i.e. if the page works correctly in the native form (for debugging) - then the transformed page must work correctly after the grunt - without requiring you to manually change any tags.
This was #1469's answer but he didn't make it clear why this works. Use concat to put all js files into one, this module does this in the order of file names, so I put a prefix to the file names based on orders. I believe it even has other options for ordering.
concat: {
js: {
options: {
block: true,
line: true,
stripBanners: true
},
files: {
'library/dist/js/scripts.js' : 'library/js/*.js',
}
}
},
Then use uglify to create the minified ugly version:
uglify: {
dist: {
files: {
'library/dist/js/scripts.min.js': [
'library/js/scripts.js'
]
},
options: {
}
}
},
If your problem was that you had vendors which needed to be loaded in order (let's say jquery before any jquery plugins). I solved it by putting jquery in its own folder called '!jquery', effectively putting it on top of the stack.
Then I just used concat as you normally would:
concat: {
options: {
separator: ';',
},
build: {
files: [
{
src: ['js/vendor/**/*.js', 'js/main.min.js'],
dest: 'js/global.min.js'
}
]
}
},
I'm writing an app that uses many JS files. Underscore, Backbone, jQuery, jQuery plugins for sliders, several files for models, routers, collections and views.
In my dev machine, I load every file separately, but in production I use only one JS file (minified, gziped, less http req, etc.).
In my build process, each file in minified with UglifyJS and then concat into prod.js. Is this the correct way to build that file? Or should I concat each file into prod.js and then minify with UglifyJS?
Thanks a lot!
I tested the output of each method using Gulp.
Test Setup
I used 9 JavaScript files totaling 19.15 kB when concatenated (not minified). Each file starts with a 'use strict'; statement.
Results:
Concatenate => Uglify: 7.993 kB
Uglify => Concatenate: 8.093 kB
Difference: 0.1 kB
Notes:
Concatenate => Uglify strips 8 of the 9 'use strict'; statements
Uglify => Concatenate preserves all 'use strict'; statements
A single 'use strict'; statement is 13 bytes. 8 × 13 bytes = 104 bytes, which accounts for the 0.1 kB difference.
Final Thoughts:
Use whichever order you prefer.
The difference between these two processes is negligible. Concatenate => Uglify could (theoretically) produce (barely noticeably) smaller files if both of the following are true:
Several of the individual files start with a 'use strict'; statement
There are many individual files
Here's the gulpfile.js I used:
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
var files = [
'!app/scripts/**/*Spec.js', // Exclude test files
'app/scripts/**/*.js'
];
// Register tasks
gulp.task('concat-min', function() {
return gulp.src(files)
.pipe(concat('script.min.js'))
.pipe(uglify())
.pipe(gulp.dest('dist'));
});
gulp.task('min-concat', function() {
return gulp.src(files)
.pipe(uglify())
.pipe(concat('script.min.js'))
.pipe(gulp.dest('dist'));
});
I'd be surprised if either way round made a significant difference to the overhead of a user's request.
I'd also suggest that concatenating all these frameworks into one file may actually increase the overhead for each user.
Why?
When using a popular/common framework such as jQuery etc. it makes sense to host it on a CDN, such as Google to benefit from caching the file - if a user's visited a website that also made use of jQuery they won't need to download it at all! Not to mention decreased geographic latency.
So, by creating your own unique file you're making it much more likely that the user will have to download the entire thing.
I would alway put them all into one then minify.
One thing i have started doing is to run it though http://www.javascriptobfuscator.com/ first i know it sounds count-intuitive but one of the things it does is store all string in an array ok an ugly array but stops string repetition then when you go to Your minified, i use Google Closure compiler it will then tidy the strings up and you often end up with a better minified file
I strongly recommend you use requirejs, using that lib you can make packages or one minimized and unified file. Please read the optimization tool.
However, as Widor told you, It's not a good idea join ALL the files into one. Many of those libs performs better using the google api (CDN) if you always will use your app online
It won't make much difference, since the toplevel statements (and variables &c.) aren't touched.
However, when using the --lift-vars option, it could change. It depends heavily on your code.
Order would not matter much assuming you have less globals floating around. There would be very minimal file size difference. My personal preference is to Concatenate and then Uglify which allows you to generate better and accurate sourcemaps rather than other way round. (This is because sourcemaps change with each transformation). I am wondering what is the purpose of uglifying smaller files and then concatenating. Basically, it is up to you and choice is yours. Concatenating and Uglifying seems more satisfactory and less error prone
I want to use the google closure compiler on the javascript source we're using.
In development mode we tend to break functionality to lots of files but for production would like to have them combined into modules.
When calling the compiler I can give it a list of files to include for compilation, but the output of that shows that the compiler did not save the order of the files list.
I searched about it and found that I can use goog.provide/good.require in order to control the dependencies between the different js files.
The problem with that is that it adds code to my js which I just don't need or want, for example:
goog.provide("mainFile")
will add this:
var mainFile = {};
to the compiled js file, something that I don't want.
We're not using the google closure library at all, all I want to use is the compiler.
Is there a way to tell the compiler the order of the files without including more "closure library" functionality which I have no need for?
I can of course create a tool of my own which will first take all the files, combine them into one which will then be the input of the compiler, but I would prefer to void that if it can be done by the compiler itself.
Edit
The goal is to be able to produce modules like the answer in this thread: Using the --module option in Closure Compiler to create multiple output files
And so I want to add to that the ability to control which files go into which module while also having control on their order.
For now I don't use wildcards, but I plan to do so in the future (if it's possible).
simply "cat file1.js file2.js > combined.js && compile..." is fine, but in our case it's a bit more complicated and we'll have to write a program/script that does that based on some logic.
If we can somehow tell the compiler the order of the files in advanced it might just save the time of implementing such a program.
Thanks.
Closure-compiler's ability to create multiple output files provides a powerful tool to separate input files into distinct output chunks. It is designed such that different chunks can be loaded at differing times depending on the features required. There are multiple compiler flags pertaining to chunks.
Each use of the --chunk flag describes an output file and it's dependencies. Each chunk flag follows the following syntax:
--js inputfile.js
--chunk name:num_files:dependency
The resulting output file will be name.js and includes the files specified by the preceding --js flag(s).
The dependency option is what you will be most interested in. It specifies what the parent chunk is. The chunk options must describe a valid dependency tree (you must have a base chunk).
Here's an example:
--js commonfunctions.js
--chunk common:1
--js page1functions.js
--js page1events.js
--chunk page1:2:common
--js page2function.js
--chunk page2:1:common
--js page1addons.js
--chunk page1addons:1:page1
In this case, you are telling the compiler that the page1 and page2 chunks depend on the common chunk and that the page1addons chunk depends on the page1 chunk.
Keep in mind that the compiler can and does move code from one chunk into other chunk output files if it determines that it is only used by that chunk.
None of this requires closure-library or the use of goog.require/provide calls nor does it add any code to your output. If you want the compiler to determine dependencies automatically or to be able to manage those dependencies for you, you'll need to use a module format such as CommonJS, ES2015 modules or goog.require/provide/module calls.
Update Note: Prior to the 20180610 version, the chunk flags were named module. They were renamed to reduce confusion with proper JS modules. The answer has been updated to reflect the new names.
Update Note 2: There is now a utility to automatically calculate and generate these flags for you: https://github.com/ChadKillingsworth/closure-calculate-chunks
You can also set the output path, for example with:
--module_output_path_prefix ./public/js/
See also:
Using the --module option in Closure Compiler to create multiple output files
I have a shell script that collects all the .js files on a page and concats them to be compiled using the closure compiler. However, I don't want a specific js file to optimized any via the compiler. For example, I have the command to compile fileA.js, fileB.js, and fileC.js. How do I notate to skip fileB.js but still place it in the output file scripts.min.js in the correct order? So, fileA.js and fileC.js would be optimized using SIMPLE_OPTIMIZATION and fileB.js wouldn't be touched. Is there a keyword I can place in the comments of the file itself that says, skip this file?
java -jar compiler.jar --js=fileA.js --js=fileB.js --js=fileC.js --js_output_file=scripts.min.js
If I understand your intent here, you may consider processing each file that you want to minify separately, then performing the concatenation as a separate step. In pseudo-code:
minify fileA.js
minify fileC.js
cat fileA.js fileB.js fileC.js >scripts.min.js
There is no keyword that you can place in any scope to say "ignore me". nullptr has the right suggestion. In our project we have created some simple preprocessing comments and use them to control the flow. However, you can only ignore and include a file before the minified code or after the minified code if you want to do it in one pass. So, nullptr's solution is the only one. Remember to use extern files so variable renaming (and not renaming) works properly.